Add multi-expansion support with data-driven protocol layer

Replace hardcoded WotLK protocol constants with a data-driven architecture
supporting Classic 1.12.1, TBC 2.4.3, and WotLK 3.3.5a. Each expansion
has JSON profiles for opcodes, update fields, and DBC layouts, plus C++
polymorphic packet parsers for binary format differences (movement flags,
speed fields, transport data, spline format, char enum layout).

Key components:
- ExpansionRegistry: scans Data/expansions/*/expansion.json at startup
- OpcodeTable: logical enum <-> wire values loaded from JSON
- UpdateFieldTable: field indices loaded from JSON per expansion
- DBCLayout: schema-driven DBC field lookups replacing magic numbers
- PacketParsers: WotLK/TBC/Classic parsers with correct flag positions
- Multi-manifest AssetManager: layered manifests with priority ordering
- HDPackManager: overlay texture packs with expansion compatibility
- Auth screen expansion picker replacing hardcoded version dropdown
This commit is contained in:
Kelsi 2026-02-12 22:56:36 -08:00
parent aa16a687c2
commit 7092844b5e
51 changed files with 5258 additions and 887 deletions

View file

@ -0,0 +1,92 @@
{
"Spell": {
"ID": 0, "Attributes": 5, "IconID": 124,
"Name": 127, "Tooltip": 154, "Rank": 136
},
"ItemDisplayInfo": {
"ID": 0, "LeftModel": 1, "LeftModelTexture": 3,
"InventoryIcon": 5, "GeosetGroup1": 7, "GeosetGroup3": 9
},
"CharSections": {
"RaceID": 1, "SexID": 2, "BaseSection": 3,
"Texture1": 4, "Texture2": 5, "Texture3": 6,
"VariationIndex": 8, "ColorIndex": 9
},
"SpellIcon": { "ID": 0, "Path": 1 },
"FactionTemplate": {
"ID": 0, "Faction": 1, "FactionGroup": 3,
"FriendGroup": 4, "EnemyGroup": 5,
"Enemy0": 6, "Enemy1": 7, "Enemy2": 8, "Enemy3": 9
},
"Faction": {
"ID": 0, "ReputationRaceMask0": 2, "ReputationRaceMask1": 3,
"ReputationRaceMask2": 4, "ReputationRaceMask3": 5,
"ReputationBase0": 10, "ReputationBase1": 11,
"ReputationBase2": 12, "ReputationBase3": 13
},
"AreaTable": { "ID": 0, "ExploreFlag": 3 },
"CreatureDisplayInfoExtra": {
"ID": 0, "RaceID": 1, "SexID": 2, "SkinID": 3, "FaceID": 4,
"HairStyleID": 5, "HairColorID": 6, "FacialHairID": 7,
"EquipDisplay0": 8, "EquipDisplay1": 9, "EquipDisplay2": 10,
"EquipDisplay3": 11, "EquipDisplay4": 12, "EquipDisplay5": 13,
"EquipDisplay6": 14, "EquipDisplay7": 15, "EquipDisplay8": 16,
"EquipDisplay9": 17, "EquipDisplay10": 18, "BakeName": 20
},
"CreatureDisplayInfo": {
"ID": 0, "ModelID": 1, "ExtraDisplayId": 3,
"Skin1": 6, "Skin2": 7, "Skin3": 8
},
"TaxiNodes": {
"ID": 0, "MapID": 1, "X": 2, "Y": 3, "Z": 4, "Name": 5,
"MountDisplayIdAlliance": 12, "MountDisplayIdHorde": 13
},
"TaxiPath": { "ID": 0, "FromNode": 1, "ToNode": 2, "Cost": 3 },
"TaxiPathNode": {
"ID": 0, "PathID": 1, "NodeIndex": 2, "MapID": 3,
"X": 4, "Y": 5, "Z": 6
},
"TalentTab": {
"ID": 0, "Name": 1, "ClassMask": 12,
"OrderIndex": 14, "BackgroundFile": 15
},
"Talent": {
"ID": 0, "TabID": 1, "Row": 2, "Column": 3,
"RankSpell0": 4, "PrereqTalent0": 9, "PrereqRank0": 12
},
"SkillLineAbility": { "SkillLineID": 1, "SpellID": 2 },
"SkillLine": { "ID": 0, "Category": 1, "Name": 3 },
"Map": { "ID": 0, "InternalName": 1 },
"CreatureModelData": { "ID": 0, "ModelPath": 2 },
"CharHairGeosets": {
"RaceID": 1, "SexID": 2, "Variation": 3, "GeosetID": 4
},
"CharacterFacialHairStyles": {
"RaceID": 0, "SexID": 1, "Variation": 2,
"Geoset100": 3, "Geoset300": 4, "Geoset200": 5
},
"GameObjectDisplayInfo": { "ID": 0, "ModelName": 1 },
"Emotes": { "ID": 0, "AnimID": 2 },
"EmotesText": {
"Command": 1, "EmoteRef": 2,
"SenderTargetTextID": 5, "SenderNoTargetTextID": 9
},
"EmotesTextData": { "ID": 0, "Text": 1 },
"Light": {
"ID": 0, "MapID": 1, "X": 2, "Z": 3, "Y": 4,
"InnerRadius": 5, "OuterRadius": 6, "LightParamsID": 7,
"LightParamsIDRain": 8, "LightParamsIDUnderwater": 9
},
"LightParams": { "LightParamsID": 0 },
"LightIntBand": {
"BlockIndex": 1, "NumKeyframes": 2, "TimeKey0": 3, "Value0": 19
},
"LightFloatBand": {
"BlockIndex": 1, "NumKeyframes": 2, "TimeKey0": 3, "Value0": 19
},
"WorldMapArea": {
"ID": 0, "MapID": 1, "AreaID": 2, "AreaName": 3,
"LocLeft": 4, "LocRight": 5, "LocTop": 6, "LocBottom": 7,
"DisplayMapID": 8, "ParentWorldMapID": 10
}
}

View file

@ -0,0 +1,11 @@
{
"id": "classic",
"name": "Classic",
"shortName": "Classic",
"version": { "major": 1, "minor": 12, "patch": 1 },
"build": 5875,
"protocolVersion": 8,
"maxLevel": 60,
"races": [1, 2, 3, 4, 5, 6, 7, 8],
"classes": [1, 2, 3, 4, 5, 7, 8, 9, 11]
}

View file

@ -0,0 +1,226 @@
{
"CMSG_PING": "0x1DC",
"CMSG_AUTH_SESSION": "0x1ED",
"CMSG_CHAR_CREATE": "0x036",
"CMSG_CHAR_ENUM": "0x037",
"CMSG_CHAR_DELETE": "0x038",
"CMSG_PLAYER_LOGIN": "0x03D",
"CMSG_MOVE_START_FORWARD": "0x0B5",
"CMSG_MOVE_START_BACKWARD": "0x0B6",
"CMSG_MOVE_STOP": "0x0B7",
"CMSG_MOVE_START_STRAFE_LEFT": "0x0B8",
"CMSG_MOVE_START_STRAFE_RIGHT": "0x0B9",
"CMSG_MOVE_STOP_STRAFE": "0x0BA",
"CMSG_MOVE_JUMP": "0x0BB",
"CMSG_MOVE_START_TURN_LEFT": "0x0BC",
"CMSG_MOVE_START_TURN_RIGHT": "0x0BD",
"CMSG_MOVE_STOP_TURN": "0x0BE",
"CMSG_MOVE_SET_FACING": "0x0DA",
"CMSG_MOVE_FALL_LAND": "0x0C9",
"CMSG_MOVE_START_SWIM": "0x0CA",
"CMSG_MOVE_STOP_SWIM": "0x0CB",
"CMSG_MOVE_HEARTBEAT": "0x0EE",
"SMSG_AUTH_CHALLENGE": "0x1EC",
"SMSG_AUTH_RESPONSE": "0x1EE",
"SMSG_CHAR_CREATE": "0x03A",
"SMSG_CHAR_ENUM": "0x03B",
"SMSG_CHAR_DELETE": "0x03C",
"SMSG_PONG": "0x1DD",
"SMSG_LOGIN_VERIFY_WORLD": "0x236",
"SMSG_LOGIN_SETTIMESPEED": "0x042",
"SMSG_TUTORIAL_FLAGS": "0x0FD",
"SMSG_WARDEN_DATA": "0x2E6",
"CMSG_WARDEN_DATA": "0x2E7",
"SMSG_ACCOUNT_DATA_TIMES": "0x209",
"SMSG_UPDATE_OBJECT": "0x0A9",
"SMSG_COMPRESSED_UPDATE_OBJECT": "0x1F6",
"SMSG_MONSTER_MOVE_TRANSPORT": "0x2AE",
"SMSG_DESTROY_OBJECT": "0x0AA",
"CMSG_MESSAGECHAT": "0x095",
"SMSG_MESSAGECHAT": "0x096",
"CMSG_WHO": "0x062",
"SMSG_WHO": "0x063",
"CMSG_REQUEST_PLAYED_TIME": "0x1CC",
"SMSG_PLAYED_TIME": "0x1CD",
"CMSG_QUERY_TIME": "0x1CE",
"SMSG_QUERY_TIME_RESPONSE": "0x1CF",
"SMSG_FRIEND_STATUS": "0x068",
"CMSG_ADD_FRIEND": "0x069",
"CMSG_DEL_FRIEND": "0x06A",
"CMSG_ADD_IGNORE": "0x06C",
"CMSG_DEL_IGNORE": "0x06D",
"CMSG_PLAYER_LOGOUT": "0x04A",
"CMSG_LOGOUT_REQUEST": "0x04B",
"CMSG_LOGOUT_CANCEL": "0x04E",
"SMSG_LOGOUT_RESPONSE": "0x04C",
"SMSG_LOGOUT_COMPLETE": "0x04D",
"CMSG_STAND_STATE_CHANGE": "0x101",
"CMSG_SHOWING_HELM": "0x2B9",
"CMSG_SHOWING_CLOAK": "0x2BA",
"CMSG_TOGGLE_PVP": "0x253",
"CMSG_GUILD_INVITE": "0x082",
"CMSG_GUILD_ACCEPT": "0x084",
"CMSG_GUILD_DECLINE_INVITATION": "0x085",
"CMSG_GUILD_INFO": "0x087",
"CMSG_GUILD_GET_ROSTER": "0x089",
"CMSG_GUILD_PROMOTE_MEMBER": "0x08B",
"CMSG_GUILD_DEMOTE_MEMBER": "0x08C",
"CMSG_GUILD_LEAVE": "0x08D",
"CMSG_GUILD_MOTD": "0x091",
"SMSG_GUILD_INFO": "0x088",
"SMSG_GUILD_ROSTER": "0x08A",
"MSG_RAID_READY_CHECK": "0x322",
"CMSG_DUEL_PROPOSED": "0x166",
"CMSG_DUEL_ACCEPTED": "0x16C",
"CMSG_DUEL_CANCELLED": "0x16D",
"SMSG_DUEL_REQUESTED": "0x167",
"CMSG_INITIATE_TRADE": "0x116",
"MSG_RANDOM_ROLL": "0x1FB",
"CMSG_SET_SELECTION": "0x13D",
"CMSG_NAME_QUERY": "0x050",
"SMSG_NAME_QUERY_RESPONSE": "0x051",
"CMSG_CREATURE_QUERY": "0x060",
"SMSG_CREATURE_QUERY_RESPONSE": "0x061",
"CMSG_GAMEOBJECT_QUERY": "0x05E",
"SMSG_GAMEOBJECT_QUERY_RESPONSE": "0x05F",
"CMSG_SET_ACTIVE_MOVER": "0x26A",
"CMSG_BINDER_ACTIVATE": "0x1B5",
"SMSG_LOG_XPGAIN": "0x1D0",
"SMSG_MONSTER_MOVE": "0x0DD",
"CMSG_ATTACKSWING": "0x141",
"CMSG_ATTACKSTOP": "0x142",
"SMSG_ATTACKSTART": "0x143",
"SMSG_ATTACKSTOP": "0x144",
"SMSG_ATTACKERSTATEUPDATE": "0x14A",
"SMSG_SPELLNONMELEEDAMAGELOG": "0x250",
"SMSG_SPELLHEALLOG": "0x150",
"SMSG_SPELLENERGIZELOG": "0x151",
"SMSG_PERIODICAURALOG": "0x24E",
"SMSG_ENVIRONMENTALDAMAGELOG": "0x1FC",
"CMSG_CAST_SPELL": "0x12E",
"CMSG_CANCEL_CAST": "0x12F",
"CMSG_CANCEL_AURA": "0x136",
"SMSG_CAST_FAILED": "0x130",
"SMSG_SPELL_START": "0x131",
"SMSG_SPELL_GO": "0x132",
"SMSG_SPELL_FAILURE": "0x133",
"SMSG_SPELL_COOLDOWN": "0x134",
"SMSG_COOLDOWN_EVENT": "0x135",
"SMSG_UPDATE_AURA_DURATION": "0x137",
"SMSG_INITIAL_SPELLS": "0x12A",
"SMSG_LEARNED_SPELL": "0x12B",
"SMSG_SUPERCEDED_SPELL": "0x12C",
"SMSG_REMOVED_SPELL": "0x203",
"SMSG_SPELL_DELAYED": "0x1E2",
"SMSG_SET_FLAT_SPELL_MODIFIER": "0x266",
"SMSG_SET_PCT_SPELL_MODIFIER": "0x267",
"CMSG_LEARN_TALENT": "0x251",
"MSG_TALENT_WIPE_CONFIRM": "0x2AA",
"CMSG_GROUP_INVITE": "0x06E",
"SMSG_GROUP_INVITE": "0x06F",
"CMSG_GROUP_ACCEPT": "0x072",
"CMSG_GROUP_DECLINE": "0x073",
"SMSG_GROUP_DECLINE": "0x074",
"CMSG_GROUP_UNINVITE_GUID": "0x076",
"SMSG_GROUP_UNINVITE": "0x077",
"CMSG_GROUP_SET_LEADER": "0x078",
"SMSG_GROUP_SET_LEADER": "0x079",
"CMSG_GROUP_DISBAND": "0x07B",
"SMSG_GROUP_LIST": "0x07D",
"SMSG_PARTY_COMMAND_RESULT": "0x07F",
"MSG_RAID_TARGET_UPDATE": "0x321",
"CMSG_REQUEST_RAID_INFO": "0x2CD",
"SMSG_RAID_INSTANCE_INFO": "0x2CC",
"CMSG_AUTOSTORE_LOOT_ITEM": "0x108",
"CMSG_LOOT": "0x15D",
"CMSG_LOOT_MONEY": "0x15E",
"CMSG_LOOT_RELEASE": "0x15F",
"SMSG_LOOT_RESPONSE": "0x160",
"SMSG_LOOT_RELEASE_RESPONSE": "0x161",
"SMSG_LOOT_REMOVED": "0x162",
"SMSG_LOOT_MONEY_NOTIFY": "0x163",
"SMSG_LOOT_CLEAR_MONEY": "0x165",
"CMSG_ACTIVATETAXI": "0x1AD",
"CMSG_GOSSIP_HELLO": "0x17B",
"CMSG_GOSSIP_SELECT_OPTION": "0x17C",
"SMSG_GOSSIP_MESSAGE": "0x17D",
"SMSG_GOSSIP_COMPLETE": "0x17E",
"SMSG_NPC_TEXT_UPDATE": "0x180",
"CMSG_GAMEOBJECT_USE": "0x0B1",
"CMSG_QUESTGIVER_STATUS_QUERY": "0x182",
"SMSG_QUESTGIVER_STATUS": "0x183",
"CMSG_QUESTGIVER_HELLO": "0x184",
"CMSG_QUESTGIVER_QUERY_QUEST": "0x186",
"SMSG_QUESTGIVER_QUEST_DETAILS": "0x188",
"CMSG_QUESTGIVER_ACCEPT_QUEST": "0x189",
"CMSG_QUESTGIVER_COMPLETE_QUEST": "0x18A",
"SMSG_QUESTGIVER_REQUEST_ITEMS": "0x18B",
"CMSG_QUESTGIVER_REQUEST_REWARD": "0x18C",
"SMSG_QUESTGIVER_OFFER_REWARD": "0x18D",
"CMSG_QUESTGIVER_CHOOSE_REWARD": "0x18E",
"SMSG_QUESTGIVER_QUEST_INVALID": "0x18F",
"SMSG_QUESTGIVER_QUEST_COMPLETE": "0x191",
"CMSG_QUESTLOG_REMOVE_QUEST": "0x194",
"SMSG_QUESTUPDATE_ADD_KILL": "0x199",
"SMSG_QUESTUPDATE_COMPLETE": "0x198",
"CMSG_QUEST_QUERY": "0x05C",
"SMSG_QUEST_QUERY_RESPONSE": "0x05D",
"SMSG_QUESTLOG_FULL": "0x195",
"CMSG_LIST_INVENTORY": "0x19E",
"SMSG_LIST_INVENTORY": "0x19F",
"CMSG_SELL_ITEM": "0x1A0",
"SMSG_SELL_ITEM": "0x1A1",
"CMSG_BUY_ITEM": "0x1A2",
"SMSG_BUY_FAILED": "0x1A5",
"CMSG_TRAINER_LIST": "0x1B0",
"SMSG_TRAINER_LIST": "0x1B1",
"CMSG_TRAINER_BUY_SPELL": "0x1B2",
"SMSG_TRAINER_BUY_FAILED": "0x1B4",
"CMSG_ITEM_QUERY_SINGLE": "0x056",
"SMSG_ITEM_QUERY_SINGLE_RESPONSE": "0x058",
"CMSG_USE_ITEM": "0x0AB",
"CMSG_AUTOEQUIP_ITEM": "0x10A",
"CMSG_SWAP_ITEM": "0x10C",
"CMSG_SWAP_INV_ITEM": "0x10D",
"SMSG_INVENTORY_CHANGE_FAILURE": "0x112",
"CMSG_INSPECT": "0x114",
"SMSG_INSPECT_RESULTS": "0x115",
"CMSG_REPOP_REQUEST": "0x15A",
"SMSG_RESURRECT_REQUEST": "0x15B",
"CMSG_RESURRECT_RESPONSE": "0x15C",
"CMSG_SPIRIT_HEALER_ACTIVATE": "0x21C",
"SMSG_SPIRIT_HEALER_CONFIRM": "0x222",
"MSG_MOVE_TELEPORT_ACK": "0x0C7",
"SMSG_TRANSFER_PENDING": "0x03F",
"SMSG_NEW_WORLD": "0x03E",
"MSG_MOVE_WORLDPORT_ACK": "0x0DC",
"SMSG_TRANSFER_ABORTED": "0x040",
"SMSG_FORCE_RUN_SPEED_CHANGE": "0x0E2",
"CMSG_FORCE_RUN_SPEED_CHANGE_ACK": "0x0E3",
"SMSG_SHOWTAXINODES": "0x1A9",
"SMSG_ACTIVATETAXIREPLY": "0x1AE",
"SMSG_NEW_TAXI_PATH": "0x1AF",
"CMSG_ACTIVATETAXIEXPRESS": "0x312",
"CMSG_TAXINODE_STATUS_QUERY": "0x1AA",
"SMSG_TAXINODE_STATUS": "0x1AB",
"SMSG_TRAINER_BUY_SUCCEEDED": "0x1B3",
"SMSG_BINDPOINTUPDATE": "0x155",
"SMSG_SET_PROFICIENCY": "0x127",
"SMSG_ACTION_BUTTONS": "0x129",
"SMSG_LEVELUP_INFO": "0x1D4",
"CMSG_UPDATE_ACCOUNT_DATA": "0x20B",
"CMSG_BATTLEFIELD_LIST": "0x23C",
"SMSG_BATTLEFIELD_LIST": "0x23D",
"CMSG_BATTLEFIELD_JOIN": "0x23E",
"CMSG_BATTLEFIELD_STATUS": "0x2D3",
"SMSG_BATTLEFIELD_STATUS": "0x2D4",
"CMSG_BATTLEFIELD_PORT": "0x2D5",
"CMSG_BATTLEMASTER_HELLO": "0x2D7",
"MSG_PVP_LOG_DATA": "0x2E0",
"CMSG_LEAVE_BATTLEFIELD": "0x2E1",
"SMSG_GROUP_JOINED_BATTLEGROUND": "0x2E8",
"MSG_BATTLEGROUND_PLAYER_POSITIONS": "0x2E9",
"SMSG_BATTLEGROUND_PLAYER_JOINED": "0x2EC",
"SMSG_BATTLEGROUND_PLAYER_LEFT": "0x2ED",
"CMSG_BATTLEMASTER_JOIN": "0x2EE"
}

View file

@ -0,0 +1,29 @@
{
"OBJECT_FIELD_ENTRY": 3,
"UNIT_FIELD_TARGET_LO": 16,
"UNIT_FIELD_TARGET_HI": 17,
"UNIT_FIELD_HEALTH": 22,
"UNIT_FIELD_POWER1": 23,
"UNIT_FIELD_MAXHEALTH": 28,
"UNIT_FIELD_MAXPOWER1": 29,
"UNIT_FIELD_LEVEL": 34,
"UNIT_FIELD_FACTIONTEMPLATE": 35,
"UNIT_FIELD_FLAGS": 46,
"UNIT_FIELD_DISPLAYID": 131,
"UNIT_FIELD_MOUNTDISPLAYID": 133,
"UNIT_NPC_FLAGS": 147,
"UNIT_DYNAMIC_FLAGS": 143,
"UNIT_END": 188,
"PLAYER_FLAGS": 190,
"PLAYER_XP": 716,
"PLAYER_NEXT_LEVEL_XP": 717,
"PLAYER_FIELD_COINAGE": 1176,
"PLAYER_QUEST_LOG_START": 198,
"PLAYER_FIELD_INV_SLOT_HEAD": 486,
"PLAYER_FIELD_PACK_SLOT_1": 532,
"PLAYER_SKILL_INFO_START": 718,
"PLAYER_EXPLORED_ZONES_START": 1111,
"PLAYER_END": 1282,
"GAMEOBJECT_DISPLAYID": 8,
"ITEM_FIELD_STACK_COUNT": 14
}