398 lines
7.9 KiB
Markdown
398 lines
7.9 KiB
Markdown
# WZ Data Export Utility Guide
|
|
|
|
## Overview
|
|
|
|
The Elixir port uses JSON files for game data instead of parsing WZ files directly. This document describes how to create a Java utility to export WZ data to JSON format.
|
|
|
|
## Required Exports
|
|
|
|
### 1. Item Strings (`priv/data/item_strings.json`)
|
|
|
|
```json
|
|
{
|
|
"2000000": "Red Potion",
|
|
"2000001": "Orange Potion",
|
|
"1002000": "Blue Bandana",
|
|
...
|
|
}
|
|
```
|
|
|
|
**Java Source:**
|
|
```java
|
|
// Use MapleItemInformationProvider
|
|
// Iterate over all items, extract names from String.wz
|
|
```
|
|
|
|
### 2. Items (`priv/data/items.json`)
|
|
|
|
```json
|
|
[
|
|
{
|
|
"item_id": 2000000,
|
|
"name": "Red Potion",
|
|
"slot_max": 100,
|
|
"price": 50.0,
|
|
"whole_price": 50,
|
|
"req_level": 0,
|
|
"tradeable": true,
|
|
"cash": false,
|
|
"recover_hp": 50,
|
|
"recover_mp": 0
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
**Fields to Export:**
|
|
- item_id, name, desc
|
|
- slot_max, price, whole_price
|
|
- req_level, req_job, req_str, req_dex, req_int, req_luk
|
|
- cash, tradeable, quest, time_limited
|
|
- recover_hp, recover_mp, buff_time
|
|
- meso, monster_book, mob_id
|
|
- All flags and properties
|
|
|
|
**Java Source:**
|
|
```java
|
|
// MapleItemInformationProvider.getAllItems()
|
|
// Convert ItemInformation to JSON
|
|
```
|
|
|
|
### 3. Equipment (`priv/data/equips.json`)
|
|
|
|
```json
|
|
[
|
|
{
|
|
"item_id": 1002000,
|
|
"str": 0,
|
|
"dex": 0,
|
|
"int": 0,
|
|
"luk": 0,
|
|
"hp": 0,
|
|
"mp": 0,
|
|
"watk": 0,
|
|
"matk": 0,
|
|
"wdef": 5,
|
|
"mdef": 5,
|
|
"acc": 0,
|
|
"avoid": 0,
|
|
"speed": 0,
|
|
"jump": 0,
|
|
"slots": 7,
|
|
"tuc": 7,
|
|
"item_level": 1
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
**Fields to Export:**
|
|
- All stat fields (str, dex, int, luk, hp, mp)
|
|
- Attack/defense (watk, matk, wdef, mdef)
|
|
- Accuracy/avoidance (acc, avoid)
|
|
- Movement (speed, jump)
|
|
- Upgrade slots (slots, tuc)
|
|
- All equipment properties
|
|
|
|
**Java Source:**
|
|
```java
|
|
// MapleItemInformationProvider.getAllItems()
|
|
// Filter by MapleInventoryType.EQUIP
|
|
// Extract equip stats
|
|
```
|
|
|
|
### 4. Monsters (`priv/data/monsters.json`)
|
|
|
|
```json
|
|
[
|
|
{
|
|
"mob_id": 100100,
|
|
"name": "Blue Snail",
|
|
"level": 1,
|
|
"hp": 50,
|
|
"mp": 0,
|
|
"exp": 3,
|
|
"physical_attack": 8,
|
|
"magic_attack": 8,
|
|
"physical_defense": 10,
|
|
"magic_defense": 10,
|
|
"accuracy": 5,
|
|
"evasion": 3,
|
|
"speed": 50,
|
|
"boss": false,
|
|
"undead": false,
|
|
"flying": false,
|
|
"skills": [],
|
|
"revives": []
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
**Fields to Export:**
|
|
- All stats from MapleMonsterStats
|
|
- Behavioral flags (boss, undead, flying, friendly, etc.)
|
|
- Skills, revives
|
|
- All combat properties
|
|
|
|
**Java Source:**
|
|
```java
|
|
// MapleLifeFactory.getAllMonster()
|
|
// Convert MapleMonsterStats to JSON
|
|
```
|
|
|
|
### 5. NPCs (`priv/data/npcs.json`)
|
|
|
|
```json
|
|
[
|
|
{
|
|
"npc_id": 1012000,
|
|
"name": "Athena Pierce",
|
|
"has_shop": false,
|
|
"shop_id": null,
|
|
"script": null
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
**Java Source:**
|
|
```java
|
|
// MapleLifeFactory.getAllNPC()
|
|
// MapleNPC.npcShopIDs for shop data
|
|
```
|
|
|
|
### 6. Maps (`priv/data/maps.json`)
|
|
|
|
```json
|
|
[
|
|
{
|
|
"map_id": 100000000,
|
|
"map_name": "Henesys",
|
|
"street_name": "Victoria Island",
|
|
"return_map": 100000000,
|
|
"forced_return": 100000000,
|
|
"mob_rate": 1.0,
|
|
"field_limit": 0,
|
|
"time_limit": -1,
|
|
"bgm": "Bgm04/PlayWithMe",
|
|
"portals": [
|
|
{
|
|
"id": 0,
|
|
"name": "sp",
|
|
"type": "sp",
|
|
"x": -1283,
|
|
"y": 86,
|
|
"target_map": 999999999,
|
|
"target_portal": "",
|
|
"script": null
|
|
},
|
|
{
|
|
"id": 1,
|
|
"name": "market00",
|
|
"type": "pv",
|
|
"x": -1183,
|
|
"y": 86,
|
|
"target_map": 910000000,
|
|
"target_portal": "market01",
|
|
"script": null
|
|
}
|
|
],
|
|
"footholds": [
|
|
{
|
|
"id": 1,
|
|
"x1": -1400,
|
|
"y1": 120,
|
|
"x2": -1200,
|
|
"y2": 120,
|
|
"prev": 0,
|
|
"next": 2
|
|
}
|
|
],
|
|
"top": -400,
|
|
"bottom": 300,
|
|
"left": -1600,
|
|
"right": 1200
|
|
},
|
|
...
|
|
]
|
|
```
|
|
|
|
**Fields to Export:**
|
|
- Map metadata (id, name, street_name)
|
|
- Return maps (return_map, forced_return)
|
|
- Rates (mob_rate, recovery_rate)
|
|
- Limits (field_limit, time_limit)
|
|
- All portals with full data
|
|
- All footholds with connections
|
|
- Bounds (top, bottom, left, right)
|
|
- BGM, scripts, properties
|
|
|
|
**Java Source:**
|
|
```java
|
|
// MapleMapFactory.loadAllFieldTemplates()
|
|
// FieldTemplate contains all data
|
|
// Extract portals from MaplePortal
|
|
// Extract footholds from MapleFootholdTree
|
|
```
|
|
|
|
## Implementation Guide
|
|
|
|
### Create Export Utility Class
|
|
|
|
```java
|
|
package tools;
|
|
|
|
import com.google.gson.Gson;
|
|
import com.google.gson.GsonBuilder;
|
|
import server.*;
|
|
import server.life.*;
|
|
import server.maps.*;
|
|
import java.io.*;
|
|
import java.nio.file.*;
|
|
import java.util.*;
|
|
|
|
public class WZExporter {
|
|
|
|
private static final Gson gson = new GsonBuilder()
|
|
.setPrettyPrinting()
|
|
.create();
|
|
|
|
private static final String OUTPUT_DIR = "../odinsea-elixir/priv/data/";
|
|
|
|
public static void main(String[] args) {
|
|
System.out.println("Starting WZ data export...");
|
|
|
|
exportItemStrings();
|
|
exportItems();
|
|
exportEquips();
|
|
exportMonsters();
|
|
exportNPCs();
|
|
exportMaps();
|
|
|
|
System.out.println("Export complete!");
|
|
}
|
|
|
|
private static void exportItemStrings() {
|
|
// Implementation here
|
|
}
|
|
|
|
private static void exportItems() {
|
|
// Implementation here
|
|
}
|
|
|
|
// ... other export methods
|
|
|
|
private static void writeJson(String filename, Object data) {
|
|
try {
|
|
Path path = Paths.get(OUTPUT_DIR + filename);
|
|
Files.createDirectories(path.getParent());
|
|
|
|
String json = gson.toJson(data);
|
|
Files.write(path, json.getBytes());
|
|
|
|
System.out.println("Wrote: " + filename);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Run Export
|
|
|
|
1. Add WZExporter.java to Java project
|
|
2. Ensure all providers are loaded (items, maps, life)
|
|
3. Run: `java tools.WZExporter`
|
|
4. Check output in `../odinsea-elixir/priv/data/`
|
|
5. Verify JSON files are valid
|
|
6. Test in Elixir by reloading data providers
|
|
|
|
## Data Validation
|
|
|
|
After export, validate data:
|
|
|
|
```elixir
|
|
# In Elixir IEx console
|
|
Odinsea.Game.ItemInfo.reload()
|
|
Odinsea.Game.MapFactory.reload()
|
|
Odinsea.Game.LifeFactory.reload()
|
|
|
|
# Check counts
|
|
:ets.info(:odinsea_item_cache, :size) # Should be 10000+
|
|
:ets.info(:odinsea_map_templates, :size) # Should be 1000+
|
|
:ets.info(:odinsea_monster_stats, :size) # Should be 5000+
|
|
|
|
# Test lookups
|
|
Odinsea.Game.ItemInfo.get_name(2000000) # "Red Potion"
|
|
Odinsea.Game.MapFactory.get_map_name(100000000) # "Henesys"
|
|
Odinsea.Game.LifeFactory.get_monster_name(100100) # "Blue Snail"
|
|
```
|
|
|
|
## Performance Considerations
|
|
|
|
- Export can take 5-10 minutes for full WZ data
|
|
- JSON files will be 50-100MB total
|
|
- Consider compressing (gzip) for distribution
|
|
- ETS loading takes <1 second with JSON
|
|
- Memory usage: ~100MB for all cached data
|
|
|
|
## Incremental Export
|
|
|
|
For development, export subsets:
|
|
|
|
```java
|
|
// Export only common maps
|
|
if (mapId < 110000000 && mapId >= 100000000) {
|
|
exportMap(mapId);
|
|
}
|
|
|
|
// Export only beginner monsters
|
|
if (mobId < 9999999 && level <= 30) {
|
|
exportMonster(mobId);
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
**Problem:** JSON parsing fails in Elixir
|
|
- Check JSON syntax with `jq` or online validator
|
|
- Ensure UTF-8 encoding
|
|
- Check for special characters in names
|
|
|
|
**Problem:** Missing data in exports
|
|
- Verify Java providers are fully initialized
|
|
- Check for null values
|
|
- Add default values in Java export code
|
|
|
|
**Problem:** Export crashes or hangs
|
|
- Add try/catch around each item
|
|
- Log progress every 100 items
|
|
- Export in smaller batches
|
|
|
|
## Future Improvements
|
|
|
|
1. **Incremental Updates**
|
|
- Track WZ file changes
|
|
- Only export modified data
|
|
- Generate diff files
|
|
|
|
2. **Validation**
|
|
- Schema validation
|
|
- Referential integrity checks
|
|
- Detect missing required fields
|
|
|
|
3. **Compression**
|
|
- GZIP JSON files
|
|
- Binary format (MessagePack)
|
|
- Reduce file sizes 80%
|
|
|
|
4. **Automation**
|
|
- CI/CD integration
|
|
- Auto-export on WZ updates
|
|
- Version tracking
|
|
|
|
---
|
|
|
|
**Next Step:** Create `WZExporter.java` in Java project and run export!
|