# 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!