Patterns
"Where Does X Live?" Cheat Sheet
The shortest distance from "I want to change this" to "this is the file I open".
I want to... Look in...
──────────────────────────────── ──────────────────────────────
add a new item dist/data/stats/items/*.xml
+ optional handler in
handler/itemhandlers/
add a new skill effect data/EnchantSkill*, SkillData
+ new EffectHandler entry
add a quest dist/data/scripts/quests/
+ register in QuestMasterHandler.java
change rates / drops dist/game/config/Rates.ini
change spawn locations dist/data/spawns/*.xml
touch packet structure gameserver/network/clientpackets
gameserver/network/serverpackets
ClientPackets / ServerPackets tables
add admin command dist/data/scripts/handlers/
chat/commands/admin/
+ dist/game/config/AdminCommands.xml
tweak siege / castle managers/Castle*Manager,
config/Siege.ini
alter login flow java/.../loginserver/
schema change dist/db_installer/*.sql
+ matching data/sql/*Table.java
chronicle-specific quirk ONLY inside that chronicle's
folder ─ never assume code is
shared with another era.
Common edit recipes
"I want to make my character an administrator"
- Create a character in-game and log out.
- Find your character's row in the
charactersSQL table. - Set the
accesslevelfield to100. - Log back in. Admin commands (
//) are now available.
"I want to add an admin command"
- Create a class under
dist/data/scripts/handlers/chat/commands/admin/implementingIAdminCommandHandler. Admin commands are scripts, compiled at boot by the in-process JDK compiler, they do not live in the core jar. - Declare which commands it handles in its
getCommandList()return. - Register it in
dist/data/scripts/handlers/MasterHandler.java: add the import (import handlers.chat.commands.admin.MyAdmin;) and addMyAdmin.class,to the admin command handler array. Without this, the class is compiled but never registered. - Add an entry in
dist/game/config/AdminCommands.xmlspecifying the minimum access level (and optionallyconfirmDlg="true"for destructive actions). - Restart or
//reload handlerto re-runMasterHandlerand pick up the new script, then run it in-game with//yourcommand.
"I want to change a config value at runtime"
You usually cannot, most config is read once at boot into typed fields. A handful of values (//reload config targets) support hot reload; the rest need a restart.
"I want to add a new item that does X"
- Define the item in
dist/data/stats/items/*.xml. Pick a free ID, set name, type, weight, stats. - If "X" is more than a stat change, add a handler in
handler/itemhandlers/implementingIItemHandler. - Reference the handler by name in the XML (
handler="MyNewItem"). - Restart the server. The item appears in the world; admin-spawn it to test.
"I want to change spawn locations"
- Find the right XML under
dist/data/spawns/(organized by region / boss / instance). - Edit coords / respawn delay / amount.
- Restart. Some spawn groups can be reloaded via admin commands, check
//list_spawngroup.
"I want to add a new quest"
- Create a new directory under
dist/data/scripts/quests/Qxxxxx_QuestName/. - Write the quest class extending
QuestwithonTalk,onKill, etc. - Restart. The quest compiles on boot and the NPC starts offering it.
"I want to touch packet structure"
Three things need to stay in sync:
- The opcode in
ClientPackets.java/ServerPackets.java/ExClientPackets.java. - The packet class in
clientpackets/orserverpackets/(theread/writeimplementation). - Every caller of that packet, since the constructor signature usually changes.
If the client and server disagree even by one byte, the connection drops. Test against the actual chronicle's client version.
Chronicle hopping
Code is not shared across chronicle folders. If you fix a bug in L2J_Mobius_GD_3.0_Lindvior/ the same bug may exist (or may not, or may be already fixed) in L2J_Mobius_GD_1.0_Awakening/. Treat every port as a fresh review:
- The file path may match exactly, but the surrounding code may differ.
- Method signatures, class hierarchies and packet structures shift between chronicles.
- An XML field that existed in one chronicle may have been renamed or replaced in the next.
Diff before you copy. Compile after you paste. Test in-game.