From 868ab62573701bc51e0ca4fd4c1152e0ababaa33 Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Wed, 3 Sep 2025 11:27:01 -0500 Subject: [PATCH] build up packets and opcodes --- opcodes/emu.go | 646 +++++++++++++++++++++++++++++++++++++++++ opcodes/gen/main.go | 84 ++++++ opcodes/generated.go | 621 +++++++++++++++++++++++++++++++++++++++ opcodes/login.go | 70 +++++ opcodes/manager.go | 257 ++++++++++++++++ opcodes/protocol.go | 18 ++ opcodes/types.go | 12 + packets/apppacket.go | 245 ++++++++++++++++ packets/helpers.go | 43 +++ packets/packet.go | 89 ++++++ packets/protopacket.go | 281 ++++++++++++++++++ packets/types.go | 42 +++ 12 files changed, 2408 insertions(+) create mode 100644 opcodes/emu.go create mode 100644 opcodes/gen/main.go create mode 100644 opcodes/generated.go create mode 100644 opcodes/login.go create mode 100644 opcodes/manager.go create mode 100644 opcodes/protocol.go create mode 100644 opcodes/types.go create mode 100644 packets/apppacket.go create mode 100644 packets/helpers.go create mode 100644 packets/packet.go create mode 100644 packets/protopacket.go create mode 100644 packets/types.go diff --git a/opcodes/emu.go b/opcodes/emu.go new file mode 100644 index 0000000..56f1910 --- /dev/null +++ b/opcodes/emu.go @@ -0,0 +1,646 @@ +package opcodes + +// Emulator/Application opcodes - Complete list from emu_oplist.h +const ( + OP_Unknown EmuOpcode = 0x0000 + + // Login and session management + OP_LoginReplyMsg EmuOpcode = 0x0001 + OP_LoginByNumRequestMsg EmuOpcode = 0x0002 + OP_WSLoginRequestMsg EmuOpcode = 0x0003 + OP_ESInitMsg EmuOpcode = 0x0004 + OP_ESReadyForClientsMsg EmuOpcode = 0x0005 + + // Zone instance management + OP_CreateZoneInstanceMsg EmuOpcode = 0x0010 + OP_ZoneInstanceCreateReplyMsg EmuOpcode = 0x0011 + OP_ZoneInstanceDestroyedMsg EmuOpcode = 0x0012 + OP_ExpectClientAsCharacterRequest EmuOpcode = 0x0013 + OP_ExpectClientAsCharacterReplyMs EmuOpcode = 0x0014 + OP_ZoneInfoMsg EmuOpcode = 0x0015 + + // Character creation and loading + OP_CreateCharacterRequestMsg EmuOpcode = 0x0020 + OP_CreateCharacterReplyMsg EmuOpcode = 0x0021 + OP_CharacterCreateRequestMsg EmuOpcode = 0x0022 + OP_CharacterCreateReplyMsg EmuOpcode = 0x0023 + OP_DoneLoadingZoneResourcesMsg EmuOpcode = 0x0024 + OP_DoneSendingInitialEntitiesMsg EmuOpcode = 0x0025 + OP_DoneLoadingEntityResourcesMsg EmuOpcode = 0x0026 + OP_DoneLoadingUIResourcesMsg EmuOpcode = 0x0027 + + // World and time + OP_PredictionUpdateMsg EmuOpcode = 0x0030 + OP_RemoteCmdMsg EmuOpcode = 0x0031 + OP_SetRemoteCmdsMsg EmuOpcode = 0x0032 + OP_GameWorldTimeMsg EmuOpcode = 0x0033 + OP_MOTDMsg EmuOpcode = 0x0034 + OP_ZoneMOTDMsg EmuOpcode = 0x0035 + OP_SetTimeMsg EmuOpcode = 0x0036 + + // Guild recruitment + OP_GuildRecruitingMemberInfo EmuOpcode = 0x0040 + OP_GuildRecruiting EmuOpcode = 0x0041 + OP_GuildRecruitingDetails EmuOpcode = 0x0042 + OP_GuildRecruitingImage EmuOpcode = 0x0043 + + // Avatar and camping + OP_AvatarCreatedMsg EmuOpcode = 0x0050 + OP_AvatarDestroyedMsg EmuOpcode = 0x0051 + OP_RequestCampMsg EmuOpcode = 0x0052 + OP_MapRequest EmuOpcode = 0x0053 + OP_CampStartedMsg EmuOpcode = 0x0054 + OP_CampAbortedMsg EmuOpcode = 0x0055 + + // Who and monitor + OP_WhoQueryRequestMsg EmuOpcode = 0x0060 + OP_WhoQueryReplyMsg EmuOpcode = 0x0061 + OP_MonitorReplyMsg EmuOpcode = 0x0062 + OP_MonitorCharacterListMsg EmuOpcode = 0x0063 + OP_MonitorCharacterListRequestMsg EmuOpcode = 0x0064 + + // Client commands + OP_ClientCmdMsg EmuOpcode = 0x0070 + OP_Lottery EmuOpcode = 0x0071 + OP_DispatchClientCmdMsg EmuOpcode = 0x0072 + OP_DispatchESMsg EmuOpcode = 0x0073 + + // Target and opportunity + OP_UpdateTargetMsg EmuOpcode = 0x0080 + OP_UpdateOpportunityMsg EmuOpcode = 0x0081 + OP_UpdateTargetLocMsg EmuOpcode = 0x0082 + OP_RequestTargetLocMsg EmuOpcode = 0x0083 + + // Character updates + OP_UpdateCharacterSheetMsg EmuOpcode = 0x0090 + OP_UpdateSpellBookMsg EmuOpcode = 0x0091 + OP_UpdateInventoryMsg EmuOpcode = 0x0092 + OP_UpdateRecipeBookMsg EmuOpcode = 0x0093 + OP_RequestRecipeDetailsMsg EmuOpcode = 0x0094 + OP_RecipeDetailsMsg EmuOpcode = 0x0095 + OP_UpdateSkillBookMsg EmuOpcode = 0x0096 + OP_UpdateSkillsMsg EmuOpcode = 0x0097 + + // Zone changes and teleports + OP_ChangeZoneMsg EmuOpcode = 0x00a0 + OP_ClientTeleportRequestMsg EmuOpcode = 0x00a1 + OP_TeleportWithinZoneMsg EmuOpcode = 0x00a2 + OP_TeleportWithinZoneNoReloadMsg EmuOpcode = 0x00a3 + OP_MigrateClientToZoneRequestMsg EmuOpcode = 0x00a4 + OP_MigrateClientToZoneReplyMsg EmuOpcode = 0x00a5 + OP_ReadyToZoneMsg EmuOpcode = 0x00a6 + OP_ZoneChangeMsg EmuOpcode = 0x00a7 + OP_ZoneUnavailMsg EmuOpcode = 0x00a8 + + // Login and world interaction + OP_EnterWorldMsg EmuOpcode = 0x00f1 + OP_LoginAcceptedMsg EmuOpcode = 0x00f3 + OP_LoginFailedMsg2 EmuOpcode = 0x00f4 + OP_ExitWorldMsg EmuOpcode = 0x00f5 + OP_ClientIdMsg EmuOpcode = 0x00f8 + + // NPC interaction + OP_QueryHoodMsg EmuOpcode = 0x00f9 + OP_QueryNpcMsg EmuOpcode = 0x00fa + OP_AttackMsg EmuOpcode = 0x00fb + OP_DialogOpenMsg EmuOpcode = 0x00fc + OP_DialogSelectMsg EmuOpcode = 0x00fd + OP_ConversationMsg EmuOpcode = 0x00fe + OP_CloseWindowMsg EmuOpcode = 0x00ff + + // Group management - detailed + OP_RemoveClientFromGroupMsg EmuOpcode = 0x0200 + OP_RemoveGroupFromGroupMsg EmuOpcode = 0x0201 + OP_MakeGroupLeaderMsg EmuOpcode = 0x0202 + OP_GroupCreatedMsg EmuOpcode = 0x0203 + OP_GroupDestroyedMsg EmuOpcode = 0x0204 + OP_GroupMemberAddedMsg EmuOpcode = 0x0205 + OP_GroupMemberRemovedMsg EmuOpcode = 0x0206 + OP_GroupRemovedFromGroupMsg EmuOpcode = 0x0207 + OP_GroupLeaderChangedMsg EmuOpcode = 0x0208 + OP_GroupSettingsChangedMsg EmuOpcode = 0x0209 + OP_GroupOptionsMsg EmuOpcode = 0x020a + OP_GroupInviteRequestMsg EmuOpcode = 0x020b + OP_GroupInviteResponseMsg EmuOpcode = 0x020c + OP_GroupDeclineResponseMsg EmuOpcode = 0x020d + OP_DefaultGroupOptionsRequestMsg EmuOpcode = 0x020e + OP_DefaultGroupOptionsMsg EmuOpcode = 0x020f + OP_DisplayGroupOptionsScreenMsg EmuOpcode = 0x0210 + OP_CloseGroupInviteWindowMsg EmuOpcode = 0x0211 + OP_UpdateGroupMemberDataMsg EmuOpcode = 0x0212 + + // ES (Emulator Server) status + OP_SendLatestRequestMsg EmuOpcode = 0x0220 + OP_ClearDataMsg EmuOpcode = 0x0221 + OP_SetSocialMsg EmuOpcode = 0x0222 + OP_ESStatusMsg EmuOpcode = 0x0223 + OP_ESZoneInstanceStatusMsg EmuOpcode = 0x0224 + OP_ZonesStatusRequestMsg EmuOpcode = 0x0225 + OP_ZonesStatusMsg EmuOpcode = 0x0226 + OP_ESWeatherRequestMsg EmuOpcode = 0x0227 + OP_ESWeatherRequestEndMsg EmuOpcode = 0x0228 + + // Chat system + OP_ChatMsg EmuOpcode = 0x0300 + OP_ChatFiltersMsg EmuOpcode = 0x0301 + OP_TellMsg EmuOpcode = 0x0302 + OP_ChatRelationshipUpdateMsg EmuOpcode = 0x0303 + OP_ChatCreateChannelMsg EmuOpcode = 0x0304 + OP_ChatJoinChannelMsg EmuOpcode = 0x0305 + OP_ChatWhoChannelMsg EmuOpcode = 0x0306 + OP_ChatLeaveChannelMsg EmuOpcode = 0x0307 + OP_ChatTellChannelMsg EmuOpcode = 0x0308 + OP_ChatTellUserMsg EmuOpcode = 0x0309 + OP_ChatToggleFriendMsg EmuOpcode = 0x030a + OP_ChatToggleIgnoreMsg EmuOpcode = 0x030b + OP_ChatSendFriendsMsg EmuOpcode = 0x030c + OP_ChatSendIgnoresMsg EmuOpcode = 0x030d + + // Trade system + OP_TradeRequestMsg EmuOpcode = 0x0400 + OP_TradeResponseMsg EmuOpcode = 0x0401 + OP_TradeStartMsg EmuOpcode = 0x0402 + OP_TradeEndMsg EmuOpcode = 0x0403 + OP_TradeAddItemMsg EmuOpcode = 0x0404 + OP_TradeRemoveItemMsg EmuOpcode = 0x0405 + OP_TradeAcceptMsg EmuOpcode = 0x0406 + + // Inventory and items + OP_InventoryMsg EmuOpcode = 0x0500 + OP_EquipItemMsg EmuOpcode = 0x0501 + OP_UnequipItemMsg EmuOpcode = 0x0502 + OP_DeleteItemMsg EmuOpcode = 0x0503 + OP_UseItemMsg EmuOpcode = 0x0504 + OP_ExamineItemRequestMsg EmuOpcode = 0x0505 + OP_ExamineItemMsg EmuOpcode = 0x0506 + OP_ExamineInfoRequestMsg EmuOpcode = 0x0507 + OP_LootItemsRequestMsg EmuOpcode = 0x0508 + OP_StoppedLootingMsg EmuOpcode = 0x0509 + + // Combat and skills + OP_ConsiderMsg EmuOpcode = 0x0600 + OP_TargetMsg EmuOpcode = 0x0601 + OP_AutoAttackMsg EmuOpcode = 0x0602 + OP_CastSpellMsg EmuOpcode = 0x0603 + OP_InterruptSpellMsg EmuOpcode = 0x0604 + OP_SkillInfoRequestMsg EmuOpcode = 0x0605 + OP_SkillInfoResponseMsg EmuOpcode = 0x0606 + OP_SkillInfoRequest EmuOpcode = 0x0607 + OP_SkillInfoResponse EmuOpcode = 0x0608 + OP_RemoveSpellEffectMsg EmuOpcode = 0x0609 + OP_RemoveConcentrationMsg EmuOpcode = 0x060a + OP_CancelSpellCast EmuOpcode = 0x060b + OP_AttackNotAllowed EmuOpcode = 0x060c + OP_AttackAllowed EmuOpcode = 0x060d + OP_PopulateSkillMapsMsg EmuOpcode = 0x060e + OP_CancelledFeignMsg EmuOpcode = 0x060f + OP_SignalMsg EmuOpcode = 0x0610 + OP_DispatchSpellCmdMsg EmuOpcode = 0x0611 + + // Player status + OP_PlayerStatsMsg EmuOpcode = 0x0700 + OP_PlayerBioMsg EmuOpcode = 0x0701 + OP_PlayerProfileMsg EmuOpcode = 0x0702 + OP_LevelUpMsg EmuOpcode = 0x0703 + OP_ExpUpdateMsg EmuOpcode = 0x0704 + OP_SkillUpMsg EmuOpcode = 0x0705 + OP_LevelChangedMsg EmuOpcode = 0x0706 + OP_SpellGainedMsg EmuOpcode = 0x0707 + OP_UpdatePositionMsg EmuOpcode = 0x0708 + OP_SitMsg EmuOpcode = 0x0709 + OP_StandMsg EmuOpcode = 0x070a + OP_SatMsg EmuOpcode = 0x070b + OP_StoodMsg EmuOpcode = 0x070c + OP_AvatarUpdateMsg EmuOpcode = 0x070d + OP_BioUpdateMsg EmuOpcode = 0x070e + OP_InspectPlayerMsg EmuOpcode = 0x070f + OP_AFKUpdateMsg EmuOpcode = 0x0710 + OP_AnonUpdateMsg EmuOpcode = 0x0711 + OP_LFGUpdateMsg EmuOpcode = 0x0712 + + // Zone and world + OP_ZoneListMsg EmuOpcode = 0x0800 + OP_ZoneEntryMsg EmuOpcode = 0x0801 + OP_ZoneExitMsg EmuOpcode = 0x0802 + OP_NewZoneMsg EmuOpcode = 0x0803 + OP_SendZonePointsMsg EmuOpcode = 0x0804 + OP_ZonePointsMsg EmuOpcode = 0x0805 + OP_WorldPingMsg EmuOpcode = 0x0806 + OP_WorldShutdownUpdateMsg EmuOpcode = 0x0807 + OP_RestartZoneMsg EmuOpcode = 0x0808 + OP_UpdateActivePublicZonesMsg EmuOpcode = 0x0809 + OP_WorldDataUpdateMsg EmuOpcode = 0x080a + OP_WorldDataChangeMsg EmuOpcode = 0x080b + OP_ClientTeleportToLocationMsg EmuOpcode = 0x080c + OP_UpdateMotdMsg EmuOpcode = 0x080d + + // Housing system + OP_HousingDataMsg EmuOpcode = 0x0900 + OP_HouseItemsList EmuOpcode = 0x0901 + OP_HousePurchase EmuOpcode = 0x0902 + OP_HousePayUpkeep EmuOpcode = 0x0903 + OP_PayHouseUpkeepMsg EmuOpcode = 0x0904 + OP_HouseDeletedRemotelyMsg EmuOpcode = 0x0905 + OP_UpdateHouseDataMsg EmuOpcode = 0x0906 + OP_UpdateHouseAccessDataMsg EmuOpcode = 0x0907 + OP_PlayerHouseBaseScreenMsg EmuOpcode = 0x0908 + OP_PlayerHousePurchaseScreenMsg EmuOpcode = 0x0909 + OP_PlayerHouseAccessUpdateMsg EmuOpcode = 0x090a + OP_PlayerHouseDisplayStatusMsg EmuOpcode = 0x090b + OP_PlayerHouseCloseUIMsg EmuOpcode = 0x090c + OP_BuyPlayerHouseMsg EmuOpcode = 0x090d + OP_BuyPlayerHouseTintMsg EmuOpcode = 0x090e + OP_CollectAllHouseItemsMsg EmuOpcode = 0x090f + OP_RelinquishHouseMsg EmuOpcode = 0x0910 + OP_EnterHouseMsg EmuOpcode = 0x0911 + OP_ExitHouseMsg EmuOpcode = 0x0912 + OP_HouseDefaultAccessSetMsg EmuOpcode = 0x0913 + OP_HouseAccessSetMsg EmuOpcode = 0x0914 + OP_HouseAccessRemoveMsg EmuOpcode = 0x0915 + OP_HousingDataChangedMsg EmuOpcode = 0x0916 + OP_HousingRestoreMsg EmuOpcode = 0x0917 + OP_HouseCustomizationScreenMsg EmuOpcode = 0x0918 + OP_CustomizationPurchaseRequestMs EmuOpcode = 0x0919 + OP_CustomizationSetRequestMsg EmuOpcode = 0x091a + OP_CustomizationReplyMsg EmuOpcode = 0x091b + OP_TintWidgetsMsg EmuOpcode = 0x091c + OP_MoveableObjectPlacementCriteri EmuOpcode = 0x091d + OP_EnterMoveObjectModeMsg EmuOpcode = 0x091e + OP_PositionMoveableObject EmuOpcode = 0x091f + OP_CancelMoveObjectModeMsg EmuOpcode = 0x0920 + OP_ShaderCustomizationMsg EmuOpcode = 0x0921 + OP_ReplaceableSubMeshesMsg EmuOpcode = 0x0922 + OP_CharacterHousingList EmuOpcode = 0x0923 + OP_CharacterCreatedDungeons EmuOpcode = 0x0924 + + // Achievement system + OP_AchievementUpdateMsg EmuOpcode = 0x0a00 + OP_AchievementCompleteMsg EmuOpcode = 0x0a01 + OP_CharacterAchievements EmuOpcode = 0x0a02 + + // Keybinds, macros and UI + OP_KeybindUpdateMsg EmuOpcode = 0x0b00 + OP_KeybindLoadMsg EmuOpcode = 0x0b01 + OP_MacroUpdateMsg EmuOpcode = 0x0b02 + OP_UISettingsMsg EmuOpcode = 0x0b03 + OP_UISettingsResponseMsg EmuOpcode = 0x0b04 + OP_UIResetMsg EmuOpcode = 0x0b05 + OP_KeymapLoadMsg EmuOpcode = 0x0b06 + OP_KeymapNoneMsg EmuOpcode = 0x0b07 + OP_KeymapDataMsg EmuOpcode = 0x0b08 + OP_KeymapSaveMsg EmuOpcode = 0x0b09 + OP_QuickbarInitMsg EmuOpcode = 0x0b0a + OP_QuickbarUpdateMsg EmuOpcode = 0x0b0b + OP_MacroInitMsg EmuOpcode = 0x0b0c + OP_QuestionnaireMsg EmuOpcode = 0x0b0d + OP_DisplayInnVisitScreenMsg EmuOpcode = 0x0b0e + OP_DisplayWarningMsg EmuOpcode = 0x0b0f + OP_OnscreenMsgMsg EmuOpcode = 0x0b10 + OP_DisplayMailScreenMsg EmuOpcode = 0x0b11 + OP_UIEvent EmuOpcode = 0x0b12 + OP_LoadWelcomeWindow EmuOpcode = 0x0b13 + OP_LoadCalendarEvents EmuOpcode = 0x0b14 + + // Mail system + OP_MailGetHeadersRequestMsg EmuOpcode = 0x0c00 + OP_MailGetHeadersReplyMsg EmuOpcode = 0x0c01 + OP_MailGetMessageRequestMsg EmuOpcode = 0x0c02 + OP_MailGetMessageReplyMsg EmuOpcode = 0x0c03 + OP_MailSendMessageRequestMsg EmuOpcode = 0x0c04 + OP_MailSendMessageReplyMsg EmuOpcode = 0x0c05 + OP_MailDeleteMessageRequestMsg EmuOpcode = 0x0c06 + OP_MailGetMessageMsg EmuOpcode = 0x0c07 + OP_MailSendMessageMsg EmuOpcode = 0x0c08 + OP_MailDeleteMessageMsg EmuOpcode = 0x0c09 + OP_MailCommitSendMessageMsg EmuOpcode = 0x0c0a + OP_MailSendSystemMessageMsg EmuOpcode = 0x0c0b + OP_MailRemoveAttachFromMailMsg EmuOpcode = 0x0c0c + OP_MailEventNotificationMsg EmuOpcode = 0x0c0d + OP_CorruptedClientMsg EmuOpcode = 0x0c0e + OP_NotifyApprenticeStoppedMentori EmuOpcode = 0x0c0f + + // Quest system + OP_QuestJournalUpdateMsg EmuOpcode = 0x0d00 + OP_QuestJournalReplyMsg EmuOpcode = 0x0d01 + OP_QuestOfferMsg EmuOpcode = 0x0d02 + OP_QuestRewardMsg EmuOpcode = 0x0d03 + OP_QuestCompleteMsg EmuOpcode = 0x0d04 + OP_QuestFailedMsg EmuOpcode = 0x0d05 + OP_OfferQuestMsg EmuOpcode = 0x0d06 + OP_QuestJournalOpenMsg EmuOpcode = 0x0d07 + OP_QuestJournalInspectMsg EmuOpcode = 0x0d08 + OP_QuestJournalSetVisibleMsg EmuOpcode = 0x0d09 + OP_QuestJournalWaypointMsg EmuOpcode = 0x0d0a + OP_QuestReward EmuOpcode = 0x0d0b + OP_JournalQuestStoryline EmuOpcode = 0x0d0c + OP_DailyObjectives EmuOpcode = 0x0d0d + + // Guild operations extended + OP_GuildUpdateMsg EmuOpcode = 0x0e00 + OP_CreateGuildRequestMsg EmuOpcode = 0x0e01 + OP_CreateGuildReplyMsg EmuOpcode = 0x0e02 + OP_GuildInviteMsg EmuOpcode = 0x0e03 + OP_GuildInviteResponseMsg EmuOpcode = 0x0e04 + OP_GuildKickMsg EmuOpcode = 0x0e05 + OP_GuildMotdMsg EmuOpcode = 0x0e06 + OP_GuildsayMsg EmuOpcode = 0x0e07 + OP_FellowshipExpMsg EmuOpcode = 0x0e08 + OP_ModifyGuildMsg EmuOpcode = 0x0e09 + OP_GuildEventMsg EmuOpcode = 0x0e0a + OP_GuildEventAddMsg EmuOpcode = 0x0e0b + OP_GuildEventActionMsg EmuOpcode = 0x0e0c + OP_GuildEventListMsg EmuOpcode = 0x0e0d + OP_RequestGuildEventDetailsMsg EmuOpcode = 0x0e0e + OP_GuildEventDetailsMsg EmuOpcode = 0x0e0f + OP_RequestGuildBankEventDetailsMs EmuOpcode = 0x0e10 + OP_GuildBankUpdateMsg EmuOpcode = 0x0e11 + OP_GuildBankEventListMsg EmuOpcode = 0x0e12 + OP_RenameGuildMsg EmuOpcode = 0x0e13 + OP_DeleteGuildMsg EmuOpcode = 0x0e14 + OP_RequestGuildMembershipMsg EmuOpcode = 0x0e15 + OP_GuildMembershipResponseMsg EmuOpcode = 0x0e16 + OP_LeaveGuildNotifyMsg EmuOpcode = 0x0e17 + OP_JoinGuildNotifyMsg EmuOpcode = 0x0e18 + OP_RequestGuildInfoMsg EmuOpcode = 0x0e19 + + // Consignment and broker + OP_ConsignmentCloseStoreMsg EmuOpcode = 0x0f00 + OP_ConsignItemRequestMsg EmuOpcode = 0x0f01 + OP_ConsignItemResponseMsg EmuOpcode = 0x0f02 + OP_PurchaseConsignmentLoreCheckRe EmuOpcode = 0x0f03 + OP_ExamineConsignmentRequestMsg EmuOpcode = 0x0f04 + OP_ExamineConsignmentResponseMsg EmuOpcode = 0x0f05 + OP_ConsignViewCreateMsg EmuOpcode = 0x0f06 + OP_ConsignViewGetPageMsg EmuOpcode = 0x0f07 + OP_ConsignViewReleaseMsg EmuOpcode = 0x0f08 + OP_ConsignRemoveItemsMsg EmuOpcode = 0x0f09 + OP_ConsignViewSortMsg EmuOpcode = 0x0f0a + OP_BrokerAddBag EmuOpcode = 0x0f0b + + // Character transfer + OP_CharTransferStartRequestMsg EmuOpcode = 0x1000 + OP_CharTransferStartReplyMsg EmuOpcode = 0x1001 + OP_CharTransferRequestMsg EmuOpcode = 0x1002 + OP_CharTransferReplyMsg EmuOpcode = 0x1003 + OP_CharTransferRollbackRequestMsg EmuOpcode = 0x1004 + OP_CharTransferCommitRequestMsg EmuOpcode = 0x1005 + OP_CharTransferRollbackReplyMsg EmuOpcode = 0x1006 + OP_CharTransferCommitReplyMsg EmuOpcode = 0x1007 + OP_GetCharacterSerializedRequestM EmuOpcode = 0x1008 + OP_GetCharacterSerializedReplyMsg EmuOpcode = 0x1009 + OP_CreateCharFromCBBRequestMsg EmuOpcode = 0x100a + OP_CreateCharFromCBBReplyMsg EmuOpcode = 0x100b + OP_CharTransferValidateRequestMsg EmuOpcode = 0x100c + OP_CharTransferValidateReplyMsg EmuOpcode = 0x100d + OP_CharacterLinkdeadMsg EmuOpcode = 0x100e + + // Auction system + OP_AuctionItem EmuOpcode = 0x1100 + OP_AuctionItemReply EmuOpcode = 0x1101 + OP_AuctionCoin EmuOpcode = 0x1102 + OP_AuctionCoinReply EmuOpcode = 0x1103 + OP_AuctionCharacter EmuOpcode = 0x1104 + OP_AuctionCharacterReply EmuOpcode = 0x1105 + OP_AuctionCommitMsg EmuOpcode = 0x1106 + OP_AuctionAbortMsg EmuOpcode = 0x1107 + + // EQ command system (client commands) + OP_EqHearChatCmd EmuOpcode = 0x1200 + OP_EqDisplayTextCmd EmuOpcode = 0x1201 + OP_EqCreateGhostCmd EmuOpcode = 0x1202 + OP_EqCreateWidgetCmd EmuOpcode = 0x1203 + OP_EqCreateSignWidgetCmd EmuOpcode = 0x1204 + OP_EqDestroyGhostCmd EmuOpcode = 0x1205 + OP_EqUpdateGhostCmd EmuOpcode = 0x1206 + OP_EqSetControlGhostCmd EmuOpcode = 0x1207 + OP_EqSetPOVGhostCmd EmuOpcode = 0x1208 + OP_EqHearCombatCmd EmuOpcode = 0x1209 + OP_EqHearSpellCastCmd EmuOpcode = 0x120a + OP_EqHearSpellInterruptCmd EmuOpcode = 0x120b + OP_EqHearSpellFizzleCmd EmuOpcode = 0x120c + OP_EqHearConsiderCmd EmuOpcode = 0x120d + OP_EqUpdateSubClassesCmd EmuOpcode = 0x120e + OP_EqCreateListBoxCmd EmuOpcode = 0x120f + OP_EqSetDebugPathPointsCmd EmuOpcode = 0x1210 + OP_EqCannedEmoteCmd EmuOpcode = 0x1211 + OP_EqStateCmd EmuOpcode = 0x1212 + OP_EqPlaySoundCmd EmuOpcode = 0x1213 + OP_EqPlaySound3DCmd EmuOpcode = 0x1214 + OP_EqPlayVoiceCmd EmuOpcode = 0x1215 + OP_EqHearDrowningCmd EmuOpcode = 0x1216 + OP_EqHearDeathCmd EmuOpcode = 0x1217 + OP_EqGroupMemberRemovedCmd EmuOpcode = 0x1218 + OP_EqHearChainEffectCmd EmuOpcode = 0x1219 + OP_EqReceiveOfferCmd EmuOpcode = 0x121a + OP_EqInspectPCResultsCmd EmuOpcode = 0x121b + OP_EqDrawablePathGraphCmd EmuOpcode = 0x121c + OP_EqDialogOpenCmd EmuOpcode = 0x121d + OP_EqDialogCloseCmd EmuOpcode = 0x121e + OP_EqCollectionUpdateCmd EmuOpcode = 0x121f + OP_EqCollectionFilterCmd EmuOpcode = 0x1220 + OP_EqCollectionItemCmd EmuOpcode = 0x1221 + OP_EqQuestJournalUpdateCmd EmuOpcode = 0x1222 + OP_EqQuestJournalReplyCmd EmuOpcode = 0x1223 + OP_EqQuestGroupCmd EmuOpcode = 0x1224 + OP_EqUpdateMerchantCmd EmuOpcode = 0x1225 + OP_EqUpdateStoreCmd EmuOpcode = 0x1226 + OP_EqUpdatePlayerTradeCmd EmuOpcode = 0x1227 + OP_EqHelpPathCmd EmuOpcode = 0x1228 + OP_EqHelpPathClearCmd EmuOpcode = 0x1229 + OP_EqUpdateBankCmd EmuOpcode = 0x122a + OP_EqExamineInfoCmd EmuOpcode = 0x122b + OP_EqCloseWindowCmd EmuOpcode = 0x122c + OP_EqUpdateLootCmd EmuOpcode = 0x122d + OP_EqJunctionListCmd EmuOpcode = 0x122e + OP_EqShowDeathWindowCmd EmuOpcode = 0x122f + OP_EqDisplaySpellFailCmd EmuOpcode = 0x1230 + OP_EqSpellCastStartCmd EmuOpcode = 0x1231 + OP_EqSpellCastEndCmd EmuOpcode = 0x1232 + OP_EqResurrectedCmd EmuOpcode = 0x1233 + OP_EqChoiceWinCmd EmuOpcode = 0x1234 + OP_EqSetDefaultVerbCmd EmuOpcode = 0x1235 + OP_EqInstructionWindowCmd EmuOpcode = 0x1236 + OP_EqInstructionWindowCloseCmd EmuOpcode = 0x1237 + OP_EqInstructionWindowGoalCmd EmuOpcode = 0x1238 + OP_EqInstructionWindowTaskCmd EmuOpcode = 0x1239 + OP_EqEnableGameEventCmd EmuOpcode = 0x123a + OP_EqShowWindowCmd EmuOpcode = 0x123b + OP_EqEnableWindowCmd EmuOpcode = 0x123c + OP_EqFlashWindowCmd EmuOpcode = 0x123d + OP_EqHearPlayFlavorCmd EmuOpcode = 0x123e + OP_EqUpdateSignWidgetCmd EmuOpcode = 0x123f + OP_EqDebugPVDCmd EmuOpcode = 0x1240 + OP_EqShowBookCmd EmuOpcode = 0x1241 + OP_EqQuestionnaireCmd EmuOpcode = 0x1242 + OP_EqGetProbsCmd EmuOpcode = 0x1243 + OP_EqHearHealCmd EmuOpcode = 0x1244 + OP_EqChatChannelUpdateCmd EmuOpcode = 0x1245 + OP_EqWhoChannelQueryReplyCmd EmuOpcode = 0x1246 + OP_EqAvailWorldChannelsCmd EmuOpcode = 0x1247 + OP_EqUpdateTargetCmd EmuOpcode = 0x1248 + OP_EqConsignmentItemsCmd EmuOpcode = 0x1249 + OP_EqStartBrokerCmd EmuOpcode = 0x124a + OP_EqMapExplorationCmd EmuOpcode = 0x124b + OP_EqStoreLogCmd EmuOpcode = 0x124c + OP_EqSpellMoveToRangeAndRetryCmd EmuOpcode = 0x124d + OP_EqUpdatePlayerMailCmd EmuOpcode = 0x124e + OP_EqFactionUpdateCmd EmuOpcode = 0x124f + OP_EQHearThreatCmd EmuOpcode = 0x1250 + OP_EqHearSpellNoLandCmd EmuOpcode = 0x1251 + OP_EQHearDispellCmd EmuOpcode = 0x1252 + OP_EqTargetItemCmd EmuOpcode = 0x1253 + + // Various game features + OP_DialogCloseMsg EmuOpcode = 0x1300 + OP_UpdateTitleCmd EmuOpcode = 0x1301 + OP_BadLanguageFilter EmuOpcode = 0x1302 + OP_DressingRoom EmuOpcode = 0x1303 + OP_TraitsList EmuOpcode = 0x1304 + OP_PointOfInterest EmuOpcode = 0x1305 + OP_AdventureList EmuOpcode = 0x1306 + OP_RecipeList EmuOpcode = 0x1307 + OP_BagOptions EmuOpcode = 0x1308 + OP_PetOptions EmuOpcode = 0x1309 + OP_CharacterPet EmuOpcode = 0x130a + OP_ClearForTakeOffMsg EmuOpcode = 0x130b + OP_CharacterCurrency EmuOpcode = 0x130c + OP_TradeskillList EmuOpcode = 0x130d + OP_RecipeBook EmuOpcode = 0x130e + OP_CharacterMerc EmuOpcode = 0x130f + OP_AfterInvSpellUpdate EmuOpcode = 0x1310 + OP_CharacterMounts EmuOpcode = 0x1311 + OP_DungeonMakerItemRequest EmuOpcode = 0x1312 + OP_SysClient EmuOpcode = 0x1313 + OP_LFGGroupSearch EmuOpcode = 0x1314 + OP_MarketPlacePrices EmuOpcode = 0x1315 + OP_MarketFundsUpdate EmuOpcode = 0x1316 + OP_MarketAddFundsRequest EmuOpcode = 0x1317 + OP_ZoneBgInstanceList EmuOpcode = 0x1318 + OP_Launchpad EmuOpcode = 0x1319 + OP_Weakness EmuOpcode = 0x131a + OP_SavageBarInitMsg EmuOpcode = 0x131b + OP_PetOptionsResponse EmuOpcode = 0x131c + OP_CurrentPet EmuOpcode = 0x131d + OP_RecipeListUnknown EmuOpcode = 0x131e + OP_ClearForLandingMsg EmuOpcode = 0x131f + OP_LikeOption EmuOpcode = 0x1320 + OP_HeritageMsg EmuOpcode = 0x1321 + OP_OpenCharCust EmuOpcode = 0x1322 + OP_PaperdollImage EmuOpcode = 0x1323 + OP_ReadyForTakeOffMsg EmuOpcode = 0x1324 + OP_EarlyLandingRequestMsg EmuOpcode = 0x1325 + OP_SubmitCharCust EmuOpcode = 0x1326 + OP_DietyAbilityWindow EmuOpcode = 0x1327 + OP_ArenaGameTypesMsg EmuOpcode = 0x1328 + OP_RaceRestrictionMsg EmuOpcode = 0x1329 + OP_SetInstanceDisplayNameMsg EmuOpcode = 0x132a + + // Entity and verbs + OP_EntityVerbsRequestMsg EmuOpcode = 0x1400 + OP_EntityVerbsReplyMsg EmuOpcode = 0x1401 + OP_EntityVerbsVerbMsg EmuOpcode = 0x1402 + + // Waypoints and navigation + OP_WaypointRequestMsg EmuOpcode = 0x1500 + OP_WaypointReplyMsg EmuOpcode = 0x1501 + OP_WaypointSelectMsg EmuOpcode = 0x1502 + OP_WaypointUpdateMsg EmuOpcode = 0x1503 + OP_ZoneToFriendRequestMsg EmuOpcode = 0x1504 + OP_ZoneToFriendReplyMsg EmuOpcode = 0x1505 + OP_FlightPathsMsg EmuOpcode = 0x1506 + OP_ShowZoneTeleporterDestinations EmuOpcode = 0x1507 + OP_SelectZoneTeleporterDestinatio EmuOpcode = 0x1508 + + // CS Tools and tickets + OP_CSTicketHeaderRequestMsg EmuOpcode = 0x1600 + OP_CSTicketInfoMsg EmuOpcode = 0x1601 + OP_CSTicketCommentRequestMsg EmuOpcode = 0x1602 + OP_CSTicketCommentResponseMsg EmuOpcode = 0x1603 + OP_CSTicketCreateMsg EmuOpcode = 0x1604 + OP_CSTicketAddCommentMsg EmuOpcode = 0x1605 + OP_CSTicketDeleteMsg EmuOpcode = 0x1606 + OP_CSTicketChangeNotificationMsg EmuOpcode = 0x1607 + OP_CSToolsRequestMsg EmuOpcode = 0x1608 + OP_CSToolsResponseMsg EmuOpcode = 0x1609 + OP_CSToolAccessResponseMsg EmuOpcode = 0x160a + OP_GetAvatarAccessRequestForCSToo EmuOpcode = 0x160b + OP_CsCategoryRequestMsg EmuOpcode = 0x160c + OP_CsCategoryResponseMsg EmuOpcode = 0x160d + + // Knowledge base + OP_KnowledgebaseRequestMsg EmuOpcode = 0x1700 + OP_KnowledgebaseResponseMsg EmuOpcode = 0x1701 + OP_KnowledgeWindowSlotMappingMsg EmuOpcode = 0x1702 + OP_KnownLanguagesMsg EmuOpcode = 0x1703 + + // Tracking + OP_TrackingUpdateMsg EmuOpcode = 0x1800 + OP_BeginTrackingMsg EmuOpcode = 0x1801 + OP_StopTrackingMsg EmuOpcode = 0x1802 + + // Advancement + OP_AdvancementRequestMsg EmuOpcode = 0x1900 + + // Map fog + OP_MapFogDataInitMsg EmuOpcode = 0x1a00 + OP_MapFogDataUpdateMsg EmuOpcode = 0x1a01 + + // Crafting + OP_ShowCreateFromRecipeUIMsg EmuOpcode = 0x1b00 + OP_CancelCreateFromRecipeMsg EmuOpcode = 0x1b01 + OP_BeginItemCreationMsg EmuOpcode = 0x1b02 + OP_StopItemCreationMsg EmuOpcode = 0x1b03 + OP_ShowItemCreationProcessUIMsg EmuOpcode = 0x1b04 + OP_UpdateItemCreationProcessUIMsg EmuOpcode = 0x1b05 + OP_DisplayTSEventReactionMsg EmuOpcode = 0x1b06 + OP_ShowRecipeBookMsg EmuOpcode = 0x1b07 + + // Boat transport + OP_CreateBoatTransportsMsg EmuOpcode = 0x1c00 + OP_PositionBoatTransportMsg EmuOpcode = 0x1c01 + OP_MigrateBoatTransportMsg EmuOpcode = 0x1c02 + OP_MigrateBoatTransportReplyMsg EmuOpcode = 0x1c03 + + // Debug + OP_DisplayDebugNLLPointsMsg EmuOpcode = 0x1d00 + OP_UpdateDebugRadiiMsg EmuOpcode = 0x1d01 + OP_DumpSchedulerMsg EmuOpcode = 0x1d02 + + // Client state + OP_UpdateClientPredFlagsMsg EmuOpcode = 0x1e00 + OP_ChangeServerControlFlagMsg EmuOpcode = 0x1e01 + OP_ClientIdleBeginMsg EmuOpcode = 0x1e02 + OP_ClientIdleEndMsg EmuOpcode = 0x1e03 + OP_ClientFellMsg EmuOpcode = 0x1e04 + OP_ClientInDeathRegionMsg EmuOpcode = 0x1e05 + OP_CampClientMsg EmuOpcode = 0x1e06 + + // Various + OP_RewardPackMsg EmuOpcode = 0x1f00 + OP_CharNameChangedMsg EmuOpcode = 0x1f01 + OP_ReloadLocalizedTxtMsg EmuOpcode = 0x1f02 + OP_UnknownNpcMsg EmuOpcode = 0x1f03 + OP_PromoFlagsDetailsMsg EmuOpcode = 0x1f04 + OP_ReportMsg EmuOpcode = 0x1f05 + OP_UpdateRaidMsg EmuOpcode = 0x1f06 + OP_TitleUpdateMsg EmuOpcode = 0x1f07 + OP_MoveLogUpdateMsg EmuOpcode = 0x1f08 + OP_PerformPlayerKnockbackMsg EmuOpcode = 0x1f09 + OP_PerformCameraShakeMsg EmuOpcode = 0x1f0a + OP_EncounterBrokenMsg EmuOpcode = 0x1f0b + OP_RequestHelpRepathMsg EmuOpcode = 0x1f0c + + // Crash logs + OP_LsRequestClientCrashLogMsg EmuOpcode = 0x2000 + OP_LsClientBaselogReplyMsg EmuOpcode = 0x2001 + OP_LsClientCrashlogReplyMsg EmuOpcode = 0x2002 + OP_LsClientAlertlogReplyMsg EmuOpcode = 0x2003 + OP_LsClientVerifylogReplyMsg EmuOpcode = 0x2004 + + // Server lock + OP_WSServerLockMsg EmuOpcode = 0x2100 + OP_WSServerHideMsg EmuOpcode = 0x2101 + OP_LSServerLockMsg EmuOpcode = 0x2102 + OP_WSAcctLockStatusMsg EmuOpcode = 0x2103 + OP_LSCheckAcctLockMsg EmuOpcode = 0x2104 +) diff --git a/opcodes/gen/main.go b/opcodes/gen/main.go new file mode 100644 index 0000000..4b313f7 --- /dev/null +++ b/opcodes/gen/main.go @@ -0,0 +1,84 @@ +//go:build ignore + +package main + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "sort" + "strings" + "text/template" +) + +const outputTemplate = `// Code generated by gen/main.go; DO NOT EDIT. + +package opcodes + +// initializeNameMappings populates nameToEmu from constants +func (om *OpcodeManager) initializeNameMappings() { +{{- range . }} + om.nameToEmu["{{ .Name }}"] = {{ .Name }} +{{- end }} +} +` + +type OpcodeInfo struct { + Name string +} + +func main() { + opcodes := []OpcodeInfo{} + + // Parse each source file for OP_ constants + files := []string{"login.go", "emu.go"} + + for _, filename := range files { + fset := token.NewFileSet() + node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to parse %s: %v\n", filename, err) + continue + } + + // Find all OP_ and LS_ constants + ast.Inspect(node, func(n ast.Node) bool { + spec, ok := n.(*ast.ValueSpec) + if !ok { + return true + } + + for _, name := range spec.Names { + if strings.HasPrefix(name.Name, "OP_") || strings.HasPrefix(name.Name, "LS_") { + opcodes = append(opcodes, OpcodeInfo{Name: name.Name}) + } + } + return true + }) + } + + // Sort for consistent output + sort.Slice(opcodes, func(i, j int) bool { + return opcodes[i].Name < opcodes[j].Name + }) + + // Generate output + tmpl, err := template.New("opcodes").Parse(outputTemplate) + if err != nil { + panic(err) + } + + file, err := os.Create("generated.go") + if err != nil { + panic(err) + } + defer file.Close() + + if err := tmpl.Execute(file, opcodes); err != nil { + panic(err) + } + + fmt.Printf("Generated %d opcode mappings\n", len(opcodes)) +} diff --git a/opcodes/generated.go b/opcodes/generated.go new file mode 100644 index 0000000..651e061 --- /dev/null +++ b/opcodes/generated.go @@ -0,0 +1,621 @@ +// Code generated by gen/main.go; DO NOT EDIT. + +package opcodes + +// initializeNameMappings populates nameToEmu from constants +func (om *OpcodeManager) initializeNameMappings() { + om.nameToEmu["LS_AccessGrantedMsg"] = LS_AccessGrantedMsg + om.nameToEmu["LS_AllCharactersDescReplyMsg"] = LS_AllCharactersDescReplyMsg + om.nameToEmu["LS_AllCharactersDescRequestMsg"] = LS_AllCharactersDescRequestMsg + om.nameToEmu["LS_AllWSDescRequestMsg"] = LS_AllWSDescRequestMsg + om.nameToEmu["LS_AllWorldsDescReplyMsg"] = LS_AllWorldsDescReplyMsg + om.nameToEmu["LS_AllWorldsDescRequestMsg"] = LS_AllWorldsDescRequestMsg + om.nameToEmu["LS_BadLanguageFilter"] = LS_BadLanguageFilter + om.nameToEmu["LS_CharListReplyMsg"] = LS_CharListReplyMsg + om.nameToEmu["LS_CharListRequestMsg"] = LS_CharListRequestMsg + om.nameToEmu["LS_CharSelectMsg"] = LS_CharSelectMsg + om.nameToEmu["LS_CreateAccountReplyMsg"] = LS_CreateAccountReplyMsg + om.nameToEmu["LS_CreateAccountRequestMsg"] = LS_CreateAccountRequestMsg + om.nameToEmu["LS_CreateCharReplyMsg"] = LS_CreateCharReplyMsg + om.nameToEmu["LS_CreateCharRequestMsg"] = LS_CreateCharRequestMsg + om.nameToEmu["LS_CreateCharacterReplyMsg"] = LS_CreateCharacterReplyMsg + om.nameToEmu["LS_CreateCharacterRequestMsg"] = LS_CreateCharacterRequestMsg + om.nameToEmu["LS_DeleteCharReplyMsg"] = LS_DeleteCharReplyMsg + om.nameToEmu["LS_DeleteCharRequestMsg"] = LS_DeleteCharRequestMsg + om.nameToEmu["LS_DeleteCharacterReplyMsg"] = LS_DeleteCharacterReplyMsg + om.nameToEmu["LS_DeleteCharacterRequestMsg"] = LS_DeleteCharacterRequestMsg + om.nameToEmu["LS_ESLoginRequestMsg"] = LS_ESLoginRequestMsg + om.nameToEmu["LS_KeymapDataMsg"] = LS_KeymapDataMsg + om.nameToEmu["LS_KeymapLoadMsg"] = LS_KeymapLoadMsg + om.nameToEmu["LS_KeymapNoneMsg"] = LS_KeymapNoneMsg + om.nameToEmu["LS_KeymapSaveMsg"] = LS_KeymapSaveMsg + om.nameToEmu["LS_LSCheckAcctLockMsg"] = LS_LSCheckAcctLockMsg + om.nameToEmu["LS_LSServerLockMsg"] = LS_LSServerLockMsg + om.nameToEmu["LS_LSStatusReplyMsg"] = LS_LSStatusReplyMsg + om.nameToEmu["LS_LSStatusRequestMsg"] = LS_LSStatusRequestMsg + om.nameToEmu["LS_LoginBannedMsg"] = LS_LoginBannedMsg + om.nameToEmu["LS_LoginByNumRequestMsg"] = LS_LoginByNumRequestMsg + om.nameToEmu["LS_LoginFailedMsg"] = LS_LoginFailedMsg + om.nameToEmu["LS_LoginReplyMsg"] = LS_LoginReplyMsg + om.nameToEmu["LS_LoginRequestMsg"] = LS_LoginRequestMsg + om.nameToEmu["LS_LsClientAlertlogReplyMsg"] = LS_LsClientAlertlogReplyMsg + om.nameToEmu["LS_LsClientBaselogReplyMsg"] = LS_LsClientBaselogReplyMsg + om.nameToEmu["LS_LsClientCrashlogReplyMsg"] = LS_LsClientCrashlogReplyMsg + om.nameToEmu["LS_LsClientVerifylogReplyMsg"] = LS_LsClientVerifylogReplyMsg + om.nameToEmu["LS_LsRequestClientCrashLogMsg"] = LS_LsRequestClientCrashLogMsg + om.nameToEmu["LS_PlayCharReplyMsg"] = LS_PlayCharReplyMsg + om.nameToEmu["LS_PlayCharRequestMsg"] = LS_PlayCharRequestMsg + om.nameToEmu["LS_PlayCharacterReplyMsg"] = LS_PlayCharacterReplyMsg + om.nameToEmu["LS_PlayCharacterRequestMsg"] = LS_PlayCharacterRequestMsg + om.nameToEmu["LS_ReskinCharacterRequestMsg"] = LS_ReskinCharacterRequestMsg + om.nameToEmu["LS_ServerListReplyMsg"] = LS_ServerListReplyMsg + om.nameToEmu["LS_ServerListRequestMsg"] = LS_ServerListRequestMsg + om.nameToEmu["LS_ServerPlayCharacterReplyMsg"] = LS_ServerPlayCharacterReplyMsg + om.nameToEmu["LS_ServerPlayCharacterRequestMsg"] = LS_ServerPlayCharacterRequestMsg + om.nameToEmu["LS_ServerStatusReplyMsg"] = LS_ServerStatusReplyMsg + om.nameToEmu["LS_ServerStatusRequestMsg"] = LS_ServerStatusRequestMsg + om.nameToEmu["LS_SessionReadyMsg"] = LS_SessionReadyMsg + om.nameToEmu["LS_UpdateCharacterSheetMsg"] = LS_UpdateCharacterSheetMsg + om.nameToEmu["LS_UpdateInventoryMsg"] = LS_UpdateInventoryMsg + om.nameToEmu["LS_UsertoWorldReq"] = LS_UsertoWorldReq + om.nameToEmu["LS_UsertoWorldResp"] = LS_UsertoWorldResp + om.nameToEmu["LS_WSAcctLockStatusMsg"] = LS_WSAcctLockStatusMsg + om.nameToEmu["LS_WSCreateCharacterReplyMsg"] = LS_WSCreateCharacterReplyMsg + om.nameToEmu["LS_WSCreateCharacterRequestMsg"] = LS_WSCreateCharacterRequestMsg + om.nameToEmu["LS_WSLoginRequestMsg"] = LS_WSLoginRequestMsg + om.nameToEmu["LS_WSServerHideMsg"] = LS_WSServerHideMsg + om.nameToEmu["LS_WSServerLockMsg"] = LS_WSServerLockMsg + om.nameToEmu["LS_WSStatusReplyMsg"] = LS_WSStatusReplyMsg + om.nameToEmu["LS_WorldListMsg"] = LS_WorldListMsg + om.nameToEmu["LS_WorldStatusChangeMsg"] = LS_WorldStatusChangeMsg + om.nameToEmu["LS_WorldStatusMsg"] = LS_WorldStatusMsg + om.nameToEmu["OP_AFKUpdateMsg"] = OP_AFKUpdateMsg + om.nameToEmu["OP_AchievementCompleteMsg"] = OP_AchievementCompleteMsg + om.nameToEmu["OP_AchievementUpdateMsg"] = OP_AchievementUpdateMsg + om.nameToEmu["OP_AdvancementRequestMsg"] = OP_AdvancementRequestMsg + om.nameToEmu["OP_AdventureList"] = OP_AdventureList + om.nameToEmu["OP_AfterInvSpellUpdate"] = OP_AfterInvSpellUpdate + om.nameToEmu["OP_AnonUpdateMsg"] = OP_AnonUpdateMsg + om.nameToEmu["OP_ArenaGameTypesMsg"] = OP_ArenaGameTypesMsg + om.nameToEmu["OP_AttackAllowed"] = OP_AttackAllowed + om.nameToEmu["OP_AttackMsg"] = OP_AttackMsg + om.nameToEmu["OP_AttackNotAllowed"] = OP_AttackNotAllowed + om.nameToEmu["OP_AuctionAbortMsg"] = OP_AuctionAbortMsg + om.nameToEmu["OP_AuctionCharacter"] = OP_AuctionCharacter + om.nameToEmu["OP_AuctionCharacterReply"] = OP_AuctionCharacterReply + om.nameToEmu["OP_AuctionCoin"] = OP_AuctionCoin + om.nameToEmu["OP_AuctionCoinReply"] = OP_AuctionCoinReply + om.nameToEmu["OP_AuctionCommitMsg"] = OP_AuctionCommitMsg + om.nameToEmu["OP_AuctionItem"] = OP_AuctionItem + om.nameToEmu["OP_AuctionItemReply"] = OP_AuctionItemReply + om.nameToEmu["OP_AutoAttackMsg"] = OP_AutoAttackMsg + om.nameToEmu["OP_AvatarCreatedMsg"] = OP_AvatarCreatedMsg + om.nameToEmu["OP_AvatarDestroyedMsg"] = OP_AvatarDestroyedMsg + om.nameToEmu["OP_AvatarUpdateMsg"] = OP_AvatarUpdateMsg + om.nameToEmu["OP_BadLanguageFilter"] = OP_BadLanguageFilter + om.nameToEmu["OP_BagOptions"] = OP_BagOptions + om.nameToEmu["OP_BeginItemCreationMsg"] = OP_BeginItemCreationMsg + om.nameToEmu["OP_BeginTrackingMsg"] = OP_BeginTrackingMsg + om.nameToEmu["OP_BioUpdateMsg"] = OP_BioUpdateMsg + om.nameToEmu["OP_BrokerAddBag"] = OP_BrokerAddBag + om.nameToEmu["OP_BuyPlayerHouseMsg"] = OP_BuyPlayerHouseMsg + om.nameToEmu["OP_BuyPlayerHouseTintMsg"] = OP_BuyPlayerHouseTintMsg + om.nameToEmu["OP_CSTicketAddCommentMsg"] = OP_CSTicketAddCommentMsg + om.nameToEmu["OP_CSTicketChangeNotificationMsg"] = OP_CSTicketChangeNotificationMsg + om.nameToEmu["OP_CSTicketCommentRequestMsg"] = OP_CSTicketCommentRequestMsg + om.nameToEmu["OP_CSTicketCommentResponseMsg"] = OP_CSTicketCommentResponseMsg + om.nameToEmu["OP_CSTicketCreateMsg"] = OP_CSTicketCreateMsg + om.nameToEmu["OP_CSTicketDeleteMsg"] = OP_CSTicketDeleteMsg + om.nameToEmu["OP_CSTicketHeaderRequestMsg"] = OP_CSTicketHeaderRequestMsg + om.nameToEmu["OP_CSTicketInfoMsg"] = OP_CSTicketInfoMsg + om.nameToEmu["OP_CSToolAccessResponseMsg"] = OP_CSToolAccessResponseMsg + om.nameToEmu["OP_CSToolsRequestMsg"] = OP_CSToolsRequestMsg + om.nameToEmu["OP_CSToolsResponseMsg"] = OP_CSToolsResponseMsg + om.nameToEmu["OP_CampAbortedMsg"] = OP_CampAbortedMsg + om.nameToEmu["OP_CampClientMsg"] = OP_CampClientMsg + om.nameToEmu["OP_CampStartedMsg"] = OP_CampStartedMsg + om.nameToEmu["OP_CancelCreateFromRecipeMsg"] = OP_CancelCreateFromRecipeMsg + om.nameToEmu["OP_CancelMoveObjectModeMsg"] = OP_CancelMoveObjectModeMsg + om.nameToEmu["OP_CancelSpellCast"] = OP_CancelSpellCast + om.nameToEmu["OP_CancelledFeignMsg"] = OP_CancelledFeignMsg + om.nameToEmu["OP_CastSpellMsg"] = OP_CastSpellMsg + om.nameToEmu["OP_ChangeServerControlFlagMsg"] = OP_ChangeServerControlFlagMsg + om.nameToEmu["OP_ChangeZoneMsg"] = OP_ChangeZoneMsg + om.nameToEmu["OP_CharNameChangedMsg"] = OP_CharNameChangedMsg + om.nameToEmu["OP_CharTransferCommitReplyMsg"] = OP_CharTransferCommitReplyMsg + om.nameToEmu["OP_CharTransferCommitRequestMsg"] = OP_CharTransferCommitRequestMsg + om.nameToEmu["OP_CharTransferReplyMsg"] = OP_CharTransferReplyMsg + om.nameToEmu["OP_CharTransferRequestMsg"] = OP_CharTransferRequestMsg + om.nameToEmu["OP_CharTransferRollbackReplyMsg"] = OP_CharTransferRollbackReplyMsg + om.nameToEmu["OP_CharTransferRollbackRequestMsg"] = OP_CharTransferRollbackRequestMsg + om.nameToEmu["OP_CharTransferStartReplyMsg"] = OP_CharTransferStartReplyMsg + om.nameToEmu["OP_CharTransferStartRequestMsg"] = OP_CharTransferStartRequestMsg + om.nameToEmu["OP_CharTransferValidateReplyMsg"] = OP_CharTransferValidateReplyMsg + om.nameToEmu["OP_CharTransferValidateRequestMsg"] = OP_CharTransferValidateRequestMsg + om.nameToEmu["OP_CharacterAchievements"] = OP_CharacterAchievements + om.nameToEmu["OP_CharacterCreateReplyMsg"] = OP_CharacterCreateReplyMsg + om.nameToEmu["OP_CharacterCreateRequestMsg"] = OP_CharacterCreateRequestMsg + om.nameToEmu["OP_CharacterCreatedDungeons"] = OP_CharacterCreatedDungeons + om.nameToEmu["OP_CharacterCurrency"] = OP_CharacterCurrency + om.nameToEmu["OP_CharacterHousingList"] = OP_CharacterHousingList + om.nameToEmu["OP_CharacterLinkdeadMsg"] = OP_CharacterLinkdeadMsg + om.nameToEmu["OP_CharacterMerc"] = OP_CharacterMerc + om.nameToEmu["OP_CharacterMounts"] = OP_CharacterMounts + om.nameToEmu["OP_CharacterPet"] = OP_CharacterPet + om.nameToEmu["OP_ChatCreateChannelMsg"] = OP_ChatCreateChannelMsg + om.nameToEmu["OP_ChatFiltersMsg"] = OP_ChatFiltersMsg + om.nameToEmu["OP_ChatJoinChannelMsg"] = OP_ChatJoinChannelMsg + om.nameToEmu["OP_ChatLeaveChannelMsg"] = OP_ChatLeaveChannelMsg + om.nameToEmu["OP_ChatMsg"] = OP_ChatMsg + om.nameToEmu["OP_ChatRelationshipUpdateMsg"] = OP_ChatRelationshipUpdateMsg + om.nameToEmu["OP_ChatSendFriendsMsg"] = OP_ChatSendFriendsMsg + om.nameToEmu["OP_ChatSendIgnoresMsg"] = OP_ChatSendIgnoresMsg + om.nameToEmu["OP_ChatTellChannelMsg"] = OP_ChatTellChannelMsg + om.nameToEmu["OP_ChatTellUserMsg"] = OP_ChatTellUserMsg + om.nameToEmu["OP_ChatToggleFriendMsg"] = OP_ChatToggleFriendMsg + om.nameToEmu["OP_ChatToggleIgnoreMsg"] = OP_ChatToggleIgnoreMsg + om.nameToEmu["OP_ChatWhoChannelMsg"] = OP_ChatWhoChannelMsg + om.nameToEmu["OP_ClearDataMsg"] = OP_ClearDataMsg + om.nameToEmu["OP_ClearForLandingMsg"] = OP_ClearForLandingMsg + om.nameToEmu["OP_ClearForTakeOffMsg"] = OP_ClearForTakeOffMsg + om.nameToEmu["OP_ClientCmdMsg"] = OP_ClientCmdMsg + om.nameToEmu["OP_ClientFellMsg"] = OP_ClientFellMsg + om.nameToEmu["OP_ClientIdMsg"] = OP_ClientIdMsg + om.nameToEmu["OP_ClientIdleBeginMsg"] = OP_ClientIdleBeginMsg + om.nameToEmu["OP_ClientIdleEndMsg"] = OP_ClientIdleEndMsg + om.nameToEmu["OP_ClientInDeathRegionMsg"] = OP_ClientInDeathRegionMsg + om.nameToEmu["OP_ClientTeleportRequestMsg"] = OP_ClientTeleportRequestMsg + om.nameToEmu["OP_ClientTeleportToLocationMsg"] = OP_ClientTeleportToLocationMsg + om.nameToEmu["OP_CloseGroupInviteWindowMsg"] = OP_CloseGroupInviteWindowMsg + om.nameToEmu["OP_CloseWindowMsg"] = OP_CloseWindowMsg + om.nameToEmu["OP_CollectAllHouseItemsMsg"] = OP_CollectAllHouseItemsMsg + om.nameToEmu["OP_ConsiderMsg"] = OP_ConsiderMsg + om.nameToEmu["OP_ConsignItemRequestMsg"] = OP_ConsignItemRequestMsg + om.nameToEmu["OP_ConsignItemResponseMsg"] = OP_ConsignItemResponseMsg + om.nameToEmu["OP_ConsignRemoveItemsMsg"] = OP_ConsignRemoveItemsMsg + om.nameToEmu["OP_ConsignViewCreateMsg"] = OP_ConsignViewCreateMsg + om.nameToEmu["OP_ConsignViewGetPageMsg"] = OP_ConsignViewGetPageMsg + om.nameToEmu["OP_ConsignViewReleaseMsg"] = OP_ConsignViewReleaseMsg + om.nameToEmu["OP_ConsignViewSortMsg"] = OP_ConsignViewSortMsg + om.nameToEmu["OP_ConsignmentCloseStoreMsg"] = OP_ConsignmentCloseStoreMsg + om.nameToEmu["OP_ConversationMsg"] = OP_ConversationMsg + om.nameToEmu["OP_CorruptedClientMsg"] = OP_CorruptedClientMsg + om.nameToEmu["OP_CreateBoatTransportsMsg"] = OP_CreateBoatTransportsMsg + om.nameToEmu["OP_CreateCharFromCBBReplyMsg"] = OP_CreateCharFromCBBReplyMsg + om.nameToEmu["OP_CreateCharFromCBBRequestMsg"] = OP_CreateCharFromCBBRequestMsg + om.nameToEmu["OP_CreateCharacterReplyMsg"] = OP_CreateCharacterReplyMsg + om.nameToEmu["OP_CreateCharacterRequestMsg"] = OP_CreateCharacterRequestMsg + om.nameToEmu["OP_CreateGuildReplyMsg"] = OP_CreateGuildReplyMsg + om.nameToEmu["OP_CreateGuildRequestMsg"] = OP_CreateGuildRequestMsg + om.nameToEmu["OP_CreateZoneInstanceMsg"] = OP_CreateZoneInstanceMsg + om.nameToEmu["OP_CsCategoryRequestMsg"] = OP_CsCategoryRequestMsg + om.nameToEmu["OP_CsCategoryResponseMsg"] = OP_CsCategoryResponseMsg + om.nameToEmu["OP_CurrentPet"] = OP_CurrentPet + om.nameToEmu["OP_CustomizationPurchaseRequestMs"] = OP_CustomizationPurchaseRequestMs + om.nameToEmu["OP_CustomizationReplyMsg"] = OP_CustomizationReplyMsg + om.nameToEmu["OP_CustomizationSetRequestMsg"] = OP_CustomizationSetRequestMsg + om.nameToEmu["OP_DailyObjectives"] = OP_DailyObjectives + om.nameToEmu["OP_DefaultGroupOptionsMsg"] = OP_DefaultGroupOptionsMsg + om.nameToEmu["OP_DefaultGroupOptionsRequestMsg"] = OP_DefaultGroupOptionsRequestMsg + om.nameToEmu["OP_DeleteGuildMsg"] = OP_DeleteGuildMsg + om.nameToEmu["OP_DeleteItemMsg"] = OP_DeleteItemMsg + om.nameToEmu["OP_DialogCloseMsg"] = OP_DialogCloseMsg + om.nameToEmu["OP_DialogOpenMsg"] = OP_DialogOpenMsg + om.nameToEmu["OP_DialogSelectMsg"] = OP_DialogSelectMsg + om.nameToEmu["OP_DietyAbilityWindow"] = OP_DietyAbilityWindow + om.nameToEmu["OP_DispatchClientCmdMsg"] = OP_DispatchClientCmdMsg + om.nameToEmu["OP_DispatchESMsg"] = OP_DispatchESMsg + om.nameToEmu["OP_DispatchSpellCmdMsg"] = OP_DispatchSpellCmdMsg + om.nameToEmu["OP_DisplayDebugNLLPointsMsg"] = OP_DisplayDebugNLLPointsMsg + om.nameToEmu["OP_DisplayGroupOptionsScreenMsg"] = OP_DisplayGroupOptionsScreenMsg + om.nameToEmu["OP_DisplayInnVisitScreenMsg"] = OP_DisplayInnVisitScreenMsg + om.nameToEmu["OP_DisplayMailScreenMsg"] = OP_DisplayMailScreenMsg + om.nameToEmu["OP_DisplayTSEventReactionMsg"] = OP_DisplayTSEventReactionMsg + om.nameToEmu["OP_DisplayWarningMsg"] = OP_DisplayWarningMsg + om.nameToEmu["OP_DoneLoadingEntityResourcesMsg"] = OP_DoneLoadingEntityResourcesMsg + om.nameToEmu["OP_DoneLoadingUIResourcesMsg"] = OP_DoneLoadingUIResourcesMsg + om.nameToEmu["OP_DoneLoadingZoneResourcesMsg"] = OP_DoneLoadingZoneResourcesMsg + om.nameToEmu["OP_DoneSendingInitialEntitiesMsg"] = OP_DoneSendingInitialEntitiesMsg + om.nameToEmu["OP_DressingRoom"] = OP_DressingRoom + om.nameToEmu["OP_DumpSchedulerMsg"] = OP_DumpSchedulerMsg + om.nameToEmu["OP_DungeonMakerItemRequest"] = OP_DungeonMakerItemRequest + om.nameToEmu["OP_EQHearDispellCmd"] = OP_EQHearDispellCmd + om.nameToEmu["OP_EQHearThreatCmd"] = OP_EQHearThreatCmd + om.nameToEmu["OP_ESInitMsg"] = OP_ESInitMsg + om.nameToEmu["OP_ESReadyForClientsMsg"] = OP_ESReadyForClientsMsg + om.nameToEmu["OP_ESStatusMsg"] = OP_ESStatusMsg + om.nameToEmu["OP_ESWeatherRequestEndMsg"] = OP_ESWeatherRequestEndMsg + om.nameToEmu["OP_ESWeatherRequestMsg"] = OP_ESWeatherRequestMsg + om.nameToEmu["OP_ESZoneInstanceStatusMsg"] = OP_ESZoneInstanceStatusMsg + om.nameToEmu["OP_EarlyLandingRequestMsg"] = OP_EarlyLandingRequestMsg + om.nameToEmu["OP_EncounterBrokenMsg"] = OP_EncounterBrokenMsg + om.nameToEmu["OP_EnterHouseMsg"] = OP_EnterHouseMsg + om.nameToEmu["OP_EnterMoveObjectModeMsg"] = OP_EnterMoveObjectModeMsg + om.nameToEmu["OP_EnterWorldMsg"] = OP_EnterWorldMsg + om.nameToEmu["OP_EntityVerbsReplyMsg"] = OP_EntityVerbsReplyMsg + om.nameToEmu["OP_EntityVerbsRequestMsg"] = OP_EntityVerbsRequestMsg + om.nameToEmu["OP_EntityVerbsVerbMsg"] = OP_EntityVerbsVerbMsg + om.nameToEmu["OP_EqAvailWorldChannelsCmd"] = OP_EqAvailWorldChannelsCmd + om.nameToEmu["OP_EqCannedEmoteCmd"] = OP_EqCannedEmoteCmd + om.nameToEmu["OP_EqChatChannelUpdateCmd"] = OP_EqChatChannelUpdateCmd + om.nameToEmu["OP_EqChoiceWinCmd"] = OP_EqChoiceWinCmd + om.nameToEmu["OP_EqCloseWindowCmd"] = OP_EqCloseWindowCmd + om.nameToEmu["OP_EqCollectionFilterCmd"] = OP_EqCollectionFilterCmd + om.nameToEmu["OP_EqCollectionItemCmd"] = OP_EqCollectionItemCmd + om.nameToEmu["OP_EqCollectionUpdateCmd"] = OP_EqCollectionUpdateCmd + om.nameToEmu["OP_EqConsignmentItemsCmd"] = OP_EqConsignmentItemsCmd + om.nameToEmu["OP_EqCreateGhostCmd"] = OP_EqCreateGhostCmd + om.nameToEmu["OP_EqCreateListBoxCmd"] = OP_EqCreateListBoxCmd + om.nameToEmu["OP_EqCreateSignWidgetCmd"] = OP_EqCreateSignWidgetCmd + om.nameToEmu["OP_EqCreateWidgetCmd"] = OP_EqCreateWidgetCmd + om.nameToEmu["OP_EqDebugPVDCmd"] = OP_EqDebugPVDCmd + om.nameToEmu["OP_EqDestroyGhostCmd"] = OP_EqDestroyGhostCmd + om.nameToEmu["OP_EqDialogCloseCmd"] = OP_EqDialogCloseCmd + om.nameToEmu["OP_EqDialogOpenCmd"] = OP_EqDialogOpenCmd + om.nameToEmu["OP_EqDisplaySpellFailCmd"] = OP_EqDisplaySpellFailCmd + om.nameToEmu["OP_EqDisplayTextCmd"] = OP_EqDisplayTextCmd + om.nameToEmu["OP_EqDrawablePathGraphCmd"] = OP_EqDrawablePathGraphCmd + om.nameToEmu["OP_EqEnableGameEventCmd"] = OP_EqEnableGameEventCmd + om.nameToEmu["OP_EqEnableWindowCmd"] = OP_EqEnableWindowCmd + om.nameToEmu["OP_EqExamineInfoCmd"] = OP_EqExamineInfoCmd + om.nameToEmu["OP_EqFactionUpdateCmd"] = OP_EqFactionUpdateCmd + om.nameToEmu["OP_EqFlashWindowCmd"] = OP_EqFlashWindowCmd + om.nameToEmu["OP_EqGetProbsCmd"] = OP_EqGetProbsCmd + om.nameToEmu["OP_EqGroupMemberRemovedCmd"] = OP_EqGroupMemberRemovedCmd + om.nameToEmu["OP_EqHearChainEffectCmd"] = OP_EqHearChainEffectCmd + om.nameToEmu["OP_EqHearChatCmd"] = OP_EqHearChatCmd + om.nameToEmu["OP_EqHearCombatCmd"] = OP_EqHearCombatCmd + om.nameToEmu["OP_EqHearConsiderCmd"] = OP_EqHearConsiderCmd + om.nameToEmu["OP_EqHearDeathCmd"] = OP_EqHearDeathCmd + om.nameToEmu["OP_EqHearDrowningCmd"] = OP_EqHearDrowningCmd + om.nameToEmu["OP_EqHearHealCmd"] = OP_EqHearHealCmd + om.nameToEmu["OP_EqHearPlayFlavorCmd"] = OP_EqHearPlayFlavorCmd + om.nameToEmu["OP_EqHearSpellCastCmd"] = OP_EqHearSpellCastCmd + om.nameToEmu["OP_EqHearSpellFizzleCmd"] = OP_EqHearSpellFizzleCmd + om.nameToEmu["OP_EqHearSpellInterruptCmd"] = OP_EqHearSpellInterruptCmd + om.nameToEmu["OP_EqHearSpellNoLandCmd"] = OP_EqHearSpellNoLandCmd + om.nameToEmu["OP_EqHelpPathClearCmd"] = OP_EqHelpPathClearCmd + om.nameToEmu["OP_EqHelpPathCmd"] = OP_EqHelpPathCmd + om.nameToEmu["OP_EqInspectPCResultsCmd"] = OP_EqInspectPCResultsCmd + om.nameToEmu["OP_EqInstructionWindowCloseCmd"] = OP_EqInstructionWindowCloseCmd + om.nameToEmu["OP_EqInstructionWindowCmd"] = OP_EqInstructionWindowCmd + om.nameToEmu["OP_EqInstructionWindowGoalCmd"] = OP_EqInstructionWindowGoalCmd + om.nameToEmu["OP_EqInstructionWindowTaskCmd"] = OP_EqInstructionWindowTaskCmd + om.nameToEmu["OP_EqJunctionListCmd"] = OP_EqJunctionListCmd + om.nameToEmu["OP_EqMapExplorationCmd"] = OP_EqMapExplorationCmd + om.nameToEmu["OP_EqPlaySound3DCmd"] = OP_EqPlaySound3DCmd + om.nameToEmu["OP_EqPlaySoundCmd"] = OP_EqPlaySoundCmd + om.nameToEmu["OP_EqPlayVoiceCmd"] = OP_EqPlayVoiceCmd + om.nameToEmu["OP_EqQuestGroupCmd"] = OP_EqQuestGroupCmd + om.nameToEmu["OP_EqQuestJournalReplyCmd"] = OP_EqQuestJournalReplyCmd + om.nameToEmu["OP_EqQuestJournalUpdateCmd"] = OP_EqQuestJournalUpdateCmd + om.nameToEmu["OP_EqQuestionnaireCmd"] = OP_EqQuestionnaireCmd + om.nameToEmu["OP_EqReceiveOfferCmd"] = OP_EqReceiveOfferCmd + om.nameToEmu["OP_EqResurrectedCmd"] = OP_EqResurrectedCmd + om.nameToEmu["OP_EqSetControlGhostCmd"] = OP_EqSetControlGhostCmd + om.nameToEmu["OP_EqSetDebugPathPointsCmd"] = OP_EqSetDebugPathPointsCmd + om.nameToEmu["OP_EqSetDefaultVerbCmd"] = OP_EqSetDefaultVerbCmd + om.nameToEmu["OP_EqSetPOVGhostCmd"] = OP_EqSetPOVGhostCmd + om.nameToEmu["OP_EqShowBookCmd"] = OP_EqShowBookCmd + om.nameToEmu["OP_EqShowDeathWindowCmd"] = OP_EqShowDeathWindowCmd + om.nameToEmu["OP_EqShowWindowCmd"] = OP_EqShowWindowCmd + om.nameToEmu["OP_EqSpellCastEndCmd"] = OP_EqSpellCastEndCmd + om.nameToEmu["OP_EqSpellCastStartCmd"] = OP_EqSpellCastStartCmd + om.nameToEmu["OP_EqSpellMoveToRangeAndRetryCmd"] = OP_EqSpellMoveToRangeAndRetryCmd + om.nameToEmu["OP_EqStartBrokerCmd"] = OP_EqStartBrokerCmd + om.nameToEmu["OP_EqStateCmd"] = OP_EqStateCmd + om.nameToEmu["OP_EqStoreLogCmd"] = OP_EqStoreLogCmd + om.nameToEmu["OP_EqTargetItemCmd"] = OP_EqTargetItemCmd + om.nameToEmu["OP_EqUpdateBankCmd"] = OP_EqUpdateBankCmd + om.nameToEmu["OP_EqUpdateGhostCmd"] = OP_EqUpdateGhostCmd + om.nameToEmu["OP_EqUpdateLootCmd"] = OP_EqUpdateLootCmd + om.nameToEmu["OP_EqUpdateMerchantCmd"] = OP_EqUpdateMerchantCmd + om.nameToEmu["OP_EqUpdatePlayerMailCmd"] = OP_EqUpdatePlayerMailCmd + om.nameToEmu["OP_EqUpdatePlayerTradeCmd"] = OP_EqUpdatePlayerTradeCmd + om.nameToEmu["OP_EqUpdateSignWidgetCmd"] = OP_EqUpdateSignWidgetCmd + om.nameToEmu["OP_EqUpdateStoreCmd"] = OP_EqUpdateStoreCmd + om.nameToEmu["OP_EqUpdateSubClassesCmd"] = OP_EqUpdateSubClassesCmd + om.nameToEmu["OP_EqUpdateTargetCmd"] = OP_EqUpdateTargetCmd + om.nameToEmu["OP_EqWhoChannelQueryReplyCmd"] = OP_EqWhoChannelQueryReplyCmd + om.nameToEmu["OP_EquipItemMsg"] = OP_EquipItemMsg + om.nameToEmu["OP_ExamineConsignmentRequestMsg"] = OP_ExamineConsignmentRequestMsg + om.nameToEmu["OP_ExamineConsignmentResponseMsg"] = OP_ExamineConsignmentResponseMsg + om.nameToEmu["OP_ExamineInfoRequestMsg"] = OP_ExamineInfoRequestMsg + om.nameToEmu["OP_ExamineItemMsg"] = OP_ExamineItemMsg + om.nameToEmu["OP_ExamineItemRequestMsg"] = OP_ExamineItemRequestMsg + om.nameToEmu["OP_ExitHouseMsg"] = OP_ExitHouseMsg + om.nameToEmu["OP_ExitWorldMsg"] = OP_ExitWorldMsg + om.nameToEmu["OP_ExpUpdateMsg"] = OP_ExpUpdateMsg + om.nameToEmu["OP_ExpectClientAsCharacterReplyMs"] = OP_ExpectClientAsCharacterReplyMs + om.nameToEmu["OP_ExpectClientAsCharacterRequest"] = OP_ExpectClientAsCharacterRequest + om.nameToEmu["OP_FellowshipExpMsg"] = OP_FellowshipExpMsg + om.nameToEmu["OP_FlightPathsMsg"] = OP_FlightPathsMsg + om.nameToEmu["OP_GameWorldTimeMsg"] = OP_GameWorldTimeMsg + om.nameToEmu["OP_GetAvatarAccessRequestForCSToo"] = OP_GetAvatarAccessRequestForCSToo + om.nameToEmu["OP_GetCharacterSerializedReplyMsg"] = OP_GetCharacterSerializedReplyMsg + om.nameToEmu["OP_GetCharacterSerializedRequestM"] = OP_GetCharacterSerializedRequestM + om.nameToEmu["OP_GroupCreatedMsg"] = OP_GroupCreatedMsg + om.nameToEmu["OP_GroupDeclineResponseMsg"] = OP_GroupDeclineResponseMsg + om.nameToEmu["OP_GroupDestroyedMsg"] = OP_GroupDestroyedMsg + om.nameToEmu["OP_GroupInviteRequestMsg"] = OP_GroupInviteRequestMsg + om.nameToEmu["OP_GroupInviteResponseMsg"] = OP_GroupInviteResponseMsg + om.nameToEmu["OP_GroupLeaderChangedMsg"] = OP_GroupLeaderChangedMsg + om.nameToEmu["OP_GroupMemberAddedMsg"] = OP_GroupMemberAddedMsg + om.nameToEmu["OP_GroupMemberRemovedMsg"] = OP_GroupMemberRemovedMsg + om.nameToEmu["OP_GroupOptionsMsg"] = OP_GroupOptionsMsg + om.nameToEmu["OP_GroupRemovedFromGroupMsg"] = OP_GroupRemovedFromGroupMsg + om.nameToEmu["OP_GroupSettingsChangedMsg"] = OP_GroupSettingsChangedMsg + om.nameToEmu["OP_GuildBankEventListMsg"] = OP_GuildBankEventListMsg + om.nameToEmu["OP_GuildBankUpdateMsg"] = OP_GuildBankUpdateMsg + om.nameToEmu["OP_GuildEventActionMsg"] = OP_GuildEventActionMsg + om.nameToEmu["OP_GuildEventAddMsg"] = OP_GuildEventAddMsg + om.nameToEmu["OP_GuildEventDetailsMsg"] = OP_GuildEventDetailsMsg + om.nameToEmu["OP_GuildEventListMsg"] = OP_GuildEventListMsg + om.nameToEmu["OP_GuildEventMsg"] = OP_GuildEventMsg + om.nameToEmu["OP_GuildInviteMsg"] = OP_GuildInviteMsg + om.nameToEmu["OP_GuildInviteResponseMsg"] = OP_GuildInviteResponseMsg + om.nameToEmu["OP_GuildKickMsg"] = OP_GuildKickMsg + om.nameToEmu["OP_GuildMembershipResponseMsg"] = OP_GuildMembershipResponseMsg + om.nameToEmu["OP_GuildMotdMsg"] = OP_GuildMotdMsg + om.nameToEmu["OP_GuildRecruiting"] = OP_GuildRecruiting + om.nameToEmu["OP_GuildRecruitingDetails"] = OP_GuildRecruitingDetails + om.nameToEmu["OP_GuildRecruitingImage"] = OP_GuildRecruitingImage + om.nameToEmu["OP_GuildRecruitingMemberInfo"] = OP_GuildRecruitingMemberInfo + om.nameToEmu["OP_GuildUpdateMsg"] = OP_GuildUpdateMsg + om.nameToEmu["OP_GuildsayMsg"] = OP_GuildsayMsg + om.nameToEmu["OP_HeritageMsg"] = OP_HeritageMsg + om.nameToEmu["OP_HouseAccessRemoveMsg"] = OP_HouseAccessRemoveMsg + om.nameToEmu["OP_HouseAccessSetMsg"] = OP_HouseAccessSetMsg + om.nameToEmu["OP_HouseCustomizationScreenMsg"] = OP_HouseCustomizationScreenMsg + om.nameToEmu["OP_HouseDefaultAccessSetMsg"] = OP_HouseDefaultAccessSetMsg + om.nameToEmu["OP_HouseDeletedRemotelyMsg"] = OP_HouseDeletedRemotelyMsg + om.nameToEmu["OP_HouseItemsList"] = OP_HouseItemsList + om.nameToEmu["OP_HousePayUpkeep"] = OP_HousePayUpkeep + om.nameToEmu["OP_HousePurchase"] = OP_HousePurchase + om.nameToEmu["OP_HousingDataChangedMsg"] = OP_HousingDataChangedMsg + om.nameToEmu["OP_HousingDataMsg"] = OP_HousingDataMsg + om.nameToEmu["OP_HousingRestoreMsg"] = OP_HousingRestoreMsg + om.nameToEmu["OP_InspectPlayerMsg"] = OP_InspectPlayerMsg + om.nameToEmu["OP_InterruptSpellMsg"] = OP_InterruptSpellMsg + om.nameToEmu["OP_InventoryMsg"] = OP_InventoryMsg + om.nameToEmu["OP_JoinGuildNotifyMsg"] = OP_JoinGuildNotifyMsg + om.nameToEmu["OP_JournalQuestStoryline"] = OP_JournalQuestStoryline + om.nameToEmu["OP_KeybindLoadMsg"] = OP_KeybindLoadMsg + om.nameToEmu["OP_KeybindUpdateMsg"] = OP_KeybindUpdateMsg + om.nameToEmu["OP_KeymapDataMsg"] = OP_KeymapDataMsg + om.nameToEmu["OP_KeymapLoadMsg"] = OP_KeymapLoadMsg + om.nameToEmu["OP_KeymapNoneMsg"] = OP_KeymapNoneMsg + om.nameToEmu["OP_KeymapSaveMsg"] = OP_KeymapSaveMsg + om.nameToEmu["OP_KnowledgeWindowSlotMappingMsg"] = OP_KnowledgeWindowSlotMappingMsg + om.nameToEmu["OP_KnowledgebaseRequestMsg"] = OP_KnowledgebaseRequestMsg + om.nameToEmu["OP_KnowledgebaseResponseMsg"] = OP_KnowledgebaseResponseMsg + om.nameToEmu["OP_KnownLanguagesMsg"] = OP_KnownLanguagesMsg + om.nameToEmu["OP_LFGGroupSearch"] = OP_LFGGroupSearch + om.nameToEmu["OP_LFGUpdateMsg"] = OP_LFGUpdateMsg + om.nameToEmu["OP_LSCheckAcctLockMsg"] = OP_LSCheckAcctLockMsg + om.nameToEmu["OP_LSServerLockMsg"] = OP_LSServerLockMsg + om.nameToEmu["OP_Launchpad"] = OP_Launchpad + om.nameToEmu["OP_LeaveGuildNotifyMsg"] = OP_LeaveGuildNotifyMsg + om.nameToEmu["OP_LevelChangedMsg"] = OP_LevelChangedMsg + om.nameToEmu["OP_LevelUpMsg"] = OP_LevelUpMsg + om.nameToEmu["OP_LikeOption"] = OP_LikeOption + om.nameToEmu["OP_LoadCalendarEvents"] = OP_LoadCalendarEvents + om.nameToEmu["OP_LoadWelcomeWindow"] = OP_LoadWelcomeWindow + om.nameToEmu["OP_LoginAcceptedMsg"] = OP_LoginAcceptedMsg + om.nameToEmu["OP_LoginByNumRequestMsg"] = OP_LoginByNumRequestMsg + om.nameToEmu["OP_LoginFailedMsg2"] = OP_LoginFailedMsg2 + om.nameToEmu["OP_LoginReplyMsg"] = OP_LoginReplyMsg + om.nameToEmu["OP_LootItemsRequestMsg"] = OP_LootItemsRequestMsg + om.nameToEmu["OP_Lottery"] = OP_Lottery + om.nameToEmu["OP_LsClientAlertlogReplyMsg"] = OP_LsClientAlertlogReplyMsg + om.nameToEmu["OP_LsClientBaselogReplyMsg"] = OP_LsClientBaselogReplyMsg + om.nameToEmu["OP_LsClientCrashlogReplyMsg"] = OP_LsClientCrashlogReplyMsg + om.nameToEmu["OP_LsClientVerifylogReplyMsg"] = OP_LsClientVerifylogReplyMsg + om.nameToEmu["OP_LsRequestClientCrashLogMsg"] = OP_LsRequestClientCrashLogMsg + om.nameToEmu["OP_MOTDMsg"] = OP_MOTDMsg + om.nameToEmu["OP_MacroInitMsg"] = OP_MacroInitMsg + om.nameToEmu["OP_MacroUpdateMsg"] = OP_MacroUpdateMsg + om.nameToEmu["OP_MailCommitSendMessageMsg"] = OP_MailCommitSendMessageMsg + om.nameToEmu["OP_MailDeleteMessageMsg"] = OP_MailDeleteMessageMsg + om.nameToEmu["OP_MailDeleteMessageRequestMsg"] = OP_MailDeleteMessageRequestMsg + om.nameToEmu["OP_MailEventNotificationMsg"] = OP_MailEventNotificationMsg + om.nameToEmu["OP_MailGetHeadersReplyMsg"] = OP_MailGetHeadersReplyMsg + om.nameToEmu["OP_MailGetHeadersRequestMsg"] = OP_MailGetHeadersRequestMsg + om.nameToEmu["OP_MailGetMessageMsg"] = OP_MailGetMessageMsg + om.nameToEmu["OP_MailGetMessageReplyMsg"] = OP_MailGetMessageReplyMsg + om.nameToEmu["OP_MailGetMessageRequestMsg"] = OP_MailGetMessageRequestMsg + om.nameToEmu["OP_MailRemoveAttachFromMailMsg"] = OP_MailRemoveAttachFromMailMsg + om.nameToEmu["OP_MailSendMessageMsg"] = OP_MailSendMessageMsg + om.nameToEmu["OP_MailSendMessageReplyMsg"] = OP_MailSendMessageReplyMsg + om.nameToEmu["OP_MailSendMessageRequestMsg"] = OP_MailSendMessageRequestMsg + om.nameToEmu["OP_MailSendSystemMessageMsg"] = OP_MailSendSystemMessageMsg + om.nameToEmu["OP_MakeGroupLeaderMsg"] = OP_MakeGroupLeaderMsg + om.nameToEmu["OP_MapFogDataInitMsg"] = OP_MapFogDataInitMsg + om.nameToEmu["OP_MapFogDataUpdateMsg"] = OP_MapFogDataUpdateMsg + om.nameToEmu["OP_MapRequest"] = OP_MapRequest + om.nameToEmu["OP_MarketAddFundsRequest"] = OP_MarketAddFundsRequest + om.nameToEmu["OP_MarketFundsUpdate"] = OP_MarketFundsUpdate + om.nameToEmu["OP_MarketPlacePrices"] = OP_MarketPlacePrices + om.nameToEmu["OP_MigrateBoatTransportMsg"] = OP_MigrateBoatTransportMsg + om.nameToEmu["OP_MigrateBoatTransportReplyMsg"] = OP_MigrateBoatTransportReplyMsg + om.nameToEmu["OP_MigrateClientToZoneReplyMsg"] = OP_MigrateClientToZoneReplyMsg + om.nameToEmu["OP_MigrateClientToZoneRequestMsg"] = OP_MigrateClientToZoneRequestMsg + om.nameToEmu["OP_ModifyGuildMsg"] = OP_ModifyGuildMsg + om.nameToEmu["OP_MonitorCharacterListMsg"] = OP_MonitorCharacterListMsg + om.nameToEmu["OP_MonitorCharacterListRequestMsg"] = OP_MonitorCharacterListRequestMsg + om.nameToEmu["OP_MonitorReplyMsg"] = OP_MonitorReplyMsg + om.nameToEmu["OP_MoveLogUpdateMsg"] = OP_MoveLogUpdateMsg + om.nameToEmu["OP_MoveableObjectPlacementCriteri"] = OP_MoveableObjectPlacementCriteri + om.nameToEmu["OP_NewZoneMsg"] = OP_NewZoneMsg + om.nameToEmu["OP_NotifyApprenticeStoppedMentori"] = OP_NotifyApprenticeStoppedMentori + om.nameToEmu["OP_OfferQuestMsg"] = OP_OfferQuestMsg + om.nameToEmu["OP_OnscreenMsgMsg"] = OP_OnscreenMsgMsg + om.nameToEmu["OP_OpenCharCust"] = OP_OpenCharCust + om.nameToEmu["OP_PaperdollImage"] = OP_PaperdollImage + om.nameToEmu["OP_PayHouseUpkeepMsg"] = OP_PayHouseUpkeepMsg + om.nameToEmu["OP_PerformCameraShakeMsg"] = OP_PerformCameraShakeMsg + om.nameToEmu["OP_PerformPlayerKnockbackMsg"] = OP_PerformPlayerKnockbackMsg + om.nameToEmu["OP_PetOptions"] = OP_PetOptions + om.nameToEmu["OP_PetOptionsResponse"] = OP_PetOptionsResponse + om.nameToEmu["OP_PlayerBioMsg"] = OP_PlayerBioMsg + om.nameToEmu["OP_PlayerHouseAccessUpdateMsg"] = OP_PlayerHouseAccessUpdateMsg + om.nameToEmu["OP_PlayerHouseBaseScreenMsg"] = OP_PlayerHouseBaseScreenMsg + om.nameToEmu["OP_PlayerHouseCloseUIMsg"] = OP_PlayerHouseCloseUIMsg + om.nameToEmu["OP_PlayerHouseDisplayStatusMsg"] = OP_PlayerHouseDisplayStatusMsg + om.nameToEmu["OP_PlayerHousePurchaseScreenMsg"] = OP_PlayerHousePurchaseScreenMsg + om.nameToEmu["OP_PlayerProfileMsg"] = OP_PlayerProfileMsg + om.nameToEmu["OP_PlayerStatsMsg"] = OP_PlayerStatsMsg + om.nameToEmu["OP_PointOfInterest"] = OP_PointOfInterest + om.nameToEmu["OP_PopulateSkillMapsMsg"] = OP_PopulateSkillMapsMsg + om.nameToEmu["OP_PositionBoatTransportMsg"] = OP_PositionBoatTransportMsg + om.nameToEmu["OP_PositionMoveableObject"] = OP_PositionMoveableObject + om.nameToEmu["OP_PredictionUpdateMsg"] = OP_PredictionUpdateMsg + om.nameToEmu["OP_PromoFlagsDetailsMsg"] = OP_PromoFlagsDetailsMsg + om.nameToEmu["OP_PurchaseConsignmentLoreCheckRe"] = OP_PurchaseConsignmentLoreCheckRe + om.nameToEmu["OP_QueryHoodMsg"] = OP_QueryHoodMsg + om.nameToEmu["OP_QueryNpcMsg"] = OP_QueryNpcMsg + om.nameToEmu["OP_QuestCompleteMsg"] = OP_QuestCompleteMsg + om.nameToEmu["OP_QuestFailedMsg"] = OP_QuestFailedMsg + om.nameToEmu["OP_QuestJournalInspectMsg"] = OP_QuestJournalInspectMsg + om.nameToEmu["OP_QuestJournalOpenMsg"] = OP_QuestJournalOpenMsg + om.nameToEmu["OP_QuestJournalReplyMsg"] = OP_QuestJournalReplyMsg + om.nameToEmu["OP_QuestJournalSetVisibleMsg"] = OP_QuestJournalSetVisibleMsg + om.nameToEmu["OP_QuestJournalUpdateMsg"] = OP_QuestJournalUpdateMsg + om.nameToEmu["OP_QuestJournalWaypointMsg"] = OP_QuestJournalWaypointMsg + om.nameToEmu["OP_QuestOfferMsg"] = OP_QuestOfferMsg + om.nameToEmu["OP_QuestReward"] = OP_QuestReward + om.nameToEmu["OP_QuestRewardMsg"] = OP_QuestRewardMsg + om.nameToEmu["OP_QuestionnaireMsg"] = OP_QuestionnaireMsg + om.nameToEmu["OP_QuickbarInitMsg"] = OP_QuickbarInitMsg + om.nameToEmu["OP_QuickbarUpdateMsg"] = OP_QuickbarUpdateMsg + om.nameToEmu["OP_RaceRestrictionMsg"] = OP_RaceRestrictionMsg + om.nameToEmu["OP_ReadyForTakeOffMsg"] = OP_ReadyForTakeOffMsg + om.nameToEmu["OP_ReadyToZoneMsg"] = OP_ReadyToZoneMsg + om.nameToEmu["OP_RecipeBook"] = OP_RecipeBook + om.nameToEmu["OP_RecipeDetailsMsg"] = OP_RecipeDetailsMsg + om.nameToEmu["OP_RecipeList"] = OP_RecipeList + om.nameToEmu["OP_RecipeListUnknown"] = OP_RecipeListUnknown + om.nameToEmu["OP_RelinquishHouseMsg"] = OP_RelinquishHouseMsg + om.nameToEmu["OP_ReloadLocalizedTxtMsg"] = OP_ReloadLocalizedTxtMsg + om.nameToEmu["OP_RemoteCmdMsg"] = OP_RemoteCmdMsg + om.nameToEmu["OP_RemoveClientFromGroupMsg"] = OP_RemoveClientFromGroupMsg + om.nameToEmu["OP_RemoveConcentrationMsg"] = OP_RemoveConcentrationMsg + om.nameToEmu["OP_RemoveGroupFromGroupMsg"] = OP_RemoveGroupFromGroupMsg + om.nameToEmu["OP_RemoveSpellEffectMsg"] = OP_RemoveSpellEffectMsg + om.nameToEmu["OP_RenameGuildMsg"] = OP_RenameGuildMsg + om.nameToEmu["OP_ReplaceableSubMeshesMsg"] = OP_ReplaceableSubMeshesMsg + om.nameToEmu["OP_ReportMsg"] = OP_ReportMsg + om.nameToEmu["OP_RequestCampMsg"] = OP_RequestCampMsg + om.nameToEmu["OP_RequestGuildBankEventDetailsMs"] = OP_RequestGuildBankEventDetailsMs + om.nameToEmu["OP_RequestGuildEventDetailsMsg"] = OP_RequestGuildEventDetailsMsg + om.nameToEmu["OP_RequestGuildInfoMsg"] = OP_RequestGuildInfoMsg + om.nameToEmu["OP_RequestGuildMembershipMsg"] = OP_RequestGuildMembershipMsg + om.nameToEmu["OP_RequestHelpRepathMsg"] = OP_RequestHelpRepathMsg + om.nameToEmu["OP_RequestRecipeDetailsMsg"] = OP_RequestRecipeDetailsMsg + om.nameToEmu["OP_RequestTargetLocMsg"] = OP_RequestTargetLocMsg + om.nameToEmu["OP_RestartZoneMsg"] = OP_RestartZoneMsg + om.nameToEmu["OP_RewardPackMsg"] = OP_RewardPackMsg + om.nameToEmu["OP_SatMsg"] = OP_SatMsg + om.nameToEmu["OP_SavageBarInitMsg"] = OP_SavageBarInitMsg + om.nameToEmu["OP_SelectZoneTeleporterDestinatio"] = OP_SelectZoneTeleporterDestinatio + om.nameToEmu["OP_SendLatestRequestMsg"] = OP_SendLatestRequestMsg + om.nameToEmu["OP_SendZonePointsMsg"] = OP_SendZonePointsMsg + om.nameToEmu["OP_SetInstanceDisplayNameMsg"] = OP_SetInstanceDisplayNameMsg + om.nameToEmu["OP_SetRemoteCmdsMsg"] = OP_SetRemoteCmdsMsg + om.nameToEmu["OP_SetSocialMsg"] = OP_SetSocialMsg + om.nameToEmu["OP_SetTimeMsg"] = OP_SetTimeMsg + om.nameToEmu["OP_ShaderCustomizationMsg"] = OP_ShaderCustomizationMsg + om.nameToEmu["OP_ShowCreateFromRecipeUIMsg"] = OP_ShowCreateFromRecipeUIMsg + om.nameToEmu["OP_ShowItemCreationProcessUIMsg"] = OP_ShowItemCreationProcessUIMsg + om.nameToEmu["OP_ShowRecipeBookMsg"] = OP_ShowRecipeBookMsg + om.nameToEmu["OP_ShowZoneTeleporterDestinations"] = OP_ShowZoneTeleporterDestinations + om.nameToEmu["OP_SignalMsg"] = OP_SignalMsg + om.nameToEmu["OP_SitMsg"] = OP_SitMsg + om.nameToEmu["OP_SkillInfoRequest"] = OP_SkillInfoRequest + om.nameToEmu["OP_SkillInfoRequestMsg"] = OP_SkillInfoRequestMsg + om.nameToEmu["OP_SkillInfoResponse"] = OP_SkillInfoResponse + om.nameToEmu["OP_SkillInfoResponseMsg"] = OP_SkillInfoResponseMsg + om.nameToEmu["OP_SkillUpMsg"] = OP_SkillUpMsg + om.nameToEmu["OP_SpellGainedMsg"] = OP_SpellGainedMsg + om.nameToEmu["OP_StandMsg"] = OP_StandMsg + om.nameToEmu["OP_StoodMsg"] = OP_StoodMsg + om.nameToEmu["OP_StopItemCreationMsg"] = OP_StopItemCreationMsg + om.nameToEmu["OP_StopTrackingMsg"] = OP_StopTrackingMsg + om.nameToEmu["OP_StoppedLootingMsg"] = OP_StoppedLootingMsg + om.nameToEmu["OP_SubmitCharCust"] = OP_SubmitCharCust + om.nameToEmu["OP_SysClient"] = OP_SysClient + om.nameToEmu["OP_TargetMsg"] = OP_TargetMsg + om.nameToEmu["OP_TeleportWithinZoneMsg"] = OP_TeleportWithinZoneMsg + om.nameToEmu["OP_TeleportWithinZoneNoReloadMsg"] = OP_TeleportWithinZoneNoReloadMsg + om.nameToEmu["OP_TellMsg"] = OP_TellMsg + om.nameToEmu["OP_TintWidgetsMsg"] = OP_TintWidgetsMsg + om.nameToEmu["OP_TitleUpdateMsg"] = OP_TitleUpdateMsg + om.nameToEmu["OP_TrackingUpdateMsg"] = OP_TrackingUpdateMsg + om.nameToEmu["OP_TradeAcceptMsg"] = OP_TradeAcceptMsg + om.nameToEmu["OP_TradeAddItemMsg"] = OP_TradeAddItemMsg + om.nameToEmu["OP_TradeEndMsg"] = OP_TradeEndMsg + om.nameToEmu["OP_TradeRemoveItemMsg"] = OP_TradeRemoveItemMsg + om.nameToEmu["OP_TradeRequestMsg"] = OP_TradeRequestMsg + om.nameToEmu["OP_TradeResponseMsg"] = OP_TradeResponseMsg + om.nameToEmu["OP_TradeStartMsg"] = OP_TradeStartMsg + om.nameToEmu["OP_TradeskillList"] = OP_TradeskillList + om.nameToEmu["OP_TraitsList"] = OP_TraitsList + om.nameToEmu["OP_UIEvent"] = OP_UIEvent + om.nameToEmu["OP_UIResetMsg"] = OP_UIResetMsg + om.nameToEmu["OP_UISettingsMsg"] = OP_UISettingsMsg + om.nameToEmu["OP_UISettingsResponseMsg"] = OP_UISettingsResponseMsg + om.nameToEmu["OP_UnequipItemMsg"] = OP_UnequipItemMsg + om.nameToEmu["OP_Unknown"] = OP_Unknown + om.nameToEmu["OP_UnknownNpcMsg"] = OP_UnknownNpcMsg + om.nameToEmu["OP_UpdateActivePublicZonesMsg"] = OP_UpdateActivePublicZonesMsg + om.nameToEmu["OP_UpdateCharacterSheetMsg"] = OP_UpdateCharacterSheetMsg + om.nameToEmu["OP_UpdateClientPredFlagsMsg"] = OP_UpdateClientPredFlagsMsg + om.nameToEmu["OP_UpdateDebugRadiiMsg"] = OP_UpdateDebugRadiiMsg + om.nameToEmu["OP_UpdateGroupMemberDataMsg"] = OP_UpdateGroupMemberDataMsg + om.nameToEmu["OP_UpdateHouseAccessDataMsg"] = OP_UpdateHouseAccessDataMsg + om.nameToEmu["OP_UpdateHouseDataMsg"] = OP_UpdateHouseDataMsg + om.nameToEmu["OP_UpdateInventoryMsg"] = OP_UpdateInventoryMsg + om.nameToEmu["OP_UpdateItemCreationProcessUIMsg"] = OP_UpdateItemCreationProcessUIMsg + om.nameToEmu["OP_UpdateMotdMsg"] = OP_UpdateMotdMsg + om.nameToEmu["OP_UpdateOpportunityMsg"] = OP_UpdateOpportunityMsg + om.nameToEmu["OP_UpdatePositionMsg"] = OP_UpdatePositionMsg + om.nameToEmu["OP_UpdateRaidMsg"] = OP_UpdateRaidMsg + om.nameToEmu["OP_UpdateRecipeBookMsg"] = OP_UpdateRecipeBookMsg + om.nameToEmu["OP_UpdateSkillBookMsg"] = OP_UpdateSkillBookMsg + om.nameToEmu["OP_UpdateSkillsMsg"] = OP_UpdateSkillsMsg + om.nameToEmu["OP_UpdateSpellBookMsg"] = OP_UpdateSpellBookMsg + om.nameToEmu["OP_UpdateTargetLocMsg"] = OP_UpdateTargetLocMsg + om.nameToEmu["OP_UpdateTargetMsg"] = OP_UpdateTargetMsg + om.nameToEmu["OP_UpdateTitleCmd"] = OP_UpdateTitleCmd + om.nameToEmu["OP_UseItemMsg"] = OP_UseItemMsg + om.nameToEmu["OP_WSAcctLockStatusMsg"] = OP_WSAcctLockStatusMsg + om.nameToEmu["OP_WSLoginRequestMsg"] = OP_WSLoginRequestMsg + om.nameToEmu["OP_WSServerHideMsg"] = OP_WSServerHideMsg + om.nameToEmu["OP_WSServerLockMsg"] = OP_WSServerLockMsg + om.nameToEmu["OP_WaypointReplyMsg"] = OP_WaypointReplyMsg + om.nameToEmu["OP_WaypointRequestMsg"] = OP_WaypointRequestMsg + om.nameToEmu["OP_WaypointSelectMsg"] = OP_WaypointSelectMsg + om.nameToEmu["OP_WaypointUpdateMsg"] = OP_WaypointUpdateMsg + om.nameToEmu["OP_Weakness"] = OP_Weakness + om.nameToEmu["OP_WhoQueryReplyMsg"] = OP_WhoQueryReplyMsg + om.nameToEmu["OP_WhoQueryRequestMsg"] = OP_WhoQueryRequestMsg + om.nameToEmu["OP_WorldDataChangeMsg"] = OP_WorldDataChangeMsg + om.nameToEmu["OP_WorldDataUpdateMsg"] = OP_WorldDataUpdateMsg + om.nameToEmu["OP_WorldPingMsg"] = OP_WorldPingMsg + om.nameToEmu["OP_WorldShutdownUpdateMsg"] = OP_WorldShutdownUpdateMsg + om.nameToEmu["OP_ZoneBgInstanceList"] = OP_ZoneBgInstanceList + om.nameToEmu["OP_ZoneChangeMsg"] = OP_ZoneChangeMsg + om.nameToEmu["OP_ZoneEntryMsg"] = OP_ZoneEntryMsg + om.nameToEmu["OP_ZoneExitMsg"] = OP_ZoneExitMsg + om.nameToEmu["OP_ZoneInfoMsg"] = OP_ZoneInfoMsg + om.nameToEmu["OP_ZoneInstanceCreateReplyMsg"] = OP_ZoneInstanceCreateReplyMsg + om.nameToEmu["OP_ZoneInstanceDestroyedMsg"] = OP_ZoneInstanceDestroyedMsg + om.nameToEmu["OP_ZoneListMsg"] = OP_ZoneListMsg + om.nameToEmu["OP_ZoneMOTDMsg"] = OP_ZoneMOTDMsg + om.nameToEmu["OP_ZonePointsMsg"] = OP_ZonePointsMsg + om.nameToEmu["OP_ZoneToFriendReplyMsg"] = OP_ZoneToFriendReplyMsg + om.nameToEmu["OP_ZoneToFriendRequestMsg"] = OP_ZoneToFriendRequestMsg + om.nameToEmu["OP_ZoneUnavailMsg"] = OP_ZoneUnavailMsg + om.nameToEmu["OP_ZonesStatusMsg"] = OP_ZonesStatusMsg + om.nameToEmu["OP_ZonesStatusRequestMsg"] = OP_ZonesStatusRequestMsg +} diff --git a/opcodes/login.go b/opcodes/login.go new file mode 100644 index 0000000..a5b42f4 --- /dev/null +++ b/opcodes/login.go @@ -0,0 +1,70 @@ +package opcodes + +// Login server opcodes +const ( + LS_LoginRequestMsg EmuOpcode = 0x0000 + LS_LoginReplyMsg EmuOpcode = 0x0001 + LS_WorldListMsg EmuOpcode = 0x0002 + LS_WorldStatusMsg EmuOpcode = 0x0003 + LS_AccessGrantedMsg EmuOpcode = 0x0004 + LS_SessionReadyMsg EmuOpcode = 0x0005 + LS_LoginFailedMsg EmuOpcode = 0x0006 + LS_LoginBannedMsg EmuOpcode = 0x0007 + LS_PlayCharRequestMsg EmuOpcode = 0x0008 + LS_PlayCharReplyMsg EmuOpcode = 0x0009 + LS_CreateCharRequestMsg EmuOpcode = 0x000a + LS_CreateCharReplyMsg EmuOpcode = 0x000b + LS_DeleteCharRequestMsg EmuOpcode = 0x000c + LS_DeleteCharReplyMsg EmuOpcode = 0x000d + LS_CharSelectMsg EmuOpcode = 0x000e + LS_CharListRequestMsg EmuOpcode = 0x000f + LS_CharListReplyMsg EmuOpcode = 0x0010 + LS_ServerListRequestMsg EmuOpcode = 0x0011 + LS_ServerListReplyMsg EmuOpcode = 0x0012 + LS_ServerStatusRequestMsg EmuOpcode = 0x0013 + LS_ServerStatusReplyMsg EmuOpcode = 0x0014 + LS_LSStatusRequestMsg EmuOpcode = 0x0015 + LS_LSStatusReplyMsg EmuOpcode = 0x0016 + LS_UsertoWorldReq EmuOpcode = 0x0017 + LS_UsertoWorldResp EmuOpcode = 0x0018 + LS_AllWorldsDescRequestMsg EmuOpcode = 0x0019 + LS_AllWorldsDescReplyMsg EmuOpcode = 0x001a + LS_CreateAccountRequestMsg EmuOpcode = 0x001b + LS_CreateAccountReplyMsg EmuOpcode = 0x001c + LS_LoginByNumRequestMsg EmuOpcode = 0x001d + LS_WSLoginRequestMsg EmuOpcode = 0x001e + LS_ESLoginRequestMsg EmuOpcode = 0x001f + LS_WorldStatusChangeMsg EmuOpcode = 0x0020 + LS_AllWSDescRequestMsg EmuOpcode = 0x0021 + LS_WSStatusReplyMsg EmuOpcode = 0x0022 + LS_AllCharactersDescRequestMsg EmuOpcode = 0x0023 + LS_AllCharactersDescReplyMsg EmuOpcode = 0x0024 + LS_CreateCharacterRequestMsg EmuOpcode = 0x0025 + LS_CreateCharacterReplyMsg EmuOpcode = 0x0026 + LS_ReskinCharacterRequestMsg EmuOpcode = 0x0027 + LS_WSCreateCharacterRequestMsg EmuOpcode = 0x0028 + LS_WSCreateCharacterReplyMsg EmuOpcode = 0x0029 + LS_DeleteCharacterRequestMsg EmuOpcode = 0x002a + LS_DeleteCharacterReplyMsg EmuOpcode = 0x002b + LS_PlayCharacterRequestMsg EmuOpcode = 0x002c + LS_PlayCharacterReplyMsg EmuOpcode = 0x002d + LS_ServerPlayCharacterRequestMsg EmuOpcode = 0x002e + LS_ServerPlayCharacterReplyMsg EmuOpcode = 0x002f + LS_KeymapLoadMsg EmuOpcode = 0x0030 + LS_KeymapNoneMsg EmuOpcode = 0x0031 + LS_KeymapDataMsg EmuOpcode = 0x0032 + LS_KeymapSaveMsg EmuOpcode = 0x0033 + LS_LSCheckAcctLockMsg EmuOpcode = 0x0034 + LS_WSAcctLockStatusMsg EmuOpcode = 0x0035 + LS_LsRequestClientCrashLogMsg EmuOpcode = 0x0036 + LS_LsClientBaselogReplyMsg EmuOpcode = 0x0037 + LS_LsClientCrashlogReplyMsg EmuOpcode = 0x0038 + LS_LsClientAlertlogReplyMsg EmuOpcode = 0x0039 + LS_LsClientVerifylogReplyMsg EmuOpcode = 0x003a + LS_BadLanguageFilter EmuOpcode = 0x003b + LS_WSServerLockMsg EmuOpcode = 0x003c + LS_WSServerHideMsg EmuOpcode = 0x003d + LS_LSServerLockMsg EmuOpcode = 0x003e + LS_UpdateCharacterSheetMsg EmuOpcode = 0x003f + LS_UpdateInventoryMsg EmuOpcode = 0x0040 +) diff --git a/opcodes/manager.go b/opcodes/manager.go new file mode 100644 index 0000000..d9e8801 --- /dev/null +++ b/opcodes/manager.go @@ -0,0 +1,257 @@ +package opcodes + +//go:generate go run gen/main.go + +import ( + "database/sql" + "fmt" + "sort" + "strings" + "sync" +) + +// OpcodeManager manages opcode translations for a specific client version +type OpcodeManager struct { + version int16 + emuToEQ map[EmuOpcode]uint16 + eqToEmu map[uint16]EmuOpcode + emuToName map[EmuOpcode]string + eqToName map[uint16]string + nameToEmu map[string]EmuOpcode + mu sync.RWMutex +} + +// NewOpcodeManager creates a new opcode manager for the specified version +func NewOpcodeManager(version int16) *OpcodeManager { + om := &OpcodeManager{ + version: version, + emuToEQ: make(map[EmuOpcode]uint16), + eqToEmu: make(map[uint16]EmuOpcode), + emuToName: make(map[EmuOpcode]string), + eqToName: make(map[uint16]string), + nameToEmu: make(map[string]EmuOpcode), + } + om.initializeNameMappings() // Generated by go:generate + return om +} + +// LoadFromDatabase loads opcode mappings from database +func (om *OpcodeManager) LoadFromDatabase(db *sql.DB, tableName string) error { + query := ` + SELECT name, opcode + FROM ` + tableName + ` + WHERE ? >= version_range1 + AND (version_range2 = 0 OR ? <= version_range2) + ORDER BY version_range1 DESC, version_range2 DESC + ` + + rows, err := db.Query(query, om.version, om.version) + if err != nil { + return err + } + defer rows.Close() + + om.mu.Lock() + defer om.mu.Unlock() + + loaded := make(map[string]bool) + + for rows.Next() { + var name string + var opcode int16 + + if err := rows.Scan(&name, &opcode); err != nil { + continue + } + + if loaded[name] { + continue + } + loaded[name] = true + + eqOpcode := uint16(opcode) + + // Only map if we have a constant for this opcode name + if emuOp, ok := om.nameToEmu[name]; ok { + om.emuToEQ[emuOp] = eqOpcode + om.eqToEmu[eqOpcode] = emuOp + om.emuToName[emuOp] = name + om.eqToName[eqOpcode] = name + } + } + + // Map missing opcodes to 0xFFFF + for name, emuOp := range om.nameToEmu { + if _, ok := om.emuToEQ[emuOp]; !ok { + om.emuToEQ[emuOp] = 0xFFFF + om.emuToName[emuOp] = name + } + } + + return rows.Err() +} + +// EmuToEQ converts emulator opcode to EQ opcode +func (om *OpcodeManager) EmuToEQ(emu EmuOpcode) uint16 { + om.mu.RLock() + defer om.mu.RUnlock() + + if eq, ok := om.emuToEQ[emu]; ok { + return eq + } + return 0xFFFF +} + +// EQToEmu converts EQ opcode to emulator opcode +func (om *OpcodeManager) EQToEmu(eq uint16) EmuOpcode { + om.mu.RLock() + defer om.mu.RUnlock() + + if emu, ok := om.eqToEmu[eq]; ok { + return emu + } + return OP_Unknown +} + +// EmuToName returns the name of an emulator opcode +func (om *OpcodeManager) EmuToName(emu EmuOpcode) string { + om.mu.RLock() + defer om.mu.RUnlock() + + if name, ok := om.emuToName[emu]; ok { + return name + } + return "OP_Unknown" +} + +// EQToName returns the name of an EQ opcode +func (om *OpcodeManager) EQToName(eq uint16) string { + om.mu.RLock() + defer om.mu.RUnlock() + + if name, ok := om.eqToName[eq]; ok { + return name + } + return "OP_Unknown" +} + +// GetMissingOpcodes returns list of opcodes that map to 0xFFFF +func (om *OpcodeManager) GetMissingOpcodes() []string { + om.mu.RLock() + defer om.mu.RUnlock() + + var missing []string + for emu, eq := range om.emuToEQ { + if eq == 0xFFFF { + if name, ok := om.emuToName[emu]; ok { + missing = append(missing, name) + } + } + } + return missing +} + +// IsValidOpcode checks if an EQ opcode is valid/known +func (om *OpcodeManager) IsValidOpcode(eq uint16) bool { + om.mu.RLock() + defer om.mu.RUnlock() + + _, exists := om.eqToEmu[eq] + return exists +} + +// DumpOpcodes returns a formatted string of all loaded opcodes for debugging +func (om *OpcodeManager) DumpOpcodes() string { + om.mu.RLock() + defer om.mu.RUnlock() + + var sb strings.Builder + sb.WriteString(fmt.Sprintf("Opcode Manager for version %d:\n", om.version)) + sb.WriteString("=====================================\n") + + var eqOpcodes []uint16 + for eq := range om.eqToEmu { + eqOpcodes = append(eqOpcodes, eq) + } + sort.Slice(eqOpcodes, func(i, j int) bool { + return eqOpcodes[i] < eqOpcodes[j] + }) + + for _, eq := range eqOpcodes { + emu := om.eqToEmu[eq] + name := om.eqToName[eq] + sb.WriteString(fmt.Sprintf("0x%04x -> 0x%04x : %s\n", eq, emu, name)) + } + + return sb.String() +} + +// GetStats returns statistics about loaded opcodes +func (om *OpcodeManager) GetStats() map[string]int { + om.mu.RLock() + defer om.mu.RUnlock() + + return map[string]int{ + "version": int(om.version), + "total_opcodes": len(om.eqToEmu), + "named_opcodes": len(om.emuToName), + "mapped_opcodes": len(om.emuToEQ), + } +} + +// Global managers cache +var ( + managers = make(map[int16]*OpcodeManager) + managersMu sync.RWMutex +) + +// GetManager returns opcode manager for a version +func GetManager(version int16, db *sql.DB, tableName string) *OpcodeManager { + managersMu.RLock() + if mgr, ok := managers[version]; ok { + managersMu.RUnlock() + return mgr + } + managersMu.RUnlock() + + managersMu.Lock() + defer managersMu.Unlock() + + if mgr, ok := managers[version]; ok { + return mgr + } + + mgr := NewOpcodeManager(version) + if db != nil { + if err := mgr.LoadFromDatabase(db, tableName); err != nil { + fmt.Printf("Warning: Failed to load opcodes for version %d: %v\n", version, err) + } + } + + managers[version] = mgr + return mgr +} + +// ClearCache clears the cached managers (useful for testing) +func ClearCache() { + managersMu.Lock() + defer managersMu.Unlock() + managers = make(map[int16]*OpcodeManager) +} + +// GetLoadedVersions returns all versions that have managers loaded +func GetLoadedVersions() []int16 { + managersMu.RLock() + defer managersMu.RUnlock() + + var versions []int16 + for v := range managers { + versions = append(versions, v) + } + + sort.Slice(versions, func(i, j int) bool { + return versions[i] < versions[j] + }) + + return versions +} diff --git a/opcodes/protocol.go b/opcodes/protocol.go new file mode 100644 index 0000000..2a93de7 --- /dev/null +++ b/opcodes/protocol.go @@ -0,0 +1,18 @@ +package opcodes + +// Protocol-level opcodes used by the network layer +const ( + OP_SessionRequest uint16 = 0x0001 + OP_SessionResponse uint16 = 0x0002 + OP_Combined uint16 = 0x0003 + OP_SessionDisconnect uint16 = 0x0005 + OP_KeepAlive uint16 = 0x0006 + OP_SessionStatRequest uint16 = 0x0007 + OP_SessionStatResponse uint16 = 0x0008 + OP_Packet uint16 = 0x0009 + OP_Fragment uint16 = 0x000d + OP_Ack uint16 = 0x0015 + OP_AppCombined uint16 = 0x0019 + OP_OutOfOrderAck uint16 = 0x001d + OP_OutOfSession uint16 = 0x001e +) diff --git a/opcodes/types.go b/opcodes/types.go new file mode 100644 index 0000000..614454a --- /dev/null +++ b/opcodes/types.go @@ -0,0 +1,12 @@ +package opcodes + +// EmuOpcode represents an emulator opcode +type EmuOpcode uint16 + +// Manager handles opcode translation between emulator and EQ2 formats +type Manager interface { + EmuToEQ(emu EmuOpcode) uint16 + EQToEmu(eq uint16) EmuOpcode + EmuToName(emu EmuOpcode) string + EQToName(eq uint16) string +} diff --git a/packets/apppacket.go b/packets/apppacket.go new file mode 100644 index 0000000..66d5245 --- /dev/null +++ b/packets/apppacket.go @@ -0,0 +1,245 @@ +package packets + +import ( + "encoding/binary" +) + +// DefaultOpcodeSize is the default opcode size for application packets +var DefaultOpcodeSize uint8 = 2 + +// EmuOpcode represents an emulator opcode +type EmuOpcode uint16 + +// Common emulator opcodes +const ( + OpUnknown EmuOpcode = 0 + // Add other opcodes as needed from op_codes.h +) + +// AppPacket handles high-level game opcodes and application data +// This is the main packet type used by game logic +type AppPacket struct { + *Packet + + emuOpcode EmuOpcode // Cached emulator opcode + opcodeSize uint8 // Size of opcode in bytes (1 or 2) +} + +// NewAppPacket creates a new application packet +func NewAppPacket() *AppPacket { + return &AppPacket{ + Packet: NewPacket(0, nil), + emuOpcode: OpUnknown, + opcodeSize: DefaultOpcodeSize, + } +} + +// NewAppPacketWithOp creates a new application packet with opcode +func NewAppPacketWithOp(op EmuOpcode) *AppPacket { + app := &AppPacket{ + Packet: NewPacket(0, nil), + opcodeSize: DefaultOpcodeSize, + } + app.SetOpcode(op) + return app +} + +// NewAppPacketWithSize creates a new application packet with opcode and size +func NewAppPacketWithSize(op EmuOpcode, size uint32) *AppPacket { + app := &AppPacket{ + Packet: NewPacket(0, make([]byte, size)), + opcodeSize: DefaultOpcodeSize, + } + app.SetOpcode(op) + return app +} + +// NewAppPacketWithData creates a new application packet with opcode and data +func NewAppPacketWithData(op EmuOpcode, data []byte) *AppPacket { + app := &AppPacket{ + Packet: NewPacket(0, data), + opcodeSize: DefaultOpcodeSize, + } + app.SetOpcode(op) + return app +} + +// NewAppPacketFromRaw creates app packet from raw buffer (used by ProtoPacket) +// Assumes first bytes are opcode based on opcodeSize +func NewAppPacketFromRaw(buf []byte, opcodeSize uint8) *AppPacket { + if opcodeSize == 0 { + opcodeSize = DefaultOpcodeSize + } + + app := &AppPacket{ + Packet: NewPacket(0, nil), + opcodeSize: opcodeSize, + } + + if opcodeSize == 1 && len(buf) >= 1 { + app.Opcode = uint16(buf[0]) + if len(buf) > 1 { + app.Buffer = make([]byte, len(buf)-1) + copy(app.Buffer, buf[1:]) + } + } else if len(buf) >= 2 { + app.Opcode = binary.BigEndian.Uint16(buf[:2]) + if len(buf) > 2 { + app.Buffer = make([]byte, len(buf)-2) + copy(app.Buffer, buf[2:]) + } + } + + return app +} + +// Size returns total packet size including opcode +func (a *AppPacket) Size() uint32 { + return uint32(len(a.Buffer)) + uint32(a.opcodeSize) +} + +// SetOpcodeSize sets the opcode size +func (a *AppPacket) SetOpcodeSize(size uint8) { + a.opcodeSize = size +} + +// SetOpcode sets the emulator opcode +func (a *AppPacket) SetOpcode(op EmuOpcode) { + a.emuOpcode = op + // In full implementation, this would convert to protocol opcode + // using opcode manager. For now, direct assignment + a.Opcode = uint16(op) +} + +// GetOpcode returns the emulator opcode (with caching) +func (a *AppPacket) GetOpcode() EmuOpcode { + if a.emuOpcode == OpUnknown { + // In full implementation, convert from protocol opcode + a.emuOpcode = EmuOpcode(a.Opcode) + } + return a.emuOpcode +} + +// Copy creates a deep copy of this application packet +func (a *AppPacket) Copy() *AppPacket { + newApp := &AppPacket{ + Packet: NewPacket(a.Opcode, a.Buffer), + emuOpcode: a.emuOpcode, + opcodeSize: a.opcodeSize, + } + newApp.Packet.CopyInfo(a.Packet) + return newApp +} + +// Serialize writes the application packet to a destination buffer +// Handles special opcode encoding rules for application-level packets +func (a *AppPacket) Serialize(dest []byte) uint32 { + opcodeBytes := a.opcodeSize + pos := 0 + + if a.opcodeSize == 1 { + // Single-byte opcode + dest[pos] = byte(a.Opcode) + pos++ + } else { + // Two-byte opcode with special encoding rules + // Application opcodes with low byte = 0x00 need extra 0x00 prefix + if (a.Opcode & 0x00ff) == 0 { + dest[pos] = 0 + pos++ + binary.BigEndian.PutUint16(dest[pos:], a.Opcode) + pos += 2 + opcodeBytes++ + } else { + binary.BigEndian.PutUint16(dest[pos:], a.Opcode) + pos += 2 + } + } + + // Copy packet data after opcode + copy(dest[pos:], a.Buffer) + + return uint32(len(a.Buffer)) + uint32(opcodeBytes) +} + +// Combine combines this packet with another application packet +func (a *AppPacket) Combine(rhs *AppPacket) bool { + const opAppCombined = 0x19 // OP_AppCombined + + // Check if we can combine these packets + totalSize := a.Size() + rhs.Size() + if totalSize > 512 { // Reasonable max combined packet size + return false + } + + // If this isn't already a combined packet, convert it + if a.Opcode != opAppCombined { + // Create combined packet structure + oldSize := a.Size() + newSize := oldSize + rhs.Size() + 2 // +2 for size headers + + newBuffer := make([]byte, newSize) + pos := 0 + + // Write first packet size and data + newBuffer[pos] = byte(oldSize) + pos++ + + // Serialize first packet + tmpBuf := make([]byte, oldSize) + a.Serialize(tmpBuf) + copy(newBuffer[pos:], tmpBuf) + pos += int(oldSize) + + // Write second packet size and data + rhsSize := rhs.Size() + newBuffer[pos] = byte(rhsSize) + pos++ + + // Serialize second packet + tmpBuf = make([]byte, rhsSize) + rhs.Serialize(tmpBuf) + copy(newBuffer[pos:], tmpBuf) + + // Update this packet to be a combined packet + a.Opcode = opAppCombined + a.Buffer = newBuffer + return true + } + + // This is already a combined packet, add to it + rhsSize := rhs.Size() + if rhsSize >= 255 { + // Oversized packet handling + newBuffer := make([]byte, len(a.Buffer)+int(rhsSize)+3) + copy(newBuffer, a.Buffer) + pos := len(a.Buffer) + + newBuffer[pos] = 255 // Oversized marker + pos++ + binary.BigEndian.PutUint16(newBuffer[pos:], uint16(rhsSize)) + pos += 2 + + tmpBuf := make([]byte, rhsSize) + rhs.Serialize(tmpBuf) + copy(newBuffer[pos:], tmpBuf) + + a.Buffer = newBuffer + } else { + // Normal sized addition + newBuffer := make([]byte, len(a.Buffer)+int(rhsSize)+1) + copy(newBuffer, a.Buffer) + pos := len(a.Buffer) + + newBuffer[pos] = byte(rhsSize) + pos++ + + tmpBuf := make([]byte, rhsSize) + rhs.Serialize(tmpBuf) + copy(newBuffer[pos:], tmpBuf) + + a.Buffer = newBuffer + } + + return true +} diff --git a/packets/helpers.go b/packets/helpers.go new file mode 100644 index 0000000..0ae2b41 --- /dev/null +++ b/packets/helpers.go @@ -0,0 +1,43 @@ +package packets + +import "fmt" + +// ValidateCRC validates packet CRC +func ValidateCRC(buffer []byte, key uint32) bool { + // TODO: Implement CRC validation + return true +} + +// Compress compresses packet data using zlib +func Compress(src []byte) ([]byte, error) { + // TODO: Implement zlib compression + return src, nil +} + +// Decompress decompresses packet data using zlib +func Decompress(src []byte) ([]byte, error) { + // TODO: Implement zlib decompression + return src, nil +} + +// ChatEncode encodes chat data +func ChatEncode(buffer []byte, encodeKey int) { + // TODO: Implement chat encoding +} + +// ChatDecode decodes chat data +func ChatDecode(buffer []byte, decodeKey int) { + // TODO: Implement chat decoding +} + +// IsProtocolPacket checks if buffer contains a valid protocol packet +func IsProtocolPacket(buffer []byte, trimCRC bool) bool { + // TODO: Implement protocol packet validation + return len(buffer) >= 2 +} + +// Helper function to convert uint32 IP to string +func longToIP(ip uint32) string { + return fmt.Sprintf("%d.%d.%d.%d", + byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)) +} diff --git a/packets/packet.go b/packets/packet.go new file mode 100644 index 0000000..2bbe090 --- /dev/null +++ b/packets/packet.go @@ -0,0 +1,89 @@ +package packets + +import ( + "fmt" + "io" + "time" +) + +// Packet is the base struct for all EverQuest packet types +type Packet struct { + Buffer []byte + Opcode uint16 + + SrcIP uint32 + DstIP uint32 + SrcPort uint16 + DstPort uint16 + + Priority uint32 + Timestamp time.Time + Version int16 +} + +// NewPacket creates a new packet with the given opcode and data +func NewPacket(opcode uint16, data []byte) *Packet { + p := &Packet{ + Opcode: opcode, + Timestamp: time.Now(), + } + if len(data) > 0 { + p.Buffer = make([]byte, len(data)) + copy(p.Buffer, data) + } + return p +} + +// Size returns the total packet size including opcode +func (p *Packet) Size() uint32 { + return uint32(len(p.Buffer)) + 2 +} + +// RawOpcode returns the raw opcode value +func (p *Packet) RawOpcode() uint16 { + return p.Opcode +} + +// SetSrcInfo sets source IP and port +func (p *Packet) SetSrcInfo(ip uint32, port uint16) { + p.SrcIP = ip + p.SrcPort = port +} + +// SetDstInfo sets destination IP and port +func (p *Packet) SetDstInfo(ip uint32, port uint16) { + p.DstIP = ip + p.DstPort = port +} + +// CopyInfo copies network and timing info from another packet +func (p *Packet) CopyInfo(other *Packet) { + p.SrcIP = other.SrcIP + p.SrcPort = other.SrcPort + p.DstIP = other.DstIP + p.DstPort = other.DstPort + p.Timestamp = other.Timestamp + p.Version = other.Version +} + +// DumpRaw writes packet contents to writer for debugging +func (p *Packet) DumpRaw(w io.Writer) { + p.DumpRawHeader(0xffff, w) + if len(p.Buffer) > 0 { + // TODO: Implement dump_message_column equivalent + fmt.Fprintf(w, "[Data: %d bytes]\n", len(p.Buffer)) + } +} + +// DumpRawHeader writes packet header info to writer +func (p *Packet) DumpRawHeader(seq uint16, w io.Writer) { + if p.SrcIP != 0 { + fmt.Fprintf(w, "[%s:%d->%s:%d] ", + longToIP(p.SrcIP), p.SrcPort, + longToIP(p.DstIP), p.DstPort) + } + if seq != 0xffff { + fmt.Fprintf(w, "[Seq=%d] ", seq) + } + fmt.Fprintf(w, "[OpCode 0x%04x Size=%d]\n", p.Opcode, len(p.Buffer)) +} diff --git a/packets/protopacket.go b/packets/protopacket.go new file mode 100644 index 0000000..e82f2a1 --- /dev/null +++ b/packets/protopacket.go @@ -0,0 +1,281 @@ +package packets + +import ( + "encoding/binary" + "time" +) + +// ProtoPacket handles low-level protocol features including EQ2-specific operations +// Merges functionality from EQProtocolPacket and EQ2Packet +type ProtoPacket struct { + *Packet + + // Protocol state flags (using bitfield) + flags uint8 // bit 0: compressed, bit 1: prepared, bit 2: encrypted, bit 3: acked + + // EQ2-specific + LoginOp EmuOpcode // From EQ2Packet + + // Reliability and sequencing + Sequence int32 + SentTime int32 + AttemptCount int8 +} + +// Protocol flag constants +const ( + FlagCompressed = 1 << iota + FlagPrepared + FlagEncrypted + FlagAcked +) + +// NewProtoPacket creates a protocol packet with opcode and buffer +func NewProtoPacket(op uint16, buf []byte) *ProtoPacket { + return &ProtoPacket{ + Packet: NewPacket(op, buf), + } +} + +// NewProtoPacketFromRaw creates a protocol packet from raw buffer +func NewProtoPacketFromRaw(buf []byte, opcodeOverride int) *ProtoPacket { + var offset uint32 + var opcode uint16 + + if opcodeOverride >= 0 { + opcode = uint16(opcodeOverride) + } else if len(buf) >= 2 { + opcode = binary.BigEndian.Uint16(buf[:2]) + offset = 2 + } + + var data []byte + if uint32(len(buf)) > offset { + data = make([]byte, len(buf)-int(offset)) + copy(data, buf[offset:]) + } + + return &ProtoPacket{ + Packet: &Packet{ + Opcode: opcode, + Buffer: data, + Timestamp: time.Now(), + }, + } +} + +// IsCompressed returns true if packet is compressed +func (p *ProtoPacket) IsCompressed() bool { + return p.flags&FlagCompressed != 0 +} + +// SetCompressed sets the compressed flag +func (p *ProtoPacket) SetCompressed(compressed bool) { + if compressed { + p.flags |= FlagCompressed + } else { + p.flags &^= FlagCompressed + } +} + +// IsPrepared returns true if packet has been prepared for sending +func (p *ProtoPacket) IsPrepared() bool { + return p.flags&FlagPrepared != 0 +} + +// SetPrepared sets the prepared flag +func (p *ProtoPacket) SetPrepared(prepared bool) { + if prepared { + p.flags |= FlagPrepared + } else { + p.flags &^= FlagPrepared + } +} + +// IsEncrypted returns true if packet is encrypted +func (p *ProtoPacket) IsEncrypted() bool { + return p.flags&FlagEncrypted != 0 +} + +// SetEncrypted sets the encrypted flag +func (p *ProtoPacket) SetEncrypted(encrypted bool) { + if encrypted { + p.flags |= FlagEncrypted + } else { + p.flags &^= FlagEncrypted + } +} + +// IsAcked returns true if packet has been acknowledged +func (p *ProtoPacket) IsAcked() bool { + return p.flags&FlagAcked != 0 +} + +// SetAcked sets the acknowledged flag +func (p *ProtoPacket) SetAcked(acked bool) { + if acked { + p.flags |= FlagAcked + } else { + p.flags &^= FlagAcked + } +} + +// Copy creates a deep copy of this protocol packet +func (p *ProtoPacket) Copy() *ProtoPacket { + newPacket := &ProtoPacket{ + Packet: NewPacket(p.Opcode, p.Buffer), + flags: p.flags, + LoginOp: p.LoginOp, + Sequence: p.Sequence, + SentTime: p.SentTime, + AttemptCount: p.AttemptCount, + } + newPacket.Packet.CopyInfo(p.Packet) + return newPacket +} + +// Serialize writes the protocol packet to a destination buffer +func (p *ProtoPacket) Serialize(dest []byte, offset int8) uint32 { + // Write opcode (2 bytes) + if p.Opcode > 0xff { + binary.BigEndian.PutUint16(dest, p.Opcode) + } else { + dest[0] = 0 + dest[1] = byte(p.Opcode) + } + + // Copy packet data after opcode + if offset < int8(len(p.Buffer)) { + copy(dest[2:], p.Buffer[offset:]) + } + + return uint32(len(p.Buffer)-int(offset)) + 2 +} + +// AppCombine combines this packet with another for efficient transmission (from EQ2Packet) +func (p *ProtoPacket) AppCombine(rhs *ProtoPacket) bool { + const opAppCombined = 0x19 // OP_AppCombined value + + // Case 1: This packet is already a combined packet + if p.Opcode == opAppCombined && (len(p.Buffer)+len(rhs.Buffer)+3) < 255 { + tmpSize := len(rhs.Buffer) - 2 + overSized := tmpSize >= 255 + + var newSize int + if overSized { + newSize = len(p.Buffer) + tmpSize + 3 + } else { + newSize = len(p.Buffer) + tmpSize + 1 + } + + tmpBuffer := make([]byte, newSize) + pos := 0 + + // Copy existing combined packet data + copy(tmpBuffer, p.Buffer) + pos += len(p.Buffer) + + // Add size information for the new packet + if overSized { + tmpBuffer[pos] = 255 + pos++ + binary.BigEndian.PutUint16(tmpBuffer[pos:], uint16(tmpSize)) + pos += 2 + } else { + tmpBuffer[pos] = byte(tmpSize) + pos++ + } + + // Copy the new packet data (skip first 2 bytes which are opcode) + if len(rhs.Buffer) > 2 { + copy(tmpBuffer[pos:], rhs.Buffer[2:]) + } + + p.Buffer = tmpBuffer + return true + } + + // Case 2: Create new combined packet + // Implementation would continue here for other combine cases + // Simplified for brevity + + return false +} + +// PreparePacket prepares an EQ2 packet for transmission (from EQ2Packet) +func (p *ProtoPacket) PreparePacket(maxLen int16) int8 { + if p.IsPrepared() { + return 0 + } + + p.SetPrepared(true) + + // Convert emulator opcode to network opcode + // This would use opcode manager in full implementation + loginOpcode := p.LoginOp // Simplified - would do actual conversion + + var offset int8 + newSize := len(p.Buffer) + 2 + 1 // sequence(2) + compressed_flag(1) + oversized := false + + // Handle different opcode sizes and formats + if loginOpcode != 2 { + newSize++ // opcode type byte + if loginOpcode >= 255 { + newSize += 2 // oversized opcode + oversized = true + } + } + + // Build new packet buffer + newBuffer := make([]byte, newSize) + ptr := 2 // Skip sequence field + + if loginOpcode != 2 { + if oversized { + ptr++ // Skip compressed flag position + newBuffer[ptr] = 0xff // Oversized marker + ptr++ + binary.BigEndian.PutUint16(newBuffer[ptr:], uint16(loginOpcode)) + ptr += 2 + } else { + binary.BigEndian.PutUint16(newBuffer[ptr:], uint16(loginOpcode)) + ptr += 2 + } + } else { + newBuffer[ptr] = byte(loginOpcode) + ptr++ + } + + // Copy original packet data + copy(newBuffer[ptr:], p.Buffer) + + p.Buffer = newBuffer + offset = int8(newSize - len(p.Buffer) - 1) + + return offset +} + +// MakeApplicationPacket converts protocol packet to application packet +func (p *ProtoPacket) MakeApplicationPacket(opcodeSize uint8) *AppPacket { + if opcodeSize == 0 { + opcodeSize = DefaultOpcodeSize + } + + app := &AppPacket{ + Packet: NewPacket(0, p.Buffer), + opcodeSize: opcodeSize, + } + app.CopyInfo(p.Packet) + + // Parse opcode from buffer based on size + if opcodeSize == 1 && len(p.Buffer) >= 1 { + app.Opcode = uint16(p.Buffer[0]) + app.Buffer = p.Buffer[1:] + } else if len(p.Buffer) >= 2 { + app.Opcode = binary.BigEndian.Uint16(p.Buffer[:2]) + app.Buffer = p.Buffer[2:] + } + + return app +} diff --git a/packets/types.go b/packets/types.go new file mode 100644 index 0000000..9b2ac02 --- /dev/null +++ b/packets/types.go @@ -0,0 +1,42 @@ +package packets + +// PacketSerializer interface for common packet operations +type PacketSerializer interface { + Serialize(dest []byte) uint32 + Size() uint32 + Copy() PacketSerializer +} + +// OpcodeManager interface for opcode translation +type OpcodeManager interface { + EmuToEQ(emu EmuOpcode) uint16 + EQToEmu(eq uint16) EmuOpcode + EmuToName(emu EmuOpcode) string + EQToName(eq uint16) string +} + +// Stream states +type StreamState uint8 + +const ( + StateDisconnected StreamState = iota + StateConnecting + StateEstablished + StateClosing + StateClosed +) + +// Packet priority levels +const ( + PriorityLow uint32 = 0 + PriorityNormal uint32 = 5 + PriorityHigh uint32 = 10 +) + +// Max packet sizes +const ( + MaxPacketSize = 0xFFFF + DefaultMTU = 1450 + MaxCombinedSize = 512 + MaxFragmentChunk = 0xFFFF +)