CastleSiegeStatusResponse |
result: byte, state: byte, startYear/Month/Day/Hour/Minute, endYear/Month/Day/Hour/Minute, siegeStartYear/Month/Day/Hour/Minute, guildName: string[8], guildMasterName: string[10], remainTime: int32 |
CastleSiegeRegistrationResponse |
result: byte, guildName: string[8] |
CastleSiegeUnregisterResponse |
result: byte |
CastleSiegeRegistrationStateResponse |
guildName: string[8], marks: uint32, registrationId: int32 |
CastleSiegeMarkRegistrationResponse |
result: byte, guildName: string[8], marks: uint32 |
CastleSiegeDefenseBuyResponse |
result: byte, npcType: int32, npcId: int32 |
CastleSiegeDefenseRepairResponse |
result: byte, npcType: int32, npcId: int32 |
CastleSiegeDefenseUpgradeResponse |
result: byte, npcType: int32, npcId: int32, upgradeType: int32, upgradeValue: int32 |
CastleSiegeTaxInfoResponse |
taxChaos: byte, taxStore: byte, taxHunt: int32, huntAllowed: byte, money: int64 |
CastleSiegeTaxChangeResponse |
result: byte, taxType: byte, taxRate: int32 |
CastleSiegeTributeWithdrawResponse |
result: byte, money: int64 |
CastleSiegeJoinSideNotification |
side: byte |
CastleSiegeCrownStateUpdate |
state: byte (0=locked, 1=available) |
CastleSiegeCrownAccessState |
state: byte, accumulatedTimeMs: uint32 |
CastleSiegeSwitchInfo |
switchIndex: uint16, switchId: byte, state: byte, joinSide: byte, guildName: string[9], userName: string[11] |
CastleSiegeOwnershipChangeNotification |
guildName: string[8] |
CastleSiegeBattleStartEnd |
started: byte |
CastleSiegeRemainingTime |
hour: byte, minute: byte |
CastleSiegeGateState |
gateIndex: uint16, state: byte |
CastleSiegeGateOperateResponse |
result: byte, gateIndex: uint16 |
CastleSiegeGateOperateState |
gateIndex: uint16, state: byte |
CastleSiegeNpcList (C2) |
result: byte, count: int32, Body[]: { number, index, defenseLevel, regenLevel, maxHp, hp, x, y, live } |
CastleSiegeGuildList (C2) |
result: byte, count: int32, Body[]: { side, involved, guildName[8], score } |
CastleSiegeRegisteredGuildList (C2) |
count: int32, Body[]: { guildName[8], marks, registeredId, isOwner } |
CastleSiegeMiniMapPlayerPositions (C2) |
count: int32, Body[]: { x, y } |
CastleSiegeMiniMapNpcPositions (C2) |
count: int32, Body[]: { npcType, x, y } |
CastleSiegeMachineUseResult |
npcIndex: uint16, x: byte, y: byte |
CastleSiegeMachineRegionNotify |
x: byte, y: byte |
CastleSiegeMachineInterface |
machineType: byte |
CastleSiegeLifeStoneState |
state: byte (creation stage 0–4) |
CastleOwnerLogo |
logoData: byte[32] |
HuntingZoneGuardInfo |
huntEnabled: byte, taxRate: int32 |
GuildRelationshipChangeResponse |
result: byte, relationshipType: byte, targetGuildId: uint32 |
AllianceList (C2) |
count: byte, Body[]: { guildName[8], memberCount, guildMasterName[10] } |
Summary
Define all Castle Siege and Guild Alliance network packet structures in the XML packet definition files. These definitions are used by the source generator to produce C# packet structs for both client→server and server→client communication.
Prerequisites
None — this phase is needed incrementally by all other phases. Can be done in parallel.
Background
OpenMU defines packets in XML files:
Network/Packets/ClientToServer/ClientToServerPackets.xmlNetwork/Packets/ServerToClient/ServerToClientPackets.xmlThe source generator in
Network/Packets/MUnique.OpenMU.Network.Packets.csprojreads these XML files and produces C# structs (e.g.,CastleSiegeStatusRequest,CastleSiegeRegistrationResponse).Existing Castle Siege packet documentation in
docs/Packets/C1-B2-*provides field layouts.Requirements
1. Verify/Complete Client→Server Packets
The following packets already exist in
ClientToServerPackets.xml— verify they have complete field definitions matching the C++ reference:C1-B2-00CastleSiegeStatusRequestC1-B2-01CastleSiegeRegistrationRequestC1-B2-02CastleSiegeUnregisterRequestC1-B2-03CastleSiegeRegistrationStateRequestC1-B2-04CastleSiegeMarkRegistrationslot: byte(inventory slot)C1-B2-05CastleSiegeDefenseBuyRequestnpcType: int32,npcId: int32C1-B2-06CastleSiegeDefenseRepairRequestnpcType: int32,npcId: int32C1-B2-07CastleSiegeDefenseUpgradeRequestnpcType: int32,npcId: int32,upgradeType: int32C1-B2-08CastleSiegeTaxInfoRequestC1-B2-09CastleSiegeTaxChangeRequesttaxType: byte,taxRate: int32(big-endian)C1-B2-10CastleSiegeTaxMoneyWithdrawmoney: int32(big-endian)C1-B2-12ToggleCastleGateRequestoperation: byte,gateIndex: uint16C1-B2-1DCastleGuildCommandteam: byte,x: byte,y: byte,command: byteC1-B2-1FCastleSiegeHuntingZoneEntranceSettingenabled: byteC1-B3-01CastleSiegeGateListRequestC1-B3-02CastleSiegeStatueListRequestC1-B4CastleSiegeRegisteredGuildsListRequestC1-B5CastleOwnerListRequestC1-B9-02GuildLogoOfCastleOwnerRequestC1-B9-05CastleSiegeHuntingZoneEnterRequestC1-E6GuildRelationshipChangeRequesttargetGuildId: uint32,relationshipType: byte,requestType: byteC1-E9RequestAllianceListC1-EB-01RemoveAllianceGuildRequestguildName: stringAdd if missing:
C1-B7-??CastleSiegeMachineUseRequestnpcIndex: uint16,targetZone: byteC1-B7-??CastleSiegeMachineDamageCallback2. Define Server→Client Packets
Add full XML definitions for all S→C packets in
ServerToClientPackets.xml:CastleSiegeStatusResponseresult: byte,state: byte,startYear/Month/Day/Hour/Minute,endYear/Month/Day/Hour/Minute,siegeStartYear/Month/Day/Hour/Minute,guildName: string[8],guildMasterName: string[10],remainTime: int32CastleSiegeRegistrationResponseresult: byte,guildName: string[8]CastleSiegeUnregisterResponseresult: byteCastleSiegeRegistrationStateResponseguildName: string[8],marks: uint32,registrationId: int32CastleSiegeMarkRegistrationResponseresult: byte,guildName: string[8],marks: uint32CastleSiegeDefenseBuyResponseresult: byte,npcType: int32,npcId: int32CastleSiegeDefenseRepairResponseresult: byte,npcType: int32,npcId: int32CastleSiegeDefenseUpgradeResponseresult: byte,npcType: int32,npcId: int32,upgradeType: int32,upgradeValue: int32CastleSiegeTaxInfoResponsetaxChaos: byte,taxStore: byte,taxHunt: int32,huntAllowed: byte,money: int64CastleSiegeTaxChangeResponseresult: byte,taxType: byte,taxRate: int32CastleSiegeTributeWithdrawResponseresult: byte,money: int64CastleSiegeJoinSideNotificationside: byteCastleSiegeCrownStateUpdatestate: byte(0=locked, 1=available)CastleSiegeCrownAccessStatestate: byte,accumulatedTimeMs: uint32CastleSiegeSwitchInfoswitchIndex: uint16,switchId: byte,state: byte,joinSide: byte,guildName: string[9],userName: string[11]CastleSiegeOwnershipChangeNotificationguildName: string[8]CastleSiegeBattleStartEndstarted: byteCastleSiegeRemainingTimehour: byte,minute: byteCastleSiegeGateStategateIndex: uint16,state: byteCastleSiegeGateOperateResponseresult: byte,gateIndex: uint16CastleSiegeGateOperateStategateIndex: uint16,state: byteCastleSiegeNpcList(C2)result: byte,count: int32,Body[]: { number, index, defenseLevel, regenLevel, maxHp, hp, x, y, live }CastleSiegeGuildList(C2)result: byte,count: int32,Body[]: { side, involved, guildName[8], score }CastleSiegeRegisteredGuildList(C2)count: int32,Body[]: { guildName[8], marks, registeredId, isOwner }CastleSiegeMiniMapPlayerPositions(C2)count: int32,Body[]: { x, y }CastleSiegeMiniMapNpcPositions(C2)count: int32,Body[]: { npcType, x, y }CastleSiegeMachineUseResultnpcIndex: uint16,x: byte,y: byteCastleSiegeMachineRegionNotifyx: byte,y: byteCastleSiegeMachineInterfacemachineType: byteCastleSiegeLifeStoneStatestate: byte(creation stage 0–4)CastleOwnerLogologoData: byte[32]HuntingZoneGuardInfohuntEnabled: byte,taxRate: int32GuildRelationshipChangeResponseresult: byte,relationshipType: byte,targetGuildId: uint32AllianceList(C2)count: byte,Body[]: { guildName[8], memberCount, guildMasterName[10] }3. Packet Format Notes
C1= small packet (1-byte size),C2= large packet (2-byte size).PBMSG_HEAD2={c=0xC1, size, headcode, subcode}(4 bytes).LittleEndianin the XML.IntegerBigEndianorIntegerLittleEndianas appropriate.Files to Modify
Network/Packets/ClientToServer/ClientToServerPackets.xmlNetwork/Packets/ServerToClient/ServerToClientPackets.xmlAcceptance Criteria