From 24359e939819b6ea073197b7afccdd2238165331 Mon Sep 17 00:00:00 2001 From: CPunch Date: Sat, 4 Mar 2023 21:57:27 -0600 Subject: [PATCH] inital commit: we can read login packets! --- .gitignore | 2 + api/protocol/consts.go | 825 ++++++++++++++++++++++++++++++++++++++++ api/protocol/handler.go | 4 + api/protocol/packet.go | 227 +++++++++++ api/protocol/structs.go | 12 + go.mod | 3 + server/server.go | 101 +++++ 7 files changed, 1174 insertions(+) create mode 100644 .gitignore create mode 100644 api/protocol/consts.go create mode 100644 api/protocol/handler.go create mode 100644 api/protocol/packet.go create mode 100644 api/protocol/structs.go create mode 100644 go.mod create mode 100644 server/server.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..41c4578 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +notes +bin \ No newline at end of file diff --git a/api/protocol/consts.go b/api/protocol/consts.go new file mode 100644 index 0000000..d860e3d --- /dev/null +++ b/api/protocol/consts.go @@ -0,0 +1,825 @@ +package protocol + +const ( + SUCC = 1 + FAIL = 0 + + SIZEOF_BYTE = 1 + SIZEOF_DWORD = 4 + SIZEOF_INT = 4 + SIZEOF_FLOAT = 4 + SIZEOF_SHORT = 2 + SIZEOF_ULONG = 4 + SIZEOF_UINT64 = 8 + SIZEOF_IP_STRING = 16 + SIZEOF_CN_UID_STRING = 50 + SIZEOF_ACCOUNT_STRING = 33 + SIZEOF_PASSWORD_STRING = 33 + SIZEOF_AUTH_ID_STRING = 255 + + CN_MAX_COUNT_GROUP_MEMBER = 5 + CN_MAX_COUNT_PC_GROUP_MEMBER = 4 + CN_MAX_COUNT_NPC_GROUP_MEMBER = 5 + + CHAT_MAX_STRING = 128 + PC_START_LOCATION_RANDOM_RANGE = 10000 + SIZEOF_ANNOUNCE_STRING = 512 + SERVER_COUNT_SHARD_CLIENT = 25 + + EXIT_CODE_DISCONNECT = 0 + EXIT_CODE_REQ_BY_PC = 1 + EXIT_CODE_REQ_BY_SVR = 2 + EXIT_CODE_REQ_BY_GM = 3 + EXIT_CODE_HACK = 4 + EXIT_CODE_ERROR = 5 + EXIT_CODE_LIVE_CHECK = 6 + EXIT_CODE_REQ_BY_PC_DUPE_LOGIN = 7 + EXIT_CODE_SERVER_ERROR = 99 + + SIZEOF_USER_ID = 32 + SIZEOF_USER_PW = 32 + SIZEOF_PC_SLOT = 4 + SIZEOF_PC_NAME = 16 + SIZEOF_PC_FIRST_NAME = 9 + SIZEOF_PC_LAST_NAME = 17 + SIZEOF_PC_NAME_FLAG = 8 + + GENDER_NONE = 0 + GENDER_MALE = 1 + GENDER_FEMALE = 2 + + MENTOR_CHANGE_BASE_COST = 100 + REPEAT_MISSION_RESET_TIME = 9 + SIZEOF_REPEAT_QUESTFLAG_NUMBER = 8 + FATIGUE_RESET_TIME = 0 + + PC_FATIGUE_KILL_UNIT = 7 + PC_FATIGUE_1_LEVEL = 11420 + PC_FATIGUE_2_LEVEL = 6480 + PC_FATIGUE_MAX_LEVEL = 2 + PC_FUSIONMATTER_MAX = 999999999 + PC_CANDY_MAX = 999999999 + PC_BATTERY_MAX = 9999 + PC_LEVEL_MAX = 36 + SIZEOF_PC_BULLET_SLOT = 3 + PC_TICK_TIME = 5000 + SIZEOF_EQUIP_SLOT = 9 + + EQUIP_SLOT_HAND = 0 + EQUIP_SLOT_UPPERBODY = 1 + EQUIP_SLOT_LOWERBODY = 2 + EQUIP_SLOT_FOOT = 3 + EQUIP_SLOT_HEAD = 4 + EQUIP_SLOT_FACE = 5 + EQUIP_SLOT_BACK = 6 + EQUIP_SLOT_END = 6 + EQUIP_SLOT_HAND_EX = 7 + EQUIP_SLOT_VEHICLE = 8 + + WPN_EQUIP_TYPE_NONE = 0 + WPN_EQUIP_TYPE_OH_BLADE = 1 + WPN_EQUIP_TYPE_OH_CLUB = 2 + WPN_EQUIP_TYPE_OH_PISTOL = 3 + WPN_EQUIP_TYPE_OH_RIPLE = 4 + WPN_EQUIP_TYPE_OH_THROW = 5 + WPN_EQUIP_TYPE_DH_BLADE = 6 + WPN_EQUIP_TYPE_DH_CLUB = 7 + WPN_EQUIP_TYPE_DH_DPISTOL = 8 + WPN_EQUIP_TYPE_DH_RIPLE = 9 + WPN_EQUIP_TYPE_DH_THROW = 10 + WPN_EQUIP_TYPE_DH_ROCKET = 11 + + SIZEOF_INVEN_SLOT = 50 + SIZEOF_QINVEN_SLOT = 50 + SIZEOF_BANK_SLOT = 119 + SIZEOF_RESTORE_SLOT = 5 + SIZEOF_NANO_BANK_SLOT = 37 + SIZEOF_QUEST_SLOT = 1024 + NANO_QUEST_INDEX = 0 + SIZEOF_RQUEST_SLOT = 9 + SIZEOF_QUESTFLAG_NUMBER = 32 + SIZEOF_EP_RECORD_SLOT = 51 + SIZEOF_TRADE_SLOT = 12 + SIZEOF_VENDOR_TABLE_SLOT = 20 + SIZEOF_VENDOR_RESTORE_SLOT = 5 + SIZEOF_QUEST_NPC_SLOT = 3 + SIZEOF_QUEST_ITEM_SLOT = 3 + SIZEOF_MAX_ITEM_STACK = 100 + SIZEOF_PC_SKILL_SLOT = 33 + SIZEOF_QUICK_SLOT = 8 + ENCHANT_WEAPON_MATERIAL_ID = 101 + ENCHANT_DEFENCE_MATERIAL_ID = 102 + SIZEOF_NANO_CARRY_SLOT = 3 + COUNTOF_NANO_PER_SET = 3 + SIZEOF_NANO_SET = 13 + SIZEOF_NANO_STYLE = 3 + NANO_STYLE_NONE = 1 + NANO_STYLE_CRYSTAL = 0 + NANO_STYLE_ENERGY = 1 + NANO_STYLE_FLUID = 2 + SIZEOF_NANO_TYPE = 4 + NANO_TYPE_POWER = 0 + NANO_TYPE_ACCURACY = 1 + NANO_TYPE_PROTECT = 2 + NANO_TYPE_DODGE = 3 + SIZEOF_NANO_TUNE_NEED_ITEM_SLOT = 10 + VALUE_ATTACK_MISS = 1 + + MSG_ONLINE = 1 + MSG_BUSY = 2 + MSG_OFFLINE = 0 + SIZEOF_FREE_CHAT_STRING = 128 + SIZEOF_MENU_CHAT_STRING = 128 + SIZEOF_BUDDYLIST_SLOT = 50 + SIZEOF_EMAIL_SUBJECT_STRING = 32 + SIZEOF_EMAIL_CONTENT_STRING = 512 + SIZEOF_EMAIL_PAGE_SIZE = 5 + SIZEOF_EMAIL_ITEM_CNT = 4 + EMAIL_AND_MONEY_COST = 50 + EMAIL_ITEM_COST = 20 + BUDDYWARP_INTERVAL = 60 + EMAILSEND_TIME_DELAY = 60 + DB_ERROR_INVALID_DATA = 1 + DB_ERROR_HACK_ATTEMPT = 2 + DB_ERROR_ACCESS_FAIL = 3 + DB_ERROR_PC_INSERT_FAIL = 4 + CALL_NPC_MAX_CNT = 2048 + + CN_EP_RING_MAX_CNT = 999 + + HF_BIT_NONE = 0 + HF_BIT_NORMAL = 1 + HF_BIT_CRITICAL = 2 + HF_BIT_STYLE_WIN = 4 + HF_BIT_STYLE_TIE = 8 + HF_BIT_STYLE_LOSE = 16 + SKIN_COLOR_MAX = 12 + HAIR_COLOR_MAX = 18 + EYE_COLOR_MAX = 5 + BODY_TYPE_MAX = 3 + HEIGHT_TYPE_MAX = 5 + CLASS_TYPE_MAX = 4 + CN_EP_RACE_MODE_PRACTICE = 0 + CN_EP_RACE_MODE_RECORD = 1 + CN_EP_SECOM_NPC_TYPE_NUM = 13 + CN_EP_EECOM_NPC_TYPE_NUM = 14 + CN_EP_SIZE_SMALL = 0 + CN_EP_SIZE_MIDDLE = 1 + CN_EP_SIZE_BIG = 2 + CN_EP_TICKET_ITEM_ID_SMALL = 115 + CN_EP_TICKET_ITEM_ID_MIDDLE = 116 + CN_EP_TICKET_ITEM_ID_BIG = 117 + CN_EP_TICKET_ITEM_ID_FREE = 118 + CN_EP_DISTANCE_ERROR_SAFE_RANGE = 1200 + + CN_ACCOUNT_LEVEL__MASTER = 1 + CN_ACCOUNT_LEVEL__POWER_DEVELOPER = 10 + CN_ACCOUNT_LEVEL__QA = 20 + CN_ACCOUNT_LEVEL__GM = 30 + CN_ACCOUNT_LEVEL__CS = 40 + CN_ACCOUNT_LEVEL__FREE_USER = 48 + CN_ACCOUNT_LEVEL__PAY_USER = 49 + CN_ACCOUNT_LEVEL__DEVELOPER = 50 + CN_ACCOUNT_LEVEL__CLOSEBETA_USER = 80 + CN_ACCOUNT_LEVEL__OPENBETA_USER = 85 + CN_ACCOUNT_LEVEL__USER = 99 + + CN_SPECIAL_STATE_FLAG__PRINT_GM = 1 + CN_SPECIAL_STATE_FLAG__INVISIBLE = 2 + CN_SPECIAL_STATE_FLAG__INVULNERABLE = 4 + CN_SPECIAL_STATE_FLAG__FULL_UI = 16 + CN_SPECIAL_STATE_FLAG__COMBAT = 32 + CN_SPECIAL_STATE_FLAG__MUTE_FREECHAT = 64 + + CN_GM_SET_VALUE_TYPE__HP = 1 + CN_GM_SET_VALUE_TYPE__WEAPON_BATTERY = 2 + CN_GM_SET_VALUE_TYPE__NANO_BATTERY = 3 + CN_GM_SET_VALUE_TYPE__FUSION_MATTER = 4 + CN_GM_SET_VALUE_TYPE__CANDY = 5 + CN_GM_SET_VALUE_TYPE__SPEED = 6 + CN_GM_SET_VALUE_TYPE__JUMP = 7 + CN_GM_SET_VALUE_TYPE__END = 8 + + HEIGHT_CLIMBABLE = 150 + CN_GROUP_WARP_CHECK_RANGE = 1000 + WYVERN_LOCATION_FLAG_SIZE = 2 + CN_PC_EVENT_ID_GET_NANO_QUEST = 1 + CN_PC_EVENT_ID_DEFEAT_FUSE_AND_GET_NANO = 2 + _dCN_STREETSTALL__ITEMLIST_COUNT_MAX = 5 + + CSB_BIT_NONE = 0 // 0 + CSB_BIT_UP_MOVE_SPEED = 0x1 // 1 + CSB_BIT_UP_SWIM_SPEED = 0x2 // 2 + CSB_BIT_UP_JUMP_HEIGHT = 0x4 // 4 + CSB_BIT_UP_STEALTH = 0x8 // 8 + CSB_BIT_PHOENIX = 0x10 // 16 + CSB_BIT_PROTECT_BATTERY = 0x20 // 32 + CSB_BIT_PROTECT_INFECTION = 0x40 // 64 + CSB_BIT_DN_MOVE_SPEED = 0x80 // 128 + CSB_BIT_DN_ATTACK_SPEED = 0x100 // 256 + CSB_BIT_STUN = 0x200 // 512 + CSB_BIT_MEZ = 0x400 // 1024 + CSB_BIT_KNOCKDOWN = 0x800 // 2048 + CSB_BIT_MINIMAP_ENEMY = 0x1000 // 4096 + CSB_BIT_MINIMAP_TRESURE = 0x2000 // 8192 + CSB_BIT_REWARD_BLOB = 0x4000 // 16384 + CSB_BIT_REWARD_CASH = 0x8000 // 32768 + CSB_BIT_INFECTION = 0x10000 // 65536 + CSB_BIT_FREEDOM = 0x20000 // 131072 + CSB_BIT_BOUNDINGBALL = 0x40000 // 262144 + CSB_BIT_INVULNERABLE = 0x80000 // 524288 + CSB_BIT_STIMPAKSLOT1 = 0x100000 // 1048576 + CSB_BIT_STIMPAKSLOT2 = 0x200000 // 2097152 + CSB_BIT_STIMPAKSLOT3 = 0x400000 // 4194304 + CSB_BIT_HEAL = 0x800000 // 8388608 + CSB_BIT_EXTRABANK = 0x1000000 // 16777216 + + TIME_BUFF_CONFIRM_KEY_MAX = 2000000000 + READPACKET_SUCC = 0 + READPACKET_FAIL = 1 + READPACKET_RETURN = 2 + BITMASK_FROM2TO = 0x7fffffff // 2147483647 + BITMASK_FROM = 0x7fffffff // 2147483647 + BITMASK_TO = 0xf000000 // 251658240 + BITMASK_SENDBLOCK = 0x800000 // 8388608 + BITMASK_AUTHED = 0x400000 // 4194304 + BITMASK_U_ID = 0xfff // 4095 + + CL2LS = 0x12000000 + CL2FE = 0x13000000 + LS2CL = 0x21000000 + LS2LS = 0x22000000 + LS2DBA = 0x27000000 + FE2CL = 0x31000000 + FE2FE = 0x33000000 + FE2GS = 0x34000000 + FE2EP = 0x36000000 + FE2MSG = 0x38000000 + GS2FE = 0x43000000 + GS2GS = 0x44000000 + GS2AI = 0x45000000 + GS2EP = 0x46000000 + GS2DBA = 0x47000000 + GS2MSG = 0x48000000 + GS2MGR = 0x4a000000 + AI2GS = 0x54000000 + EP2FE = 0x63000000 + EP2GS = 0x64000000 + DBA2GS = 0x74000000 + DBA2EP = 0x75000000 + MSG2FE = 0x7fffffff + MSG2GS = 0x7fffffff + MSG2CMSG = 0x7fffffff + CMSG2MSG = 0x7fffffff + MGR2SPY = 0x7fffffff + SPY2MGR = 0x7fffffff + MGR2SA = 0x7fffffff + SA2MGR = 0x7fffffff + SA2SPY = 0x7fffffff + SPY2SA = 0x7fffffff + SPY2SVR = 0x7fffffff + SVR2SPY = 0x7fffffff + SCH2SVR = 0x7fffffff + SCH2LS = 0x7fffffff + SCH2FE = 0x7fffffff + SCH2GS = 0x7fffffff + SCH2AI = 0x7fffffff + SCH2EP = 0x7fffffff + SCH2DBA = 0x7fffffff + SCH2MSG = 0x7fffffff + SCH2CMSG = 0x7fffffff + CL2CDR = 0x1f000000 + + SENDBLOCK = 0x800000 // 8388608 + AUTHED_X = 0 // 0 + AUTHED_O = 0x400000 // 4194304 + + SEND_SVR_FE = 1 + SEND_SVR_FE_ANY = 2 + SEND_SVR_FE_ALL = 3 + SEND_SVR_AI = 4 + SEND_SVR_AI_ANY = 5 + SEND_SVR_AI_ALL = 6 + SEND_SVR_FE_AI_ALL = 7 + SEND_SVR_DBA = 8 + SEND_SVR_GS = 9 + SEND_SVR_MSG = 10 + SEND_SVR_MSG_ANY = 11 + SEND_SVR_MSG_ALL = 12 + + SEND_UNICAST = 1 + SEND_ANYCAST = 2 + SEND_ANYCAST_NEW = 3 + SEND_BROADCAST = 4 + + CN_PACKET_BUFFER_SIZE = 4096 + + P_CL2LS_REQ_LOGIN = 0x12000001 // 301989889 + P_CL2LS_REQ_CHECK_CHAR_NAME = 0x12000002 // 301989890 + P_CL2LS_REQ_SAVE_CHAR_NAME = 0x12000003 // 301989891 + P_CL2LS_REQ_CHAR_CREATE = 0x12000004 // 301989892 + P_CL2LS_REQ_CHAR_SELECT = 0x12000005 // 301989893 + P_CL2LS_REQ_CHAR_DELETE = 0x12000006 // 301989894 + P_CL2LS_REQ_SHARD_SELECT = 0x12000007 // 301989895 + P_CL2LS_REQ_SHARD_LIST_INFO = 0x12000008 // 301989896 + P_CL2LS_CHECK_NAME_LIST = 0x12000009 // 301989897 + P_CL2LS_REQ_SAVE_CHAR_TUTOR = 0x1200000a // 301989898 + P_CL2LS_REQ_PC_EXIT_DUPLICATE = 0x1200000b // 301989899 + P_CL2LS_REP_LIVE_CHECK = 0x1200000c // 301989900 + P_CL2LS_REQ_CHANGE_CHAR_NAME = 0x1200000d // 301989901 + P_CL2LS_REQ_SERVER_SELECT = 0x1200000e // 301989902 + + P_CL2FE_REQ_PC_ENTER = 0x13000001 // 318767105 + P_CL2FE_REQ_PC_EXIT = 0x13000002 // 318767106 + P_CL2FE_REQ_PC_MOVE = 0x13000003 // 318767107 + P_CL2FE_REQ_PC_STOP = 0x13000004 // 318767108 + P_CL2FE_REQ_PC_JUMP = 0x13000005 // 318767109 + P_CL2FE_REQ_PC_ATTACK_NPCs = 0x13000006 // 318767110 + P_CL2FE_REQ_SEND_FREECHAT_MESSAGE = 0x13000007 // 318767111 + P_CL2FE_REQ_SEND_MENUCHAT_MESSAGE = 0x13000008 // 318767112 + P_CL2FE_REQ_PC_REGEN = 0x13000009 // 318767113 + P_CL2FE_REQ_ITEM_MOVE = 0x1300000a // 318767114 + P_CL2FE_REQ_PC_TASK_START = 0x1300000b // 318767115 + P_CL2FE_REQ_PC_TASK_END = 0x1300000c // 318767116 + P_CL2FE_REQ_NANO_EQUIP = 0x1300000d // 318767117 + P_CL2FE_REQ_NANO_UNEQUIP = 0x1300000e // 318767118 + P_CL2FE_REQ_NANO_ACTIVE = 0x1300000f // 318767119 + P_CL2FE_REQ_NANO_TUNE = 0x13000010 // 318767120 + P_CL2FE_REQ_NANO_SKILL_USE = 0x13000011 // 318767121 + P_CL2FE_REQ_PC_TASK_STOP = 0x13000012 // 318767122 + P_CL2FE_REQ_PC_TASK_CONTINUE = 0x13000013 // 318767123 + P_CL2FE_REQ_PC_GOTO = 0x13000014 // 318767124 + P_CL2FE_REQ_CHARGE_NANO_STAMINA = 0x13000015 // 318767125 + P_CL2FE_REQ_PC_KILL_QUEST_NPCs = 0x13000016 // 318767126 + P_CL2FE_REQ_PC_VENDOR_ITEM_BUY = 0x13000017 // 318767127 + P_CL2FE_REQ_PC_VENDOR_ITEM_SELL = 0x13000018 // 318767128 + P_CL2FE_REQ_PC_ITEM_DELETE = 0x13000019 // 318767129 + P_CL2FE_REQ_PC_GIVE_ITEM = 0x1300001a // 318767130 + P_CL2FE_REQ_PC_ROCKET_STYLE_READY = 0x1300001b // 318767131 + P_CL2FE_REQ_PC_ROCKET_STYLE_FIRE = 0x1300001c // 318767132 + P_CL2FE_REQ_PC_ROCKET_STYLE_HIT = 0x1300001d // 318767133 + P_CL2FE_REQ_PC_GRENADE_STYLE_READY = 0x1300001e // 318767134 + P_CL2FE_REQ_PC_GRENADE_STYLE_FIRE = 0x1300001f // 318767135 + P_CL2FE_REQ_PC_GRENADE_STYLE_HIT = 0x13000020 // 318767136 + P_CL2FE_REQ_PC_NANO_CREATE = 0x13000021 // 318767137 + P_CL2FE_REQ_PC_TRADE_OFFER = 0x13000022 // 318767138 + P_CL2FE_REQ_PC_TRADE_OFFER_CANCEL = 0x13000023 // 318767139 + P_CL2FE_REQ_PC_TRADE_OFFER_ACCEPT = 0x13000024 // 318767140 + P_CL2FE_REQ_PC_TRADE_OFFER_REFUSAL = 0x13000025 // 318767141 + P_CL2FE_REQ_PC_TRADE_OFFER_ABORT = 0x13000026 // 318767142 + P_CL2FE_REQ_PC_TRADE_CONFIRM = 0x13000027 // 318767143 + P_CL2FE_REQ_PC_TRADE_CONFIRM_CANCEL = 0x13000028 // 318767144 + P_CL2FE_REQ_PC_TRADE_CONFIRM_ABORT = 0x13000029 // 318767145 + P_CL2FE_REQ_PC_TRADE_ITEM_REGISTER = 0x1300002a // 318767146 + P_CL2FE_REQ_PC_TRADE_ITEM_UNREGISTER = 0x1300002b // 318767147 + P_CL2FE_REQ_PC_TRADE_CASH_REGISTER = 0x1300002c // 318767148 + P_CL2FE_REQ_PC_TRADE_EMOTES_CHAT = 0x1300002d // 318767149 + P_CL2FE_REQ_PC_BANK_OPEN = 0x1300002e // 318767150 + P_CL2FE_REQ_PC_BANK_CLOSE = 0x1300002f // 318767151 + P_CL2FE_REQ_PC_VENDOR_START = 0x13000030 // 318767152 + P_CL2FE_REQ_PC_VENDOR_TABLE_UPDATE = 0x13000031 // 318767153 + P_CL2FE_REQ_PC_VENDOR_ITEM_RESTORE_BUY = 0x13000032 // 318767154 + P_CL2FE_REQ_PC_COMBAT_BEGIN = 0x13000033 // 318767155 + P_CL2FE_REQ_PC_COMBAT_END = 0x13000034 // 318767156 + P_CL2FE_REQ_REQUEST_MAKE_BUDDY = 0x13000035 // 318767157 + P_CL2FE_REQ_ACCEPT_MAKE_BUDDY = 0x13000036 // 318767158 + P_CL2FE_REQ_SEND_BUDDY_FREECHAT_MESSAGE = 0x13000037 // 318767159 + P_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE = 0x13000038 // 318767160 + P_CL2FE_REQ_GET_BUDDY_STYLE = 0x13000039 // 318767161 + P_CL2FE_REQ_SET_BUDDY_BLOCK = 0x1300003a // 318767162 + P_CL2FE_REQ_REMOVE_BUDDY = 0x1300003b // 318767163 + P_CL2FE_REQ_GET_BUDDY_STATE = 0x1300003c // 318767164 + P_CL2FE_REQ_PC_JUMPPAD = 0x1300003d // 318767165 + P_CL2FE_REQ_PC_LAUNCHER = 0x1300003e // 318767166 + P_CL2FE_REQ_PC_ZIPLINE = 0x1300003f // 318767167 + P_CL2FE_REQ_PC_MOVEPLATFORM = 0x13000040 // 318767168 + P_CL2FE_REQ_PC_SLOPE = 0x13000041 // 318767169 + P_CL2FE_REQ_PC_STATE_CHANGE = 0x13000042 // 318767170 + P_CL2FE_REQ_PC_MAP_WARP = 0x13000043 // 318767171 + P_CL2FE_REQ_PC_GIVE_NANO = 0x13000044 // 318767172 + P_CL2FE_REQ_NPC_SUMMON = 0x13000045 // 318767173 + P_CL2FE_REQ_NPC_UNSUMMON = 0x13000046 // 318767174 + P_CL2FE_REQ_ITEM_CHEST_OPEN = 0x13000047 // 318767175 + P_CL2FE_REQ_PC_GIVE_NANO_SKILL = 0x13000048 // 318767176 + P_CL2FE_DOT_DAMAGE_ONOFF = 0x13000049 // 318767177 + P_CL2FE_REQ_PC_VENDOR_BATTERY_BUY = 0x1300004a // 318767178 + P_CL2FE_REQ_PC_WARP_USE_NPC = 0x1300004b // 318767179 + P_CL2FE_REQ_PC_GROUP_INVITE = 0x1300004c // 318767180 + P_CL2FE_REQ_PC_GROUP_INVITE_REFUSE = 0x1300004d // 318767181 + P_CL2FE_REQ_PC_GROUP_JOIN = 0x1300004e // 318767182 + P_CL2FE_REQ_PC_GROUP_LEAVE = 0x1300004f // 318767183 + P_CL2FE_REQ_PC_AVATAR_EMOTES_CHAT = 0x13000050 // 318767184 + P_CL2FE_REQ_PC_BUDDY_WARP = 0x13000051 // 318767185 + P_CL2FE_REQ_GET_MEMBER_STYLE = 0x13000052 // 318767186 + P_CL2FE_REQ_GET_GROUP_STYLE = 0x13000053 // 318767187 + P_CL2FE_REQ_PC_CHANGE_MENTOR = 0x13000054 // 318767188 + P_CL2FE_REQ_GET_BUDDY_LOCATION = 0x13000055 // 318767189 + P_CL2FE_REQ_NPC_GROUP_SUMMON = 0x13000056 // 318767190 + P_CL2FE_REQ_PC_WARP_TO_PC = 0x13000057 // 318767191 + P_CL2FE_REQ_EP_RANK_GET_LIST = 0x13000058 // 318767192 + P_CL2FE_REQ_EP_RANK_GET_DETAIL = 0x13000059 // 318767193 + P_CL2FE_REQ_EP_RANK_GET_PC_INFO = 0x1300005a // 318767194 + P_CL2FE_REQ_EP_RACE_START = 0x1300005b // 318767195 + P_CL2FE_REQ_EP_RACE_END = 0x1300005c // 318767196 + P_CL2FE_REQ_EP_RACE_CANCEL = 0x1300005d // 318767197 + P_CL2FE_REQ_EP_GET_RING = 0x1300005e // 318767198 + P_CL2FE_REQ_IM_CHANGE_SWITCH_STATUS = 0x1300005f // 318767199 + P_CL2FE_REQ_SHINY_PICKUP = 0x13000060 // 318767200 + P_CL2FE_REQ_SHINY_SUMMON = 0x13000061 // 318767201 + P_CL2FE_REQ_PC_MOVETRANSPORTATION = 0x13000062 // 318767202 + P_CL2FE_REQ_SEND_ALL_GROUP_FREECHAT_MESSAGE = 0x13000063 // 318767203 + P_CL2FE_REQ_SEND_ANY_GROUP_FREECHAT_MESSAGE = 0x13000064 // 318767204 + P_CL2FE_REQ_BARKER = 0x13000065 // 318767205 + P_CL2FE_REQ_SEND_ALL_GROUP_MENUCHAT_MESSAGE = 0x13000066 // 318767206 + P_CL2FE_REQ_SEND_ANY_GROUP_MENUCHAT_MESSAGE = 0x13000067 // 318767207 + P_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION = 0x13000068 // 318767208 + P_CL2FE_REQ_PC_WARP_USE_TRANSPORTATION = 0x13000069 // 318767209 + P_CL2FE_GM_REQ_PC_SPECIAL_STATE_SWITCH = 0x1300006a // 318767210 + P_CL2FE_GM_REQ_PC_SET_VALUE = 0x1300006b // 318767211 + P_CL2FE_GM_REQ_KICK_PLAYER = 0x1300006c // 318767212 + P_CL2FE_GM_REQ_TARGET_PC_TELEPORT = 0x1300006d // 318767213 + P_CL2FE_GM_REQ_PC_LOCATION = 0x1300006e // 318767214 + P_CL2FE_GM_REQ_PC_ANNOUNCE = 0x1300006f // 318767215 + P_CL2FE_REQ_SET_PC_BLOCK = 0x13000070 // 318767216 + P_CL2FE_REQ_REGIST_RXCOM = 0x13000071 // 318767217 + P_CL2FE_GM_REQ_PC_MOTD_REGISTER = 0x13000072 // 318767218 + P_CL2FE_REQ_ITEM_USE = 0x13000073 // 318767219 + P_CL2FE_REQ_WARP_USE_RECALL = 0x13000074 // 318767220 + P_CL2FE_REP_LIVE_CHECK = 0x13000075 // 318767221 + P_CL2FE_REQ_PC_MISSION_COMPLETE = 0x13000076 // 318767222 + P_CL2FE_REQ_PC_TASK_COMPLETE = 0x13000077 // 318767223 + P_CL2FE_REQ_NPC_INTERACTION = 0x13000078 // 318767224 + P_CL2FE_DOT_HEAL_ONOFF = 0x13000079 // 318767225 + P_CL2FE_REQ_PC_SPECIAL_STATE_SWITCH = 0x1300007a // 318767226 + P_CL2FE_REQ_PC_EMAIL_UPDATE_CHECK = 0x1300007b // 318767227 + P_CL2FE_REQ_PC_READ_EMAIL = 0x1300007c // 318767228 + P_CL2FE_REQ_PC_RECV_EMAIL_PAGE_LIST = 0x1300007d // 318767229 + P_CL2FE_REQ_PC_DELETE_EMAIL = 0x1300007e // 318767230 + P_CL2FE_REQ_PC_SEND_EMAIL = 0x1300007f // 318767231 + P_CL2FE_REQ_PC_RECV_EMAIL_ITEM = 0x13000080 // 318767232 + P_CL2FE_REQ_PC_RECV_EMAIL_CANDY = 0x13000081 // 318767233 + P_CL2FE_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF = 0x13000082 // 318767234 + P_CL2FE_REQ_PC_SET_CURRENT_MISSION_ID = 0x13000083 // 318767235 + P_CL2FE_REQ_NPC_GROUP_INVITE = 0x13000084 // 318767236 + P_CL2FE_REQ_NPC_GROUP_KICK = 0x13000085 // 318767237 + P_CL2FE_REQ_PC_FIRST_USE_FLAG_SET = 0x13000086 // 318767238 + P_CL2FE_REQ_PC_TRANSPORT_WARP = 0x13000087 // 318767239 + P_CL2FE_REQ_PC_TIME_TO_GO_WARP = 0x13000088 // 318767240 + P_CL2FE_REQ_PC_RECV_EMAIL_ITEM_ALL = 0x13000089 // 318767241 + P_CL2FE_REQ_CHANNEL_INFO = 0x1300008a // 318767242 + P_CL2FE_REQ_PC_CHANNEL_NUM = 0x1300008b // 318767243 + P_CL2FE_REQ_PC_WARP_CHANNEL = 0x1300008c // 318767244 + P_CL2FE_REQ_PC_LOADING_COMPLETE = 0x1300008d // 318767245 + P_CL2FE_REQ_PC_FIND_NAME_MAKE_BUDDY = 0x1300008e // 318767246 + P_CL2FE_REQ_PC_FIND_NAME_ACCEPT_BUDDY = 0x1300008f // 318767247 + P_CL2FE_REQ_PC_ATTACK_CHARs = 0x13000090 // 318767248 + P_CL2FE_PC_STREETSTALL_REQ_READY = 0x13000091 // 318767249 + P_CL2FE_PC_STREETSTALL_REQ_CANCEL = 0x13000092 // 318767250 + P_CL2FE_PC_STREETSTALL_REQ_REGIST_ITEM = 0x13000093 // 318767251 + P_CL2FE_PC_STREETSTALL_REQ_UNREGIST_ITEM = 0x13000094 // 318767252 + P_CL2FE_PC_STREETSTALL_REQ_SALE_START = 0x13000095 // 318767253 + P_CL2FE_PC_STREETSTALL_REQ_ITEM_LIST = 0x13000096 // 318767254 + P_CL2FE_PC_STREETSTALL_REQ_ITEM_BUY = 0x13000097 // 318767255 + P_CL2FE_REQ_PC_ITEM_COMBINATION = 0x13000098 // 318767256 + P_CL2FE_GM_REQ_SET_PC_SKILL = 0x13000099 // 318767257 + P_CL2FE_REQ_PC_SKILL_ADD = 0x1300009a // 318767258 + P_CL2FE_REQ_PC_SKILL_DEL = 0x1300009b // 318767259 + P_CL2FE_REQ_PC_SKILL_USE = 0x1300009c // 318767260 + P_CL2FE_REQ_PC_ROPE = 0x1300009d // 318767261 + P_CL2FE_REQ_PC_BELT = 0x1300009e // 318767262 + P_CL2FE_REQ_PC_VEHICLE_ON = 0x1300009f // 318767263 + P_CL2FE_REQ_PC_VEHICLE_OFF = 0x130000a0 // 318767264 + P_CL2FE_REQ_PC_REGIST_QUICK_SLOT = 0x130000a1 // 318767265 + P_CL2FE_REQ_PC_DISASSEMBLE_ITEM = 0x130000a2 // 318767266 + P_CL2FE_GM_REQ_REWARD_RATE = 0x130000a3 // 318767267 + P_CL2FE_REQ_PC_ITEM_ENCHANT = 0x130000a4 // 318767268 + + P_FE2CL_ERROR = 0x31000000 // 822083584 + P_FE2CL_REP_PC_ENTER_FAIL = 0x31000001 // 822083585 + P_FE2CL_REP_PC_ENTER_SUCC = 0x31000002 // 822083586 + P_FE2CL_PC_NEW = 0x31000003 // 822083587 + P_FE2CL_REP_PC_EXIT_FAIL = 0x31000004 // 822083588 + P_FE2CL_REP_PC_EXIT_SUCC = 0x31000005 // 822083589 + P_FE2CL_PC_EXIT = 0x31000006 // 822083590 + P_FE2CL_PC_AROUND = 0x31000007 // 822083591 + P_FE2CL_PC_MOVE = 0x31000008 // 822083592 + P_FE2CL_PC_STOP = 0x31000009 // 822083593 + P_FE2CL_PC_JUMP = 0x3100000a // 822083594 + P_FE2CL_NPC_ENTER = 0x3100000b // 822083595 + P_FE2CL_NPC_EXIT = 0x3100000c // 822083596 + P_FE2CL_NPC_MOVE = 0x3100000d // 822083597 + P_FE2CL_NPC_NEW = 0x3100000e // 822083598 + P_FE2CL_NPC_AROUND = 0x3100000f // 822083599 + P_FE2CL_AROUND_DEL_PC = 0x31000010 // 822083600 + P_FE2CL_AROUND_DEL_NPC = 0x31000011 // 822083601 + P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC = 0x31000012 // 822083602 + P_FE2CL_REP_SEND_FREECHAT_MESSAGE_FAIL = 0x31000013 // 822083603 + P_FE2CL_PC_ATTACK_NPCs_SUCC = 0x31000014 // 822083604 + P_FE2CL_PC_ATTACK_NPCs = 0x31000015 // 822083605 + P_FE2CL_NPC_ATTACK_PCs = 0x31000016 // 822083606 + P_FE2CL_REP_PC_REGEN_SUCC = 0x31000017 // 822083607 + P_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC = 0x31000018 // 822083608 + P_FE2CL_REP_SEND_MENUCHAT_MESSAGE_FAIL = 0x31000019 // 822083609 + P_FE2CL_PC_ITEM_MOVE_SUCC = 0x3100001a // 822083610 + P_FE2CL_PC_EQUIP_CHANGE = 0x3100001b // 822083611 + P_FE2CL_REP_PC_TASK_START_SUCC = 0x3100001c // 822083612 + P_FE2CL_REP_PC_TASK_START_FAIL = 0x3100001d // 822083613 + P_FE2CL_REP_PC_TASK_END_SUCC = 0x3100001e // 822083614 + P_FE2CL_REP_PC_TASK_END_FAIL = 0x3100001f // 822083615 + P_FE2CL_NPC_SKILL_READY = 0x31000020 // 822083616 + P_FE2CL_NPC_SKILL_FIRE = 0x31000021 // 822083617 + P_FE2CL_NPC_SKILL_HIT = 0x31000022 // 822083618 + P_FE2CL_NPC_SKILL_CORRUPTION_READY = 0x31000023 // 822083619 + P_FE2CL_NPC_SKILL_CORRUPTION_HIT = 0x31000024 // 822083620 + P_FE2CL_NPC_SKILL_CANCEL = 0x31000025 // 822083621 + P_FE2CL_REP_NANO_EQUIP_SUCC = 0x31000026 // 822083622 + P_FE2CL_REP_NANO_UNEQUIP_SUCC = 0x31000027 // 822083623 + P_FE2CL_REP_NANO_ACTIVE_SUCC = 0x31000028 // 822083624 + P_FE2CL_REP_NANO_TUNE_SUCC = 0x31000029 // 822083625 + P_FE2CL_NANO_ACTIVE = 0x3100002a // 822083626 + P_FE2CL_NANO_SKILL_USE_SUCC = 0x3100002b // 822083627 + P_FE2CL_NANO_SKILL_USE = 0x3100002c // 822083628 + P_FE2CL_REP_PC_TASK_STOP_SUCC = 0x3100002d // 822083629 + P_FE2CL_REP_PC_TASK_STOP_FAIL = 0x3100002e // 822083630 + P_FE2CL_REP_PC_TASK_CONTINUE_SUCC = 0x3100002f // 822083631 + P_FE2CL_REP_PC_TASK_CONTINUE_FAIL = 0x31000030 // 822083632 + P_FE2CL_REP_PC_GOTO_SUCC = 0x31000031 // 822083633 + P_FE2CL_REP_CHARGE_NANO_STAMINA = 0x31000032 // 822083634 + P_FE2CL_REP_PC_TICK = 0x31000033 // 822083635 + P_FE2CL_REP_PC_KILL_QUEST_NPCs_SUCC = 0x31000034 // 822083636 + P_FE2CL_REP_PC_VENDOR_ITEM_BUY_SUCC = 0x31000035 // 822083637 + P_FE2CL_REP_PC_VENDOR_ITEM_BUY_FAIL = 0x31000036 // 822083638 + P_FE2CL_REP_PC_VENDOR_ITEM_SELL_SUCC = 0x31000037 // 822083639 + P_FE2CL_REP_PC_VENDOR_ITEM_SELL_FAIL = 0x31000038 // 822083640 + P_FE2CL_REP_PC_ITEM_DELETE_SUCC = 0x31000039 // 822083641 + P_FE2CL_PC_ROCKET_STYLE_READY = 0x3100003a // 822083642 + P_FE2CL_REP_PC_ROCKET_STYLE_FIRE_SUCC = 0x3100003b // 822083643 + P_FE2CL_PC_ROCKET_STYLE_FIRE = 0x3100003c // 822083644 + P_FE2CL_PC_ROCKET_STYLE_HIT = 0x3100003d // 822083645 + P_FE2CL_PC_GRENADE_STYLE_READY = 0x3100003e // 822083646 + P_FE2CL_REP_PC_GRENADE_STYLE_FIRE_SUCC = 0x3100003f // 822083647 + P_FE2CL_PC_GRENADE_STYLE_FIRE = 0x31000040 // 822083648 + P_FE2CL_PC_GRENADE_STYLE_HIT = 0x31000041 // 822083649 + P_FE2CL_REP_PC_TRADE_OFFER = 0x31000042 // 822083650 + P_FE2CL_REP_PC_TRADE_OFFER_CANCEL = 0x31000043 // 822083651 + P_FE2CL_REP_PC_TRADE_OFFER_SUCC = 0x31000044 // 822083652 + P_FE2CL_REP_PC_TRADE_OFFER_REFUSAL = 0x31000045 // 822083653 + P_FE2CL_REP_PC_TRADE_OFFER_ABORT = 0x31000046 // 822083654 + P_FE2CL_REP_PC_TRADE_CONFIRM = 0x31000047 // 822083655 + P_FE2CL_REP_PC_TRADE_CONFIRM_CANCEL = 0x31000048 // 822083656 + P_FE2CL_REP_PC_TRADE_CONFIRM_ABORT = 0x31000049 // 822083657 + P_FE2CL_REP_PC_TRADE_CONFIRM_SUCC = 0x3100004a // 822083658 + P_FE2CL_REP_PC_TRADE_CONFIRM_FAIL = 0x3100004b // 822083659 + P_FE2CL_REP_PC_TRADE_ITEM_REGISTER_SUCC = 0x3100004c // 822083660 + P_FE2CL_REP_PC_TRADE_ITEM_REGISTER_FAIL = 0x3100004d // 822083661 + P_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_SUCC = 0x3100004e // 822083662 + P_FE2CL_REP_PC_TRADE_ITEM_UNREGISTER_FAIL = 0x3100004f // 822083663 + P_FE2CL_REP_PC_TRADE_CASH_REGISTER_SUCC = 0x31000050 // 822083664 + P_FE2CL_REP_PC_TRADE_CASH_REGISTER_FAIL = 0x31000051 // 822083665 + P_FE2CL_REP_PC_TRADE_EMOTES_CHAT = 0x31000052 // 822083666 + P_FE2CL_REP_PC_NANO_CREATE_SUCC = 0x31000053 // 822083667 + P_FE2CL_REP_PC_NANO_CREATE_FAIL = 0x31000054 // 822083668 + P_FE2CL_REP_NANO_TUNE_FAIL = 0x31000055 // 822083669 + P_FE2CL_REP_PC_BANK_OPEN_SUCC = 0x31000056 // 822083670 + P_FE2CL_REP_PC_BANK_OPEN_FAIL = 0x31000057 // 822083671 + P_FE2CL_REP_PC_BANK_CLOSE_SUCC = 0x31000058 // 822083672 + P_FE2CL_REP_PC_BANK_CLOSE_FAIL = 0x31000059 // 822083673 + P_FE2CL_REP_PC_VENDOR_START_SUCC = 0x3100005a // 822083674 + P_FE2CL_REP_PC_VENDOR_START_FAIL = 0x3100005b // 822083675 + P_FE2CL_REP_PC_VENDOR_TABLE_UPDATE_SUCC = 0x3100005c // 822083676 + P_FE2CL_REP_PC_VENDOR_TABLE_UPDATE_FAIL = 0x3100005d // 822083677 + P_FE2CL_REP_PC_VENDOR_ITEM_RESTORE_BUY_SUCC = 0x3100005e // 822083678 + P_FE2CL_REP_PC_VENDOR_ITEM_RESTORE_BUY_FAIL = 0x3100005f // 822083679 + P_FE2CL_CHAR_TIME_BUFF_TIME_OUT = 0x31000060 // 822083680 + P_FE2CL_REP_PC_GIVE_ITEM_SUCC = 0x31000061 // 822083681 + P_FE2CL_REP_PC_GIVE_ITEM_FAIL = 0x31000062 // 822083682 + P_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC = 0x31000063 // 822083683 + P_FE2CL_REP_PC_BUDDYLIST_INFO_FAIL = 0x31000064 // 822083684 + P_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC = 0x7fffffff // 2147483647 + P_FE2CL_REP_REQUEST_MAKE_BUDDY_FAIL = 0x31000066 // 822083686 + P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC = 0x31000067 // 822083687 + P_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL = 0x31000068 // 822083688 + P_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC = 0x31000069 // 822083689 + P_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_FAIL = 0x3100006a // 822083690 + P_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC = 0x3100006b // 822083691 + P_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_FAIL = 0x3100006c // 822083692 + P_FE2CL_REP_GET_BUDDY_STYLE_SUCC = 0x3100006d // 822083693 + P_FE2CL_REP_GET_BUDDY_STYLE_FAIL = 0x3100006e // 822083694 + P_FE2CL_REP_GET_BUDDY_STATE_SUCC = 0x3100006f // 822083695 + P_FE2CL_REP_GET_BUDDY_STATE_FAIL = 0x31000070 // 822083696 + P_FE2CL_REP_SET_BUDDY_BLOCK_SUCC = 0x31000071 // 822083697 + P_FE2CL_REP_SET_BUDDY_BLOCK_FAIL = 0x31000072 // 822083698 + P_FE2CL_REP_REMOVE_BUDDY_SUCC = 0x31000073 // 822083699 + P_FE2CL_REP_REMOVE_BUDDY_FAIL = 0x31000074 // 822083700 + P_FE2CL_PC_JUMPPAD = 0x31000075 // 822083701 + P_FE2CL_PC_LAUNCHER = 0x31000076 // 822083702 + P_FE2CL_PC_ZIPLINE = 0x31000077 // 822083703 + P_FE2CL_PC_MOVEPLATFORM = 0x31000078 // 822083704 + P_FE2CL_PC_SLOPE = 0x31000079 // 822083705 + P_FE2CL_PC_STATE_CHANGE = 0x3100007a // 822083706 + P_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC_TO_ACCEPTER = 0x3100007b // 822083707 + P_FE2CL_REP_REWARD_ITEM = 0x3100007c // 822083708 + P_FE2CL_REP_ITEM_CHEST_OPEN_SUCC = 0x3100007d // 822083709 + P_FE2CL_REP_ITEM_CHEST_OPEN_FAIL = 0x3100007e // 822083710 + P_FE2CL_CHAR_TIME_BUFF_TIME_TICK = 0x3100007f // 822083711 + P_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC = 0x31000080 // 822083712 + P_FE2CL_REP_PC_VENDOR_BATTERY_BUY_FAIL = 0x31000081 // 822083713 + P_FE2CL_NPC_ROCKET_STYLE_FIRE = 0x31000082 // 822083714 + P_FE2CL_NPC_GRENADE_STYLE_FIRE = 0x31000083 // 822083715 + P_FE2CL_NPC_BULLET_STYLE_HIT = 0x31000084 // 822083716 + P_FE2CL_CHARACTER_ATTACK_CHARACTERs = 0x31000085 // 822083717 + P_FE2CL_PC_GROUP_INVITE = 0x31000086 // 822083718 + P_FE2CL_PC_GROUP_INVITE_FAIL = 0x31000087 // 822083719 + P_FE2CL_PC_GROUP_INVITE_REFUSE = 0x31000088 // 822083720 + P_FE2CL_PC_GROUP_JOIN = 0x31000089 // 822083721 + P_FE2CL_PC_GROUP_JOIN_FAIL = 0x3100008a // 822083722 + P_FE2CL_PC_GROUP_JOIN_SUCC = 0x3100008b // 822083723 + P_FE2CL_PC_GROUP_LEAVE = 0x3100008c // 822083724 + P_FE2CL_PC_GROUP_LEAVE_FAIL = 0x3100008d // 822083725 + P_FE2CL_PC_GROUP_LEAVE_SUCC = 0x3100008e // 822083726 + P_FE2CL_PC_GROUP_MEMBER_INFO = 0x3100008f // 822083727 + P_FE2CL_REP_PC_WARP_USE_NPC_SUCC = 0x31000090 // 822083728 + P_FE2CL_REP_PC_WARP_USE_NPC_FAIL = 0x31000091 // 822083729 + P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT = 0x31000092 // 822083730 + P_FE2CL_REP_PC_CHANGE_MENTOR_SUCC = 0x31000093 // 822083731 + P_FE2CL_REP_PC_CHANGE_MENTOR_FAIL = 0x31000094 // 822083732 + P_FE2CL_REP_GET_MEMBER_STYLE_FAIL = 0x31000095 // 822083733 + P_FE2CL_REP_GET_MEMBER_STYLE_SUCC = 0x31000096 // 822083734 + P_FE2CL_REP_GET_GROUP_STYLE_FAIL = 0x31000097 // 822083735 + P_FE2CL_REP_GET_GROUP_STYLE_SUCC = 0x31000098 // 822083736 + P_FE2CL_PC_REGEN = 0x31000099 // 822083737 + P_FE2CL_INSTANCE_MAP_INFO = 0x3100009a // 822083738 + P_FE2CL_TRANSPORTATION_ENTER = 0x3100009b // 822083739 + P_FE2CL_TRANSPORTATION_EXIT = 0x3100009c // 822083740 + P_FE2CL_TRANSPORTATION_MOVE = 0x3100009d // 822083741 + P_FE2CL_TRANSPORTATION_NEW = 0x3100009e // 822083742 + P_FE2CL_TRANSPORTATION_AROUND = 0x3100009f // 822083743 + P_FE2CL_AROUND_DEL_TRANSPORTATION = 0x310000a0 // 822083744 + P_FE2CL_REP_EP_RANK_LIST = 0x310000a1 // 822083745 + P_FE2CL_REP_EP_RANK_DETAIL = 0x310000a2 // 822083746 + P_FE2CL_REP_EP_RANK_PC_INFO = 0x310000a3 // 822083747 + P_FE2CL_REP_EP_RACE_START_SUCC = 0x310000a4 // 822083748 + P_FE2CL_REP_EP_RACE_START_FAIL = 0x310000a5 // 822083749 + P_FE2CL_REP_EP_RACE_END_SUCC = 0x310000a6 // 822083750 + P_FE2CL_REP_EP_RACE_END_FAIL = 0x310000a7 // 822083751 + P_FE2CL_REP_EP_RACE_CANCEL_SUCC = 0x310000a8 // 822083752 + P_FE2CL_REP_EP_RACE_CANCEL_FAIL = 0x310000a9 // 822083753 + P_FE2CL_REP_EP_GET_RING_SUCC = 0x310000aa // 822083754 + P_FE2CL_REP_EP_GET_RING_FAIL = 0x310000ab // 822083755 + P_FE2CL_REP_IM_CHANGE_SWITCH_STATUS = 0x310000ac // 822083756 + P_FE2CL_SHINY_ENTER = 0x310000ad // 822083757 + P_FE2CL_SHINY_EXIT = 0x310000ae // 822083758 + P_FE2CL_SHINY_NEW = 0x310000af // 822083759 + P_FE2CL_SHINY_AROUND = 0x310000b0 // 822083760 + P_FE2CL_AROUND_DEL_SHINY = 0x310000b1 // 822083761 + P_FE2CL_REP_SHINY_PICKUP_FAIL = 0x310000b2 // 822083762 + P_FE2CL_REP_SHINY_PICKUP_SUCC = 0x310000b3 // 822083763 + P_FE2CL_PC_MOVETRANSPORTATION = 0x310000b4 // 822083764 + P_FE2CL_REP_SEND_ALL_GROUP_FREECHAT_MESSAGE_SUCC = 0x310000b5 // 822083765 + P_FE2CL_REP_SEND_ALL_GROUP_FREECHAT_MESSAGE_FAIL = 0x310000b6 // 822083766 + P_FE2CL_REP_SEND_ANY_GROUP_FREECHAT_MESSAGE_SUCC = 0x310000b7 // 822083767 + P_FE2CL_REP_SEND_ANY_GROUP_FREECHAT_MESSAGE_FAIL = 0x310000b8 // 822083768 + P_FE2CL_REP_BARKER = 0x310000b9 // 822083769 + P_FE2CL_REP_SEND_ALL_GROUP_MENUCHAT_MESSAGE_SUCC = 0x310000ba // 822083770 + P_FE2CL_REP_SEND_ALL_GROUP_MENUCHAT_MESSAGE_FAIL = 0x310000bb // 822083771 + P_FE2CL_REP_SEND_ANY_GROUP_MENUCHAT_MESSAGE_SUCC = 0x310000bc // 822083772 + P_FE2CL_REP_SEND_ANY_GROUP_MENUCHAT_MESSAGE_FAIL = 0x310000bd // 822083773 + P_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_FAIL = 0x310000be // 822083774 + P_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_SUCC = 0x310000bf // 822083775 + P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_FAIL = 0x310000c0 // 822083776 + P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC = 0x310000c1 // 822083777 + P_FE2CL_ANNOUNCE_MSG = 0x310000c2 // 822083778 + P_FE2CL_REP_PC_SPECIAL_STATE_SWITCH_SUCC = 0x310000c3 // 822083779 + P_FE2CL_PC_SPECIAL_STATE_CHANGE = 0x310000c4 // 822083780 + P_FE2CL_GM_REP_PC_SET_VALUE = 0x310000c5 // 822083781 + P_FE2CL_GM_PC_CHANGE_VALUE = 0x310000c6 // 822083782 + P_FE2CL_GM_REP_PC_LOCATION = 0x310000c7 // 822083783 + P_FE2CL_GM_REP_PC_ANNOUNCE = 0x310000c8 // 822083784 + P_FE2CL_REP_PC_BUDDY_WARP_FAIL = 0x310000c9 // 822083785 + P_FE2CL_REP_PC_CHANGE_LEVEL = 0x310000ca // 822083786 + P_FE2CL_REP_SET_PC_BLOCK_SUCC = 0x310000cb // 822083787 + P_FE2CL_REP_SET_PC_BLOCK_FAIL = 0x310000cc // 822083788 + P_FE2CL_REP_REGIST_RXCOM = 0x310000cd // 822083789 + P_FE2CL_REP_REGIST_RXCOM_FAIL = 0x310000ce // 822083790 + P_FE2CL_PC_INVEN_FULL_MSG = 0x310000cf // 822083791 + P_FE2CL_REQ_LIVE_CHECK = 0x310000d0 // 822083792 + P_FE2CL_PC_MOTD_LOGIN = 0x310000d1 // 822083793 + P_FE2CL_REP_PC_ITEM_USE_FAIL = 0x310000d2 // 822083794 + P_FE2CL_REP_PC_ITEM_USE_SUCC = 0x310000d3 // 822083795 + P_FE2CL_PC_ITEM_USE = 0x310000d4 // 822083796 + P_FE2CL_REP_GET_BUDDY_LOCATION_SUCC = 0x310000d5 // 822083797 + P_FE2CL_REP_GET_BUDDY_LOCATION_FAIL = 0x310000d6 // 822083798 + P_FE2CL_REP_PC_RIDING_FAIL = 0x310000d7 // 822083799 + P_FE2CL_REP_PC_RIDING_SUCC = 0x310000d8 // 822083800 + P_FE2CL_PC_RIDING = 0x310000d9 // 822083801 + P_FE2CL_PC_BROOMSTICK_MOVE = 0x310000da // 822083802 + P_FE2CL_REP_PC_BUDDY_WARP_OTHER_SHARD_SUCC = 0x310000db // 822083803 + P_FE2CL_REP_WARP_USE_RECALL_FAIL = 0x310000dc // 822083804 + P_FE2CL_REP_PC_EXIT_DUPLICATE = 0x310000dd // 822083805 + P_FE2CL_REP_PC_MISSION_COMPLETE_SUCC = 0x310000de // 822083806 + P_FE2CL_PC_BUFF_UPDATE = 0x310000df // 822083807 + P_FE2CL_REP_PC_NEW_EMAIL = 0x310000e0 // 822083808 + P_FE2CL_REP_PC_READ_EMAIL_SUCC = 0x310000e1 // 822083809 + P_FE2CL_REP_PC_READ_EMAIL_FAIL = 0x310000e2 // 822083810 + P_FE2CL_REP_PC_RECV_EMAIL_PAGE_LIST_SUCC = 0x310000e3 // 822083811 + P_FE2CL_REP_PC_RECV_EMAIL_PAGE_LIST_FAIL = 0x310000e4 // 822083812 + P_FE2CL_REP_PC_DELETE_EMAIL_SUCC = 0x310000e5 // 822083813 + P_FE2CL_REP_PC_DELETE_EMAIL_FAIL = 0x310000e6 // 822083814 + P_FE2CL_REP_PC_SEND_EMAIL_SUCC = 0x310000e7 // 822083815 + P_FE2CL_REP_PC_SEND_EMAIL_FAIL = 0x310000e8 // 822083816 + P_FE2CL_REP_PC_RECV_EMAIL_ITEM_SUCC = 0x310000e9 // 822083817 + P_FE2CL_REP_PC_RECV_EMAIL_ITEM_FAIL = 0x310000ea // 822083818 + P_FE2CL_REP_PC_RECV_EMAIL_CANDY_SUCC = 0x310000eb // 822083819 + P_FE2CL_REP_PC_RECV_EMAIL_CANDY_FAIL = 0x310000ec // 822083820 + P_FE2CL_PC_SUDDEN_DEAD = 0x310000ed // 822083821 + P_FE2CL_REP_GM_REQ_TARGET_PC_SPECIAL_STATE_ONOFF_SUCC = 0x310000ee // 822083822 + P_FE2CL_REP_PC_SET_CURRENT_MISSION_ID = 0x310000ef // 822083823 + P_FE2CL_REP_NPC_GROUP_INVITE_FAIL = 0x310000f0 // 822083824 + P_FE2CL_REP_NPC_GROUP_INVITE_SUCC = 0x310000f1 // 822083825 + P_FE2CL_REP_NPC_GROUP_KICK_FAIL = 0x310000f2 // 822083826 + P_FE2CL_REP_NPC_GROUP_KICK_SUCC = 0x310000f3 // 822083827 + P_FE2CL_PC_EVENT = 0x310000f4 // 822083828 + P_FE2CL_REP_PC_TRANSPORT_WARP_SUCC = 0x310000f5 // 822083829 + P_FE2CL_REP_PC_TRADE_EMOTES_CHAT_FAIL = 0x310000f6 // 822083830 + P_FE2CL_REP_PC_RECV_EMAIL_ITEM_ALL_SUCC = 0x310000f7 // 822083831 + P_FE2CL_REP_PC_RECV_EMAIL_ITEM_ALL_FAIL = 0x310000f8 // 822083832 + P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC = 0x310000f9 // 822083833 + P_FE2CL_REP_CHANNEL_INFO = 0x310000fa // 822083834 + P_FE2CL_REP_PC_CHANNEL_NUM = 0x310000fb // 822083835 + P_FE2CL_REP_PC_WARP_CHANNEL_FAIL = 0x310000fc // 822083836 + P_FE2CL_REP_PC_WARP_CHANNEL_SUCC = 0x310000fd // 822083837 + P_FE2CL_REP_PC_FIND_NAME_MAKE_BUDDY_SUCC = 0x310000fe // 822083838 + P_FE2CL_REP_PC_FIND_NAME_MAKE_BUDDY_FAIL = 0x310000ff // 822083839 + P_FE2CL_REP_PC_FIND_NAME_ACCEPT_BUDDY_FAIL = 0x31000100 // 822083840 + P_FE2CL_REP_PC_BUDDY_WARP_SAME_SHARD_SUCC = 0x31000101 // 822083841 + P_FE2CL_PC_ATTACK_CHARs_SUCC = 0x31000102 // 822083842 + P_FE2CL_PC_ATTACK_CHARs = 0x31000103 // 822083843 + P_FE2CL_NPC_ATTACK_CHARs = 0x31000104 // 822083844 + P_FE2CL_REP_PC_CHANGE_LEVEL_SUCC = 0x31000105 // 822083845 + P_FE2CL_REP_PC_NANO_CREATE = 0x31000106 // 822083846 + P_FE2CL_PC_STREETSTALL_REP_READY_SUCC = 0x31000107 // 822083847 + P_FE2CL_PC_STREETSTALL_REP_READY_FAIL = 0x31000108 // 822083848 + P_FE2CL_PC_STREETSTALL_REP_CANCEL_SUCC = 0x31000109 // 822083849 + P_FE2CL_PC_STREETSTALL_REP_CANCEL_FAIL = 0x3100010a // 822083850 + P_FE2CL_PC_STREETSTALL_REP_REGIST_ITEM_SUCC = 0x3100010b // 822083851 + P_FE2CL_PC_STREETSTALL_REP_REGIST_ITEM_FAIL = 0x3100010c // 822083852 + P_FE2CL_PC_STREETSTALL_REP_UNREGIST_ITEM_SUCC = 0x3100010d // 822083853 + P_FE2CL_PC_STREETSTALL_REP_UNREGIST_ITEM_FAIL = 0x3100010e // 822083854 + P_FE2CL_PC_STREETSTALL_REP_SALE_START_SUCC = 0x3100010f // 822083855 + P_FE2CL_PC_STREETSTALL_REP_SALE_START_FAIL = 0x31000110 // 822083856 + P_FE2CL_PC_STREETSTALL_REP_ITEM_LIST = 0x31000111 // 822083857 + P_FE2CL_PC_STREETSTALL_REP_ITEM_LIST_FAIL = 0x31000112 // 822083858 + P_FE2CL_PC_STREETSTALL_REP_ITEM_BUY_SUCC_BUYER = 0x31000113 // 822083859 + P_FE2CL_PC_STREETSTALL_REP_ITEM_BUY_SUCC_SELLER = 0x31000114 // 822083860 + P_FE2CL_PC_STREETSTALL_REP_ITEM_BUY_FAIL = 0x31000115 // 822083861 + P_FE2CL_REP_PC_ITEM_COMBINATION_SUCC = 0x31000116 // 822083862 + P_FE2CL_REP_PC_ITEM_COMBINATION_FAIL = 0x31000117 // 822083863 + P_FE2CL_PC_CASH_BUFF_UPDATE = 0x31000118 // 822083864 + P_FE2CL_REP_PC_SKILL_ADD_SUCC = 0x31000119 // 822083865 + P_FE2CL_REP_PC_SKILL_ADD_FAIL = 0x3100011a // 822083866 + P_FE2CL_REP_PC_SKILL_DEL_SUCC = 0x3100011b // 822083867 + P_FE2CL_REP_PC_SKILL_DEL_FAIL = 0x3100011c // 822083868 + P_FE2CL_REP_PC_SKILL_USE_SUCC = 0x3100011d // 822083869 + P_FE2CL_REP_PC_SKILL_USE_FAIL = 0x3100011e // 822083870 + P_FE2CL_PC_SKILL_USE = 0x3100011f // 822083871 + P_FE2CL_PC_ROPE = 0x31000120 // 822083872 + P_FE2CL_PC_BELT = 0x31000121 // 822083873 + P_FE2CL_PC_VEHICLE_ON_SUCC = 0x31000122 // 822083874 + P_FE2CL_PC_VEHICLE_ON_FAIL = 0x31000123 // 822083875 + P_FE2CL_PC_VEHICLE_OFF_SUCC = 0x31000124 // 822083876 + P_FE2CL_PC_VEHICLE_OFF_FAIL = 0x31000125 // 822083877 + P_FE2CL_PC_QUICK_SLOT_INFO = 0x31000126 // 822083878 + P_FE2CL_REP_PC_REGIST_QUICK_SLOT_FAIL = 0x31000127 // 822083879 + P_FE2CL_REP_PC_REGIST_QUICK_SLOT_SUCC = 0x31000128 // 822083880 + P_FE2CL_PC_DELETE_TIME_LIMIT_ITEM = 0x31000129 // 822083881 + P_FE2CL_REP_PC_DISASSEMBLE_ITEM_SUCC = 0x3100012a // 822083882 + P_FE2CL_REP_PC_DISASSEMBLE_ITEM_FAIL = 0x3100012b // 822083883 + P_FE2CL_GM_REP_REWARD_RATE_SUCC = 0x3100012c // 822083884 + P_FE2CL_REP_PC_ITEM_ENCHANT_SUCC = 0x3100012d // 822083885 + P_FE2CL_REP_PC_ITEM_ENCHANT_FAIL = 0x3100012e // 822083886 + + P_LS2CL_REP_LOGIN_SUCC = 0x21000001 // 553648129 + P_LS2CL_REP_LOGIN_FAIL = 0x21000002 // 553648130 + P_LS2CL_REP_CHAR_INFO = 0x21000003 // 553648131 + P_LS2CL_REP_CHECK_CHAR_NAME_SUCC = 0x21000005 // 553648133 + P_LS2CL_REP_CHECK_CHAR_NAME_FAIL = 0x21000006 // 553648134 + P_LS2CL_REP_SAVE_CHAR_NAME_SUCC = 0x21000007 // 553648135 + P_LS2CL_REP_SAVE_CHAR_NAME_FAIL = 0x21000008 // 553648136 + P_LS2CL_REP_CHAR_CREATE_SUCC = 0x21000009 // 553648137 + P_LS2CL_REP_CHAR_CREATE_FAIL = 0x2100000a // 553648138 + P_LS2CL_REP_CHAR_SELECT_SUCC = 0x2100000b // 553648139 + P_LS2CL_REP_CHAR_SELECT_FAIL = 0x2100000c // 553648140 + P_LS2CL_REP_CHAR_DELETE_SUCC = 0x2100000d // 553648141 + P_LS2CL_REP_CHAR_DELETE_FAIL = 0x2100000e // 553648142 + P_LS2CL_REP_SHARD_SELECT_SUCC = 0x2100000f // 553648143 + P_LS2CL_REP_SHARD_SELECT_FAIL = 0x21000010 // 553648144 + P_LS2CL_REP_VERSION_CHECK_SUCC = 0x21000011 // 553648145 + P_LS2CL_REP_VERSION_CHECK_FAIL = 0x21000012 // 553648146 + P_LS2CL_REP_CHECK_NAME_LIST_SUCC = 0x21000013 // 553648147 + P_LS2CL_REP_CHECK_NAME_LIST_FAIL = 0x21000014 // 553648148 + P_LS2CL_REP_PC_EXIT_DUPLICATE = 0x21000015 // 553648149 + P_LS2CL_REQ_LIVE_CHECK = 0x21000016 // 553648150 + P_LS2CL_REP_CHANGE_CHAR_NAME_SUCC = 0x21000017 // 553648151 + P_LS2CL_REP_CHANGE_CHAR_NAME_FAIL = 0x21000018 // 553648152 + P_LS2CL_REP_SHARD_LIST_INFO_SUCC = 0x21000019 // 553648153 +) diff --git a/api/protocol/handler.go b/api/protocol/handler.go new file mode 100644 index 0000000..3c11dc6 --- /dev/null +++ b/api/protocol/handler.go @@ -0,0 +1,4 @@ +package protocol + +type PacketHandler interface { +} diff --git a/api/protocol/packet.go b/api/protocol/packet.go new file mode 100644 index 0000000..37f630a --- /dev/null +++ b/api/protocol/packet.go @@ -0,0 +1,227 @@ +package protocol + +import ( + "encoding/binary" + "fmt" + "log" + "reflect" + "strconv" + "unicode/utf16" + "unsafe" +) + +/* + this file handles serializing (and deserializing) structs to alignment-strict c structures +*/ + +type Packet struct { + ByteOrder binary.ByteOrder + Buf []byte + cursor int // to keep track of things like member alignment +} + +const PACK_ALIGN = 4 + +func NewPacket(sz int) *Packet { + newBuf := make([]byte, sz) + return &Packet{ByteOrder: binary.LittleEndian, Buf: newBuf} +} + +func (pkt *Packet) ResetCursor() { + pkt.cursor = 0 +} + +func (pkt *Packet) CompletePacket(typeID uint32) { + tmp := make([]byte, 4) + pkt.ByteOrder.PutUint32(tmp, typeID) + pkt.Buf = append(tmp, pkt.Buf...) +} + +func (pkt *Packet) writeRaw(data []byte) { + pkt.Buf = append(pkt.Buf, data...) + pkt.cursor += len(data) +} + +func (pkt *Packet) Write(data []byte) { + pkt.writeRaw(data) +} + +func (pkt *Packet) writeByte(data byte) { + pkt.Write([]byte{data}) +} + +func (pkt *Packet) readRaw(sz int) []byte { + data := pkt.Buf[:sz] + pkt.Buf = pkt.Buf[sz:] + pkt.cursor += sz + return data +} + +func (pkt *Packet) Read(sz int) []byte { + if sz > len(pkt.Buf) { + panic("Failed to read from packet, invalid size!") + } + + return pkt.readRaw(sz) +} + +func (pkt *Packet) readByte() byte { + return pkt.Read(1)[0] +} + +func (pkt *Packet) encodeStructField(field reflect.StructField, value reflect.Value) { + switch field.Type.Kind() { + case reflect.String: // all strings in fusionfall packets are encoded as utf16, we'll need to encode it + sz, err := strconv.Atoi(field.Tag.Get("size")) + if err != nil { + panic(fmt.Errorf("Failed to grab string 'size' tag!!")) + } + + buf16 := utf16.Encode([]rune(value.String())) + + // len(buf16) needs to be the same size as sz + if len(buf16) > sz { + // truncate + buf16 = buf16[:sz] + } else { + // grow + for len(buf16) < sz { + buf16 = append(buf16, 0) + } + } + + buf := *(*[]byte)(unsafe.Pointer(&buf16)) + pkt.Write(buf) + default: + pkt.Encode(value.Addr().Interface()) + } +} + +func (pkt *Packet) Encode(data interface{}) { + rv := reflect.Indirect(reflect.ValueOf(data)) + + switch rv.Kind() { + case reflect.Struct: + // walk through each struct fields + sz := rv.NumField() + for i := 0; i < sz; i++ { + pkt.encodeStructField(rv.Type().Field(i), rv.Field(i)) + } + case reflect.Slice: // (untested) + sz := rv.Len() + + // encode data + for i := 0; i < sz; i++ { + elem := rv.Index(i).Addr() + pkt.Encode(elem.Addr().Interface()) + } + case reflect.Uint8: + pkt.writeByte(byte(rv.Uint())) + case reflect.Uint16: + tmp := make([]byte, 2) + pkt.ByteOrder.PutUint16(tmp, uint16(rv.Uint())) + pkt.Write(tmp) + case reflect.Uint32: + tmp := make([]byte, 4) + pkt.ByteOrder.PutUint32(tmp, uint32(rv.Uint())) + pkt.Write(tmp) + case reflect.Uint64: + tmp := make([]byte, 8) + pkt.ByteOrder.PutUint64(tmp, uint64(rv.Uint())) + pkt.Write(tmp) + // im using the PutUintX() api here because it's functionally the same and apparently PutIntX doesn't exist? + case reflect.Int8: + pkt.writeByte(byte(rv.Int())) + case reflect.Int16: + tmp := make([]byte, 2) + pkt.ByteOrder.PutUint16(tmp, uint16(rv.Int())) + pkt.Write(tmp) + case reflect.Int32: + tmp := make([]byte, 4) + pkt.ByteOrder.PutUint32(tmp, uint32(rv.Int())) + pkt.Write(tmp) + case reflect.Int64: + tmp := make([]byte, 8) + pkt.ByteOrder.PutUint64(tmp, uint64(rv.Int())) + pkt.Write(tmp) + } +} + +func (pkt *Packet) decodeStructField(field reflect.StructField, value reflect.Value) { + log.Printf("Decoding '%s', current cursor: %d", field.Name, pkt.cursor) + + // read padding bytes + offset, err := strconv.Atoi(field.Tag.Get("offset")) + if err == nil { + for pkt.cursor < offset { + pkt.readByte() + } + } + + switch field.Type.Kind() { + case reflect.String: // all strings in fusionfall packets are encoded as utf16, we'll need to decode it + sz, err := strconv.Atoi(field.Tag.Get("size")) + if err != nil { + panic(fmt.Errorf("Failed to grab string 'size' tag!!")) + } + + // sz * sizeof(char16_t) + sz *= 2 + buf := make([]byte, 0, sz) + buf = append(buf, pkt.Read(sz)...) + + buf16 := *(*[]uint16)(unsafe.Pointer(&buf)) + + // find null terminator + var realSize int + for ; realSize < len(buf16); realSize++ { + if buf16[realSize] == 0 { + break + } + } + + str := string(utf16.Decode(buf16[:realSize])) + log.Printf(" got: %#.v or '%s'", buf16, str) + value.SetString(str) + default: + pkt.Decode(value.Addr().Interface()) + } +} + +func (pkt *Packet) Decode(data interface{}) { + rv := reflect.Indirect(reflect.ValueOf(data)) + + switch rv.Kind() { + case reflect.Struct: + // walk through each struct fields + sz := rv.NumField() + for i := 0; i < sz; i++ { + pkt.decodeStructField(rv.Type().Field(i), rv.Field(i)) + } + case reflect.Array: // (untested) + sz := rv.Len() + + // decode data + log.Print("reading array length ", sz, " cursor: ", pkt.cursor) + for i := 0; i < sz; i++ { + elem := rv.Index(i) + pkt.Decode(elem.Addr().Interface()) + } + case reflect.Uint8: + rv.SetUint(uint64(pkt.readByte())) + case reflect.Uint16: + rv.SetUint(uint64(pkt.ByteOrder.Uint16(pkt.Read(2)))) + case reflect.Uint32: + rv.SetUint(uint64(pkt.ByteOrder.Uint32(pkt.Read(4)))) + case reflect.Uint64: + rv.SetUint(pkt.ByteOrder.Uint64(pkt.Read(8))) + case reflect.Int8: + rv.SetInt(int64(pkt.readByte())) + case reflect.Int16: + rv.SetInt(int64(pkt.ByteOrder.Uint16(pkt.Read(2)))) + case reflect.Int32: + rv.SetInt(int64(pkt.ByteOrder.Uint32(pkt.Read(4)))) + case reflect.Int64: + rv.SetInt(int64(pkt.ByteOrder.Uint64(pkt.Read(8)))) + } +} diff --git a/api/protocol/structs.go b/api/protocol/structs.go new file mode 100644 index 0000000..a5be50a --- /dev/null +++ b/api/protocol/structs.go @@ -0,0 +1,12 @@ +package protocol + +type SP_CL2LS_REQ_LOGIN struct { + ID string `size:"33"` + Password string `size:"33"` + ClientVerA int32 + ClientVerB int32 + ClientVerC int32 + LoginType int32 + Cookie_TEGid [64]uint8 + Cookie_authid [255]uint8 +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5f3e231 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/CPunch/GoFusion + +go 1.19 diff --git a/server/server.go b/server/server.go new file mode 100644 index 0000000..d768760 --- /dev/null +++ b/server/server.go @@ -0,0 +1,101 @@ +package main + +import ( + "encoding/binary" + "fmt" + "log" + "net" + + "github.com/CPunch/GoFusion/api/protocol" +) + +const ( + E_KEY = "m@rQn~W#" + KEY_LENGTH = 8 +) + +func encrypt_byte_change_A(ERSize int, data []byte) int { + var num, num2, num3 int + + for num+ERSize <= len(data) { + num4 := num + num3 + num5 := num + (ERSize - 1 - num3) + + b := data[num4] + data[num4] = data[num5] + data[num5] = b + num += ERSize + num3++ + if num3 > ERSize/2 { + num3 = 0 + } + } + + num2 = ERSize - (num + ERSize - len(data)) + return num + num2 +} + +func xorData(buff, key []byte, size int) { + for i := 0; i < size; i++ { + buff[i] ^= key[i%KEY_LENGTH] + } +} + +func decryptData(buff, key []byte) { + ERSize := len(buff)%(KEY_LENGTH/2+1)*2 + KEY_LENGTH + size := encrypt_byte_change_A(ERSize, buff) + xorData(buff, key, size) +} + +func handle(conn net.Conn) { + defer func() { + conn.Close() + }() + + tmp := make([]byte, 4) + for { + // grab packet size + if _, err := conn.Read(tmp); err != nil { + panic(fmt.Errorf("[FATAL] failed to read packet size! %v", err)) + } + + sz := int(binary.LittleEndian.Uint32(tmp)) + pkt := protocol.NewPacket(sz) + + if _, err := conn.Read(pkt.Buf); err != nil { + panic(fmt.Errorf("[FATAL] failed to read packet body! %v", err)) + } + + decryptData(pkt.Buf, []byte(E_KEY)) + typeID := int(binary.LittleEndian.Uint32(pkt.Read(4))) + sizeof := len(pkt.Buf) + log.Printf("Got packet ID: %x\n", typeID) + + pkt.ResetCursor() + switch typeID { + case protocol.P_CL2LS_REQ_LOGIN: + var loginPkt protocol.SP_CL2LS_REQ_LOGIN + pkt.Decode(&loginPkt) + log.Printf("Got packet: %#v, with a sizeof: %d", loginPkt, sizeof) + default: + log.Printf("[WARN] unsupported packet ID: %x\n", typeID) + } + } +} + +func main() { + server, err := net.Listen("tcp", ":23000") + if err != nil { + log.Fatal(err) + } + + log.Print("Server hosted on 127.0.0.1:23000") + for { + conn, err := server.Accept() + if err != nil { + log.Println("Connection error: ", err) + return + } + go handle(conn) + } +}