From 50489a9f797eb83226c830003dbceb59866ac49c Mon Sep 17 00:00:00 2001 From: sven-n Date: Tue, 24 Sep 2024 19:51:47 +0200 Subject: [PATCH] Extended protocol to solve some limitations Now we can transmit values of Health, Shield, Mana, AG, Damage, Experience above 65k. I widened all to 32 bit. Additionally, I added a message to add more than one statpoint at a time. These changes will be added to my MuMain sources soon as well. --- .../C1-11-ObjectHitExtended_by-server.md | 38 + ...ItemConsumptionFailedExtended_by-server.md | 20 + ...aximumHealthAndShieldExtended_by-server.md | 20 + ...urrentHealthAndShieldExtended_by-server.md | 20 + ...MaximumManaAndAbilityExtended_by-server.md | 20 + ...CurrentManaAndAbilityExtended_by-server.md | 20 + ...-CharacterLevelUpdateExtended_by-server.md | 28 + ...rStatIncreaseResponseExtended_by-server.md | 36 + ...-50-MasterStatsUpdateExtended_by-server.md | 26 + ...rCharacterLevelUpdateExtended_by-server.md | 26 + ...3-16-ExperienceGainedExtended_by-server.md | 34 + ...-CharacterInformationExtended_by-server.md | 69 + docs/Packets/ServerToClient.md | 12 + src/GameLogic/Player.cs | 10 +- .../Character/IncreaseStatsAction.cs | 65 +- .../Views/Character/IAddExperiencePlugIn.cs | 38 +- .../Character/IStatIncreaseResultPlugIn.cs | 4 +- .../Character/AddExperienceExtendedPlugIn.cs | 51 + .../Character/AddExperiencePlugIn.cs | 2 +- .../StatIncreaseResultExtendedPlugIn.cs | 44 + .../Character/StatIncreaseResultPlugIn.cs | 47 +- .../UpdateCharacterStatsExtendedPlugIn.cs | 71 + .../UpdateCurrentHealthExtendedPlugIn.cs | 38 + .../UpdateCurrentManaExtendedPlugIn.cs | 38 + .../Character/UpdateLevelExtendedPlugIn.cs | 78 + .../UpdateMasterStatsExtendedPlugIn.cs | 49 + .../UpdateMaximumHealthExtendedPlugIn.cs | 39 + .../UpdateMaximumManaExtendedPlugIn.cs | 39 + ...stedItemConsumptionFailedExtendedPlugIn.cs | 44 + .../RemoteView/World/ShowHitExtendedPlugIn.cs | 88 + .../RemoteView/World/ShowHitPlugIn.cs | 14 +- .../ServerToClient/ConnectionExtensions.cs | 474 +- .../ServerToClient/ServerToClientPackets.cs | 6667 ++++++++++------- .../ServerToClient/ServerToClientPackets.xml | 853 ++- .../ServerToClientPacketsRef.cs | 5508 +++++++++----- ...rceClientNetworkEncryptionFactoryPlugIn.cs | 45 + 36 files changed, 10009 insertions(+), 4666 deletions(-) create mode 100644 docs/Packets/C1-11-ObjectHitExtended_by-server.md create mode 100644 docs/Packets/C1-26-FD-ItemConsumptionFailedExtended_by-server.md create mode 100644 docs/Packets/C1-26-FE-MaximumHealthAndShieldExtended_by-server.md create mode 100644 docs/Packets/C1-26-FF-CurrentHealthAndShieldExtended_by-server.md create mode 100644 docs/Packets/C1-27-FE-MaximumManaAndAbilityExtended_by-server.md create mode 100644 docs/Packets/C1-27-FF-CurrentManaAndAbilityExtended_by-server.md create mode 100644 docs/Packets/C1-F3-05-CharacterLevelUpdateExtended_by-server.md create mode 100644 docs/Packets/C1-F3-06-CharacterStatIncreaseResponseExtended_by-server.md create mode 100644 docs/Packets/C1-F3-50-MasterStatsUpdateExtended_by-server.md create mode 100644 docs/Packets/C1-F3-51-MasterCharacterLevelUpdateExtended_by-server.md create mode 100644 docs/Packets/C3-16-ExperienceGainedExtended_by-server.md create mode 100644 docs/Packets/C3-F3-03-CharacterInformationExtended_by-server.md create mode 100644 src/GameServer/RemoteView/Character/AddExperienceExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/StatIncreaseResultExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/UpdateCharacterStatsExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/UpdateCurrentHealthExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/UpdateCurrentManaExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/UpdateLevelExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/UpdateMasterStatsExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/UpdateMaximumHealthExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Character/UpdateMaximumManaExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/Inventory/RequestedItemConsumptionFailedExtendedPlugIn.cs create mode 100644 src/GameServer/RemoteView/World/ShowHitExtendedPlugIn.cs create mode 100644 src/Network/PlugIns/OpenSourceClientNetworkEncryptionFactoryPlugIn.cs diff --git a/docs/Packets/C1-11-ObjectHitExtended_by-server.md b/docs/Packets/C1-11-ObjectHitExtended_by-server.md new file mode 100644 index 000000000..95e1c76d3 --- /dev/null +++ b/docs/Packets/C1-11-ObjectHitExtended_by-server.md @@ -0,0 +1,38 @@ +# C1 11 - ObjectHitExtended (by server) + +## Is sent when + +An object got hit in two cases: 1. When the own player is hit; 2. When the own player attacked some other object which got hit. + +## Causes the following actions on the client side + +The damage is shown at the object which received the hit. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 16 | Packet header - length of the packet | +| 2 | 1 | Byte | 0x11 | Packet header - packet type identifier | +| 3 << 0 | 4 bit | DamageKind | | Kind | +| 3 << 6 | 1 bit | Boolean | | IsDoubleDamage | +| 3 << 7 | 1 bit | Boolean | | IsTripleDamage | +| 4 | 2 | ShortLittleEndian | | ObjectId | +| 8 | 4 | IntegerLittleEndian | | HealthDamage | +| 12 | 4 | IntegerLittleEndian | | ShieldDamage | + +### DamageKind Enum + +Defines the kind of the damage. + +| Value | Name | Description | +|-------|------|-------------| +| 0 | NormalRed | Red color, used by normal damage. | +| 1 | IgnoreDefenseCyan | Cyan color, usually used by ignore defense damage. | +| 2 | ExcellentLightGreen | Light green color, usually used by excellent damage. | +| 3 | CriticalBlue | Blue color, usually used by critical damage. | +| 4 | LightPink | Light pink color. | +| 5 | PoisonDarkGreen | Dark green color, usually used by poison damage. | +| 6 | ReflectedDarkPink | Dark pink color, usually used by reflected damage. | +| 7 | White | White color. | \ No newline at end of file diff --git a/docs/Packets/C1-26-FD-ItemConsumptionFailedExtended_by-server.md b/docs/Packets/C1-26-FD-ItemConsumptionFailedExtended_by-server.md new file mode 100644 index 000000000..8047040ee --- /dev/null +++ b/docs/Packets/C1-26-FD-ItemConsumptionFailedExtended_by-server.md @@ -0,0 +1,20 @@ +# C1 26 FD - ItemConsumptionFailedExtended (by server) + +## Is sent when + +When the consumption of an item failed. + +## Causes the following actions on the client side + +The game client gets a feedback about a failed consumption, and allows for do further consumption requests. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 12 | Packet header - length of the packet | +| 2 | 1 | Byte | 0x26 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0xFD | Packet header - sub packet type identifier | +| 4 | 4 | IntegerLittleEndian | | Health | +| 8 | 4 | IntegerLittleEndian | | Shield | \ No newline at end of file diff --git a/docs/Packets/C1-26-FE-MaximumHealthAndShieldExtended_by-server.md b/docs/Packets/C1-26-FE-MaximumHealthAndShieldExtended_by-server.md new file mode 100644 index 000000000..9ea3b588d --- /dev/null +++ b/docs/Packets/C1-26-FE-MaximumHealthAndShieldExtended_by-server.md @@ -0,0 +1,20 @@ +# C1 26 FE - MaximumHealthAndShieldExtended (by server) + +## Is sent when + +When the maximum health changed, e.g. by adding stat points or changed items. + +## Causes the following actions on the client side + +The health and shield bar is updated on the game client user interface. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 12 | Packet header - length of the packet | +| 2 | 1 | Byte | 0x26 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0xFE | Packet header - sub packet type identifier | +| 4 | 4 | IntegerLittleEndian | | Health | +| 8 | 4 | IntegerLittleEndian | | Shield | \ No newline at end of file diff --git a/docs/Packets/C1-26-FF-CurrentHealthAndShieldExtended_by-server.md b/docs/Packets/C1-26-FF-CurrentHealthAndShieldExtended_by-server.md new file mode 100644 index 000000000..72edaaf40 --- /dev/null +++ b/docs/Packets/C1-26-FF-CurrentHealthAndShieldExtended_by-server.md @@ -0,0 +1,20 @@ +# C1 26 FF - CurrentHealthAndShieldExtended (by server) + +## Is sent when + +Periodically, or if the current health or shield changed on the server side, e.g. by hits. + +## Causes the following actions on the client side + +The health and shield bar is updated on the game client user interface. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 12 | Packet header - length of the packet | +| 2 | 1 | Byte | 0x26 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0xFF | Packet header - sub packet type identifier | +| 4 | 4 | IntegerLittleEndian | | Health | +| 8 | 4 | IntegerLittleEndian | | Shield | \ No newline at end of file diff --git a/docs/Packets/C1-27-FE-MaximumManaAndAbilityExtended_by-server.md b/docs/Packets/C1-27-FE-MaximumManaAndAbilityExtended_by-server.md new file mode 100644 index 000000000..360ea9520 --- /dev/null +++ b/docs/Packets/C1-27-FE-MaximumManaAndAbilityExtended_by-server.md @@ -0,0 +1,20 @@ +# C1 27 FE - MaximumManaAndAbilityExtended (by server) + +## Is sent when + +The maximum available mana or ability has changed, e.g. by adding stat points. + +## Causes the following actions on the client side + +The mana and ability bar is updated on the game client user interface. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 12 | Packet header - length of the packet | +| 2 | 1 | Byte | 0x27 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0xFE | Packet header - sub packet type identifier | +| 4 | 4 | IntegerLittleEndian | | Mana | +| 8 | 4 | IntegerLittleEndian | | Ability | \ No newline at end of file diff --git a/docs/Packets/C1-27-FF-CurrentManaAndAbilityExtended_by-server.md b/docs/Packets/C1-27-FF-CurrentManaAndAbilityExtended_by-server.md new file mode 100644 index 000000000..cafa844ab --- /dev/null +++ b/docs/Packets/C1-27-FF-CurrentManaAndAbilityExtended_by-server.md @@ -0,0 +1,20 @@ +# C1 27 FF - CurrentManaAndAbilityExtended (by server) + +## Is sent when + +The currently available mana or ability has changed, e.g. by using a skill. + +## Causes the following actions on the client side + +The mana and ability bar is updated on the game client user interface. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 12 | Packet header - length of the packet | +| 2 | 1 | Byte | 0x27 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0xFF | Packet header - sub packet type identifier | +| 4 | 4 | IntegerLittleEndian | | Mana | +| 8 | 4 | IntegerLittleEndian | | Ability | \ No newline at end of file diff --git a/docs/Packets/C1-F3-05-CharacterLevelUpdateExtended_by-server.md b/docs/Packets/C1-F3-05-CharacterLevelUpdateExtended_by-server.md new file mode 100644 index 000000000..26b395fff --- /dev/null +++ b/docs/Packets/C1-F3-05-CharacterLevelUpdateExtended_by-server.md @@ -0,0 +1,28 @@ +# C1 F3 05 - CharacterLevelUpdateExtended (by server) + +## Is sent when + +After a character leveled up. + +## Causes the following actions on the client side + +Updates the level (and other related stats) in the game client and shows an effect. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 32 | Packet header - length of the packet | +| 2 | 1 | Byte | 0xF3 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0x05 | Packet header - sub packet type identifier | +| 4 | 2 | ShortLittleEndian | | Level | +| 6 | 2 | ShortLittleEndian | | LevelUpPoints | +| 8 | 4 | IntegerLittleEndian | | MaximumHealth | +| 12 | 4 | IntegerLittleEndian | | MaximumMana | +| 16 | 4 | IntegerLittleEndian | | MaximumShield | +| 20 | 4 | IntegerLittleEndian | | MaximumAbility | +| 24 | 2 | ShortLittleEndian | | FruitPoints | +| 26 | 2 | ShortLittleEndian | | MaximumFruitPoints | +| 28 | 2 | ShortLittleEndian | | NegativeFruitPoints | +| 30 | 2 | ShortLittleEndian | | MaximumNegativeFruitPoints | \ No newline at end of file diff --git a/docs/Packets/C1-F3-06-CharacterStatIncreaseResponseExtended_by-server.md b/docs/Packets/C1-F3-06-CharacterStatIncreaseResponseExtended_by-server.md new file mode 100644 index 000000000..3fd82a301 --- /dev/null +++ b/docs/Packets/C1-F3-06-CharacterStatIncreaseResponseExtended_by-server.md @@ -0,0 +1,36 @@ +# C1 F3 06 - CharacterStatIncreaseResponseExtended (by server) + +## Is sent when + +After the server processed a character stat increase request packet. + +## Causes the following actions on the client side + +If it was successful, adds a point to the requested stat type. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 24 | Packet header - length of the packet | +| 2 | 1 | Byte | 0xF3 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0x06 | Packet header - sub packet type identifier | +| 4 | 1 | CharacterStatAttribute | | Attribute | +| 6 | 2 | ShortLittleEndian | | AddedAmount | +| 8 | 4 | IntegerLittleEndian | | UpdatedMaximumHealth | +| 12 | 4 | IntegerLittleEndian | | UpdatedMaximumMana | +| 16 | 4 | IntegerLittleEndian | | UpdatedMaximumShield | +| 20 | 4 | IntegerLittleEndian | | UpdatedMaximumAbility | + +### CharacterStatAttribute Enum + +Defines the type of a character stat attribute. + +| Value | Name | Description | +|-------|------|-------------| +| 0 | Strength | The strength attribute. | +| 1 | Agility | The agility attribute. | +| 2 | Vitality | The vitality attribute. | +| 3 | Energy | The energy attribute. | +| 4 | Leadership | The leadership attribute. | \ No newline at end of file diff --git a/docs/Packets/C1-F3-50-MasterStatsUpdateExtended_by-server.md b/docs/Packets/C1-F3-50-MasterStatsUpdateExtended_by-server.md new file mode 100644 index 000000000..5c55a29fb --- /dev/null +++ b/docs/Packets/C1-F3-50-MasterStatsUpdateExtended_by-server.md @@ -0,0 +1,26 @@ +# C1 F3 50 - MasterStatsUpdateExtended (by server) + +## Is sent when + +After entering the game with a master class character. + +## Causes the following actions on the client side + +The master related data is available. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 40 | Packet header - length of the packet | +| 2 | 1 | Byte | 0xF3 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0x50 | Packet header - sub packet type identifier | +| 4 | 2 | ShortLittleEndian | | MasterLevel | +| 6 | 8 | LongBigEndian | | MasterExperience | +| 14 | 8 | LongBigEndian | | MasterExperienceOfNextLevel | +| 22 | 2 | ShortLittleEndian | | MasterLevelUpPoints | +| 24 | 4 | IntegerLittleEndian | | MaximumHealth | +| 28 | 4 | IntegerLittleEndian | | MaximumMana | +| 32 | 4 | IntegerLittleEndian | | MaximumShield | +| 36 | 4 | IntegerLittleEndian | | MaximumAbility | \ No newline at end of file diff --git a/docs/Packets/C1-F3-51-MasterCharacterLevelUpdateExtended_by-server.md b/docs/Packets/C1-F3-51-MasterCharacterLevelUpdateExtended_by-server.md new file mode 100644 index 000000000..78335deda --- /dev/null +++ b/docs/Packets/C1-F3-51-MasterCharacterLevelUpdateExtended_by-server.md @@ -0,0 +1,26 @@ +# C1 F3 51 - MasterCharacterLevelUpdateExtended (by server) + +## Is sent when + +After a master character leveled up. + +## Causes the following actions on the client side + +Updates the master level (and other related stats) in the game client and shows an effect. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 28 | Packet header - length of the packet | +| 2 | 1 | Byte | 0xF3 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0x51 | Packet header - sub packet type identifier | +| 4 | 2 | ShortLittleEndian | | MasterLevel | +| 6 | 2 | ShortLittleEndian | | GainedMasterPoints | +| 8 | 2 | ShortLittleEndian | | CurrentMasterPoints | +| 10 | 2 | ShortLittleEndian | | MaximumMasterPoints | +| 12 | 4 | IntegerLittleEndian | | MaximumHealth | +| 16 | 4 | IntegerLittleEndian | | MaximumMana | +| 20 | 4 | IntegerLittleEndian | | MaximumShield | +| 24 | 4 | IntegerLittleEndian | | MaximumAbility | \ No newline at end of file diff --git a/docs/Packets/C3-16-ExperienceGainedExtended_by-server.md b/docs/Packets/C3-16-ExperienceGainedExtended_by-server.md new file mode 100644 index 000000000..987195c99 --- /dev/null +++ b/docs/Packets/C3-16-ExperienceGainedExtended_by-server.md @@ -0,0 +1,34 @@ +# C3 16 - ExperienceGainedExtended (by server) + +## Is sent when + +A player gained experience. + +## Causes the following actions on the client side + +The experience is added to the experience counter and bar. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC3 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 16 | Packet header - length of the packet | +| 2 | 1 | Byte | 0x16 | Packet header - packet type identifier | +| 3 | 1 | AddResult | | Type | +| 4 | 4 | IntegerLittleEndian | | AddedExperience | +| 8 | 4 | IntegerLittleEndian | | DamageOfLastHit | +| 12 | 2 | ShortLittleEndian | | KilledObjectId | +| 14 | 2 | ShortLittleEndian | | KillerObjectId | + +### AddResult Enum + +Defines the result and type of experience which is added. + +| Value | Name | Description | +|-------|------|-------------| +| 1 | Normal | The normal experience is added. | +| 2 | Master | The master experience is added. | +| 0x10 | MaxLevelReached | The maximum level has been reached, no experience is added. | +| 0x20 | MaxMasterLevelReached | The maximum master level has been reached, no master experience is added. | +| 0x21 | MonsterLevelTooLowForMasterExperience | The monster level is too low for master experience, no master experience is added. | \ No newline at end of file diff --git a/docs/Packets/C3-F3-03-CharacterInformationExtended_by-server.md b/docs/Packets/C3-F3-03-CharacterInformationExtended_by-server.md new file mode 100644 index 000000000..7ae8a07a4 --- /dev/null +++ b/docs/Packets/C3-F3-03-CharacterInformationExtended_by-server.md @@ -0,0 +1,69 @@ +# C3 F3 03 - CharacterInformationExtended (by server) + +## Is sent when + +After the character was selected by the player and entered the game. + +## Causes the following actions on the client side + +The characters enters the game world. + +## Structure + +| Index | Length | Data Type | Value | Description | +|-------|--------|-----------|-------|-------------| +| 0 | 1 | Byte | 0xC3 | [Packet type](PacketTypes.md) | +| 1 | 1 | Byte | 84 | Packet header - length of the packet | +| 2 | 1 | Byte | 0xF3 | Packet header - packet type identifier | +| 3 | 1 | Byte | 0x03 | Packet header - sub packet type identifier | +| 4 | 1 | Byte | | X | +| 5 | 1 | Byte | | Y | +| 6 | 2 | ShortLittleEndian | | MapId | +| 8 | 8 | LongBigEndian | | CurrentExperience | +| 16 | 8 | LongBigEndian | | ExperienceForNextLevel | +| 24 | 2 | ShortLittleEndian | | LevelUpPoints | +| 26 | 2 | ShortLittleEndian | | Strength | +| 28 | 2 | ShortLittleEndian | | Agility | +| 30 | 2 | ShortLittleEndian | | Vitality | +| 32 | 2 | ShortLittleEndian | | Energy | +| 34 | 2 | ShortLittleEndian | | Leadership | +| 36 | 4 | IntegerLittleEndian | | CurrentHealth | +| 40 | 4 | IntegerLittleEndian | | MaximumHealth | +| 44 | 4 | IntegerLittleEndian | | CurrentMana | +| 48 | 4 | IntegerLittleEndian | | MaximumMana | +| 52 | 4 | IntegerLittleEndian | | CurrentShield | +| 56 | 4 | IntegerLittleEndian | | MaximumShield | +| 60 | 4 | IntegerLittleEndian | | CurrentAbility | +| 64 | 4 | IntegerLittleEndian | | MaximumAbility | +| 68 | 4 | IntegerLittleEndian | | Money | +| 72 | 1 | CharacterHeroState | | HeroState | +| 73 | 1 | CharacterStatus | | Status | +| 74 | 2 | ShortLittleEndian | | UsedFruitPoints | +| 76 | 2 | ShortLittleEndian | | MaxFruitPoints | +| 78 | 2 | ShortLittleEndian | | UsedNegativeFruitPoints | +| 80 | 2 | ShortLittleEndian | | MaxNegativeFruitPoints | +| 81 | 1 | Byte | | InventoryExtensions | + +### CharacterHeroState Enum + +Defines the hero state of a character. + +| Value | Name | Description | +|-------|------|-------------| +| 0 | New | The character is new and has the highest state. | +| 1 | Hero | The character is a hero. | +| 2 | LightHero | The character is a hero, but the state is almost gone. | +| 3 | Normal | The character is in a neutral state. | +| 4 | PlayerKillWarning | The character killed another character, and has a kill warning. | +| 5 | PlayerKiller1stStage | The character killed two characters, and has some restrictions. | +| 6 | PlayerKiller2ndStage | The character killed more than two characters, and has hard restrictions. | + +### CharacterStatus Enum + +The status of a character. + +| Value | Name | Description | +|-------|------|-------------| +| 0 | Normal | The state of the character is normal. | +| 1 | Banned | The character is banned from the game. | +| 32 | GameMaster | The character is a game master. | \ No newline at end of file diff --git a/docs/Packets/ServerToClient.md b/docs/Packets/ServerToClient.md index 174a704f0..d072431cb 100644 --- a/docs/Packets/ServerToClient.md +++ b/docs/Packets/ServerToClient.md @@ -8,6 +8,7 @@ * [C1 0F - WeatherStatusUpdate (by server)](C1-0F-WeatherStatusUpdate_by-server.md) * [C1 10 - ObjectWalked075 (by server)](C1-10-ObjectWalked075_by-server.md) * [C1 11 - ObjectHit (by server)](C1-11-ObjectHit_by-server.md) + * [C1 11 - ObjectHitExtended (by server)](C1-11-ObjectHitExtended_by-server.md) * [C2 12 - AddCharactersToScope (by server)](C2-12-AddCharactersToScope_by-server.md) * [C2 12 - AddCharactersToScope075 (by server)](C2-12-AddCharactersToScope075_by-server.md) * [C2 12 - AddCharactersToScope095 (by server)](C2-12-AddCharactersToScope095_by-server.md) @@ -17,6 +18,7 @@ * [C1 14 - MapObjectOutOfScope (by server)](C1-14-MapObjectOutOfScope_by-server.md) * [C1 15 - ObjectMoved (by server)](C1-15-ObjectMoved_by-server.md) * [C3 16 - ExperienceGained (by server)](C3-16-ExperienceGained_by-server.md) + * [C3 16 - ExperienceGainedExtended (by server)](C3-16-ExperienceGainedExtended_by-server.md) * [C1 17 - ObjectGotKilled (by server)](C1-17-ObjectGotKilled_by-server.md) * [C1 18 - ObjectAnimation (by server)](C1-18-ObjectAnimation_by-server.md) * [C3 19 - SkillAnimation (by server)](C3-19-SkillAnimation_by-server.md) @@ -44,10 +46,15 @@ * [C3 24 FF - ItemMoveRequestFailed (by server)](C3-24-FF-ItemMoveRequestFailed_by-server.md) * [C1 25 - AppearanceChanged (by server)](C1-25-AppearanceChanged_by-server.md) * [C1 26 FD - ItemConsumptionFailed (by server)](C1-26-FD-ItemConsumptionFailed_by-server.md) + * [C1 26 FD - ItemConsumptionFailedExtended (by server)](C1-26-FD-ItemConsumptionFailedExtended_by-server.md) * [C1 26 FE - MaximumHealthAndShield (by server)](C1-26-FE-MaximumHealthAndShield_by-server.md) + * [C1 26 FE - MaximumHealthAndShieldExtended (by server)](C1-26-FE-MaximumHealthAndShieldExtended_by-server.md) * [C1 26 FF - CurrentHealthAndShield (by server)](C1-26-FF-CurrentHealthAndShield_by-server.md) + * [C1 26 FF - CurrentHealthAndShieldExtended (by server)](C1-26-FF-CurrentHealthAndShieldExtended_by-server.md) * [C1 27 FE - MaximumManaAndAbility (by server)](C1-27-FE-MaximumManaAndAbility_by-server.md) + * [C1 27 FE - MaximumManaAndAbilityExtended (by server)](C1-27-FE-MaximumManaAndAbilityExtended_by-server.md) * [C1 27 FF - CurrentManaAndAbility (by server)](C1-27-FF-CurrentManaAndAbility_by-server.md) + * [C1 27 FF - CurrentManaAndAbilityExtended (by server)](C1-27-FF-CurrentManaAndAbilityExtended_by-server.md) * [C1 28 - ItemRemoved (by server)](C1-28-ItemRemoved_by-server.md) * [C3 29 - ConsumeItemWithEffect (by server)](C3-29-ConsumeItemWithEffect_by-server.md) * [C1 2A - ItemDurabilityChanged (by server)](C1-2A-ItemDurabilityChanged_by-server.md) @@ -172,12 +179,15 @@ * [C1 F3 01 - CharacterCreationFailed (by server)](C1-F3-01-CharacterCreationFailed_by-server.md) * [C1 F3 02 - CharacterDeleteResponse (by server)](C1-F3-02-CharacterDeleteResponse_by-server.md) * [C3 F3 03 - CharacterInformation (by server)](C3-F3-03-CharacterInformation_by-server.md) + * [C3 F3 03 - CharacterInformationExtended (by server)](C3-F3-03-CharacterInformationExtended_by-server.md) * [C3 F3 03 - CharacterInformation075 (by server)](C3-F3-03-CharacterInformation075_by-server.md) * [C3 F3 03 - CharacterInformation097 (by server)](C3-F3-03-CharacterInformation097_by-server.md) * [C1 F3 04 - RespawnAfterDeath075 (by server)](C1-F3-04-RespawnAfterDeath075_by-server.md) * [C1 F3 04 - RespawnAfterDeath095 (by server)](C1-F3-04-RespawnAfterDeath095_by-server.md) * [C1 F3 05 - CharacterLevelUpdate (by server)](C1-F3-05-CharacterLevelUpdate_by-server.md) + * [C1 F3 05 - CharacterLevelUpdateExtended (by server)](C1-F3-05-CharacterLevelUpdateExtended_by-server.md) * [C1 F3 06 - CharacterStatIncreaseResponse (by server)](C1-F3-06-CharacterStatIncreaseResponse_by-server.md) + * [C1 F3 06 - CharacterStatIncreaseResponseExtended (by server)](C1-F3-06-CharacterStatIncreaseResponseExtended_by-server.md) * [C1 F3 07 - PoisonDamage (by server)](C1-F3-07-PoisonDamage_by-server.md) * [C1 F3 08 - HeroStateChanged (by server)](C1-F3-08-HeroStateChanged_by-server.md) * [C4 F3 10 - CharacterInventory (by server)](C4-F3-10-CharacterInventory_by-server.md) @@ -201,7 +211,9 @@ * [C1 F3 40 - PlayFanfareSound (by server)](C1-F3-40-PlayFanfareSound_by-server.md) * [C1 F3 40 - ShowSwirl (by server)](C1-F3-40-ShowSwirl_by-server.md) * [C1 F3 50 - MasterStatsUpdate (by server)](C1-F3-50-MasterStatsUpdate_by-server.md) + * [C1 F3 50 - MasterStatsUpdateExtended (by server)](C1-F3-50-MasterStatsUpdateExtended_by-server.md) * [C1 F3 51 - MasterCharacterLevelUpdate (by server)](C1-F3-51-MasterCharacterLevelUpdate_by-server.md) + * [C1 F3 51 - MasterCharacterLevelUpdateExtended (by server)](C1-F3-51-MasterCharacterLevelUpdateExtended_by-server.md) * [C1 F3 52 - MasterSkillLevelUpdate (by server)](C1-F3-52-MasterSkillLevelUpdate_by-server.md) * [C2 F3 53 - MasterSkillList (by server)](C2-F3-53-MasterSkillList_by-server.md) * [C1 F6 03 - QuestEventResponse (by server)](C1-F6-03-QuestEventResponse_by-server.md) diff --git a/src/GameLogic/Player.cs b/src/GameLogic/Player.cs index 8f9dadb02..2aa63fe20 100644 --- a/src/GameLogic/Player.cs +++ b/src/GameLogic/Player.cs @@ -1045,13 +1045,13 @@ public async ValueTask AddMasterExperienceAsync(int experience, IAttackable? kil { if (this.Attributes![Stats.MasterLevel] >= this.GameContext.Configuration.MaximumMasterLevel) { - await this.InvokeViewPlugInAsync(p => p.ShowMessageAsync("You already reached maximum master Level.", MessageType.BlueNormal)).ConfigureAwait(false); + await this.InvokeViewPlugInAsync(p => p.AddExperienceAsync(0, killedObject, ExperienceType.MaxMasterLevelReached)).ConfigureAwait(false); return; } if (killedObject is not null && killedObject.Attributes[Stats.Level] < this.GameContext.Configuration.MinimumMonsterLevelForMasterExperience) { - await this.InvokeViewPlugInAsync(p => p.ShowMessageAsync("You need to kill stronger monsters to gain master experience.", MessageType.BlueNormal)).ConfigureAwait(false); + await this.InvokeViewPlugInAsync(p => p.AddExperienceAsync(0, killedObject, ExperienceType.MonsterLevelTooLowForMasterExperience)).ConfigureAwait(false); return; } @@ -1069,7 +1069,7 @@ public async ValueTask AddMasterExperienceAsync(int experience, IAttackable? kil this.SelectedCharacter.MasterExperience += exp; // Tell it to the Player - await this.InvokeViewPlugInAsync(p => p.AddExperienceAsync((int)exp, killedObject)).ConfigureAwait(false); + await this.InvokeViewPlugInAsync(p => p.AddExperienceAsync((int)exp, killedObject, ExperienceType.Master)).ConfigureAwait(false); // Check the lvl up if (lvlup) @@ -1092,7 +1092,7 @@ public async ValueTask AddExperienceAsync(int experience, IAttackable? killedObj { if (this.Attributes![Stats.Level] >= this.GameContext.Configuration.MaximumLevel) { - await this.InvokeViewPlugInAsync(p => p.ShowMessageAsync("You already reached maximum Level.", MessageType.BlueNormal)).ConfigureAwait(false); + await this.InvokeViewPlugInAsync(p => p.AddExperienceAsync(0, killedObject, ExperienceType.MaxLevelReached)).ConfigureAwait(false); return; } @@ -1109,7 +1109,7 @@ public async ValueTask AddExperienceAsync(int experience, IAttackable? killedObj this.SelectedCharacter.Experience += exp; // Tell it to the Player - await this.InvokeViewPlugInAsync(p => p.AddExperienceAsync((int)exp, killedObject)).ConfigureAwait(false); + await this.InvokeViewPlugInAsync(p => p.AddExperienceAsync((int)exp, killedObject, ExperienceType.Normal)).ConfigureAwait(false); // Check the lvl up if (isLevelUp) diff --git a/src/GameLogic/PlayerActions/Character/IncreaseStatsAction.cs b/src/GameLogic/PlayerActions/Character/IncreaseStatsAction.cs index 58a98da73..cedfcf2dd 100644 --- a/src/GameLogic/PlayerActions/Character/IncreaseStatsAction.cs +++ b/src/GameLogic/PlayerActions/Character/IncreaseStatsAction.cs @@ -7,8 +7,6 @@ namespace MUnique.OpenMU.GameLogic.PlayerActions.Character; using MUnique.OpenMU.AttributeSystem; using MUnique.OpenMU.GameLogic.Views; using MUnique.OpenMU.GameLogic.Views.Character; -using MUnique.OpenMU.GameLogic.Views.Inventory; -using MUnique.OpenMU.GameLogic.Views.World; using MUnique.OpenMU.Interfaces; /// @@ -24,7 +22,7 @@ public class IncreaseStatsAction /// The amount of points. public async ValueTask IncreaseStatsAsync(Player player, AttributeDefinition targetAttribute, ushort amount = 1) { - if (player.SelectedCharacter is null) + if (player.SelectedCharacter is not { } selectedCharacter) { throw new InvalidOperationException("No character selected"); } @@ -34,18 +32,6 @@ public async ValueTask IncreaseStatsAsync(Player player, AttributeDefinition tar throw new ArgumentOutOfRangeException(nameof(amount), "The amount must be greater than 0."); } - if (amount == 1) - { - await this.IncreaseStatsBySinglePointAsync(player, player.SelectedCharacter, targetAttribute).ConfigureAwait(false); - } - else - { - await this.IncreaseStatsByMultiplePointsAsync(player, amount, player.SelectedCharacter, targetAttribute).ConfigureAwait(false); - } - } - - private async ValueTask IncreaseStatsByMultiplePointsAsync(Player player, ushort amount, DataModel.Entities.Character selectedCharacter, AttributeDefinition targetAttribute) - { if (!selectedCharacter.CanIncreaseStats(amount)) { await player.InvokeViewPlugInAsync(p => p.ShowMessageAsync("Not enough level up points available.", MessageType.BlueNormal)).ConfigureAwait(false); @@ -58,54 +44,11 @@ private async ValueTask IncreaseStatsByMultiplePointsAsync(Player player, ushort player.Attributes![attributeDef.Attribute] += amount; selectedCharacter.LevelUpPoints -= Math.Min(selectedCharacter.LevelUpPoints, amount); - var map = player.CurrentMap!; - - await player.InvokeViewPlugInAsync(p => p.ObjectsOutOfScopeAsync(player.GetAsEnumerable())).ConfigureAwait(false); - await player.InvokeViewPlugInAsync(p => p.UpdateCharacterStatsAsync()).ConfigureAwait(false); - await player.InvokeViewPlugInAsync(p => p.UpdateInventoryListAsync()).ConfigureAwait(false); - var currentGate = new Persistence.BasicModel.ExitGate - { - Map = map.Definition, - X1 = player.Position.X, - X2 = player.Position.X, - Y1 = player.Position.Y, - Y2 = player.Position.Y, - }; - - await player.WarpToAsync(currentGate).ConfigureAwait(false); - - return; + await player.InvokeViewPlugInAsync(p => p.StatIncreaseResultAsync(targetAttribute, amount)); } - - await player.InvokeViewPlugInAsync(p => p.ShowMessageAsync("Attribute not available.", MessageType.BlueNormal)).ConfigureAwait(false); - } - - private async ValueTask IncreaseStatsBySinglePointAsync(Player player, DataModel.Entities.Character selectedCharacter, AttributeDefinition targetAttribute) - { - if (!selectedCharacter.CanIncreaseStats()) - { - await this.PublishIncreaseResultAsync(player, targetAttribute, false).ConfigureAwait(false); - return; - } - - var attributeDef = selectedCharacter.CharacterClass?.GetStatAttribute(targetAttribute); - if (attributeDef is { IncreasableByPlayer: true }) + else { - player.Attributes![attributeDef.Attribute]++; - if (selectedCharacter.LevelUpPoints > 0) - { - selectedCharacter.LevelUpPoints--; - } - - await this.PublishIncreaseResultAsync(player, targetAttribute, true).ConfigureAwait(false); - return; + await player.InvokeViewPlugInAsync(p => p.ShowMessageAsync("Attribute not available.", MessageType.BlueNormal)).ConfigureAwait(false); } - - await this.PublishIncreaseResultAsync(player, targetAttribute, false).ConfigureAwait(false); - } - - private ValueTask PublishIncreaseResultAsync(Player player, AttributeDefinition statAttributeDefinition, bool success) - { - return player.InvokeViewPlugInAsync(p => p.StatIncreaseResultAsync(statAttributeDefinition, success)); } } \ No newline at end of file diff --git a/src/GameLogic/Views/Character/IAddExperiencePlugIn.cs b/src/GameLogic/Views/Character/IAddExperiencePlugIn.cs index c405704f2..c790207ed 100644 --- a/src/GameLogic/Views/Character/IAddExperiencePlugIn.cs +++ b/src/GameLogic/Views/Character/IAddExperiencePlugIn.cs @@ -14,5 +14,41 @@ public interface IAddExperiencePlugIn : IViewPlugIn /// /// The experience gain. /// The killed object. - ValueTask AddExperienceAsync(int gainedExperience, IAttackable? killedObject); + ValueTask AddExperienceAsync(int gainedExperience, IAttackable? killedObject, ExperienceType experienceType); +} + +/// +/// Defines the type of experience which is added. +/// +public enum ExperienceType : byte +{ + /// + /// The type is not defined. + /// + Undefined, + + /// + /// The normal experience is added. + /// + Normal, + + /// + /// The master experience is added. + /// + Master, + + /// + /// The maximum level has been reached, no experience is added. + /// + MaxLevelReached, + + /// + /// The maximum master level has been reached, no master experience is added. + /// + MaxMasterLevelReached, + + /// + /// The monster level is too low for master experience, no master experience is added. + /// + MonsterLevelTooLowForMasterExperience, } \ No newline at end of file diff --git a/src/GameLogic/Views/Character/IStatIncreaseResultPlugIn.cs b/src/GameLogic/Views/Character/IStatIncreaseResultPlugIn.cs index f1fb6c94e..1294643c3 100644 --- a/src/GameLogic/Views/Character/IStatIncreaseResultPlugIn.cs +++ b/src/GameLogic/Views/Character/IStatIncreaseResultPlugIn.cs @@ -15,6 +15,6 @@ public interface IStatIncreaseResultPlugIn : IViewPlugIn /// Shows the stat increase result. /// /// Type of the stat. - /// if set to true the increment was successful. - ValueTask StatIncreaseResultAsync(AttributeDefinition statType, bool success); + /// The added points. If 0, it was not successful. + ValueTask StatIncreaseResultAsync(AttributeDefinition statType, ushort addedPoints); } \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/AddExperienceExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/AddExperienceExtendedPlugIn.cs new file mode 100644 index 000000000..d081b4463 --- /dev/null +++ b/src/GameServer/RemoteView/Character/AddExperienceExtendedPlugIn.cs @@ -0,0 +1,51 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic; +using MUnique.OpenMU.GameLogic.Views; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(AddExperienceExtendedPlugIn), "The extended implementation of the IAddExperiencePlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("2C5AAEF1-47C9-498F-B3C1-D0F1B9AF0496")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class AddExperienceExtendedPlugIn : IAddExperiencePlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public AddExperienceExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask AddExperienceAsync(int exp, IAttackable? obj, ExperienceType experienceType) + { + uint damage = 0; + if (obj is not null + && this._player.Id != obj.LastDeath?.KillerId) // Show Damage only for party members. + { + damage = (uint)Math.Min(obj.LastDeath?.FinalHit.HealthDamage ?? 0, uint.MaxValue); + } + + var killedId = obj?.GetId(this._player) ?? 0; + var killerId = obj?.LastDeath?.KillerId ?? 0; + if (killerId == this._player.Id) + { + killerId = ViewExtensions.ConstantPlayerId; + } + + await this._player.Connection.SendExperienceGainedExtendedAsync((byte)experienceType, + (uint)exp, + (uint)damage, + killedId, + killerId) + .ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/AddExperiencePlugIn.cs b/src/GameServer/RemoteView/Character/AddExperiencePlugIn.cs index 9a81c53ae..a8c78782f 100644 --- a/src/GameServer/RemoteView/Character/AddExperiencePlugIn.cs +++ b/src/GameServer/RemoteView/Character/AddExperiencePlugIn.cs @@ -27,7 +27,7 @@ public class AddExperiencePlugIn : IAddExperiencePlugIn public AddExperiencePlugIn(RemotePlayer player) => this._player = player; /// - public async ValueTask AddExperienceAsync(int exp, IAttackable? obj) + public async ValueTask AddExperienceAsync(int exp, IAttackable? obj, ExperienceType experienceType) { var remainingExperience = exp; ushort damage = 0; diff --git a/src/GameServer/RemoteView/Character/StatIncreaseResultExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/StatIncreaseResultExtendedPlugIn.cs new file mode 100644 index 000000000..e9c4e8942 --- /dev/null +++ b/src/GameServer/RemoteView/Character/StatIncreaseResultExtendedPlugIn.cs @@ -0,0 +1,44 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.AttributeSystem; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn("StatIncreaseResultPlugIn", "The extended implementation of the IStatIncreaseResultPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("4B9AEFF1-B139-45F9-9277-0FBDA7A3C020")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class StatIncreaseResultExtendedPlugIn : IStatIncreaseResultPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public StatIncreaseResultExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask StatIncreaseResultAsync(AttributeDefinition attribute, ushort addedPoints) + { + var connection = this._player.Connection; + if (connection is null) + { + return; + } + + await connection.SendCharacterStatIncreaseResponseExtendedAsync( + attribute.GetStatType(), + addedPoints, + (uint)this._player.Attributes![Stats.MaximumHealth], + (uint)this._player.Attributes![Stats.MaximumMana], + (uint)this._player.Attributes![Stats.MaximumShield], + (uint)this._player.Attributes![Stats.MaximumAbility]).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/StatIncreaseResultPlugIn.cs b/src/GameServer/RemoteView/Character/StatIncreaseResultPlugIn.cs index 78234c193..226204874 100644 --- a/src/GameServer/RemoteView/Character/StatIncreaseResultPlugIn.cs +++ b/src/GameServer/RemoteView/Character/StatIncreaseResultPlugIn.cs @@ -6,8 +6,11 @@ namespace MUnique.OpenMU.GameServer.RemoteView.Character; using System.Runtime.InteropServices; using MUnique.OpenMU.AttributeSystem; +using MUnique.OpenMU.GameLogic; using MUnique.OpenMU.GameLogic.Attributes; using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.GameLogic.Views.Inventory; +using MUnique.OpenMU.GameLogic.Views.World; using MUnique.OpenMU.Network.Packets.ServerToClient; using MUnique.OpenMU.PlugIns; @@ -27,7 +30,7 @@ public class StatIncreaseResultPlugIn : IStatIncreaseResultPlugIn public StatIncreaseResultPlugIn(RemotePlayer player) => this._player = player; /// - public async ValueTask StatIncreaseResultAsync(AttributeDefinition attribute, bool success) + public async ValueTask StatIncreaseResultAsync(AttributeDefinition attribute, ushort addedPoints) { var connection = this._player.Connection; if (connection is null) @@ -35,15 +38,37 @@ public async ValueTask StatIncreaseResultAsync(AttributeDefinition attribute, bo return; } - await connection.SendCharacterStatIncreaseResponseAsync( - success, - attribute.GetStatType(), - attribute == Stats.BaseEnergy - ? (ushort)this._player.Attributes![Stats.MaximumMana] - : attribute == Stats.BaseVitality - ? (ushort)this._player.Attributes![Stats.MaximumHealth] - : default, - (ushort)this._player.Attributes![Stats.MaximumShield], - (ushort)this._player.Attributes[Stats.MaximumAbility]).ConfigureAwait(false); + if (addedPoints <= 1) + { + await connection.SendCharacterStatIncreaseResponseAsync( + addedPoints > 0, + attribute.GetStatType(), + attribute == Stats.BaseEnergy + ? (ushort)this._player.Attributes![Stats.MaximumMana] + : attribute == Stats.BaseVitality + ? (ushort)this._player.Attributes![Stats.MaximumHealth] + : default, + (ushort)this._player.Attributes![Stats.MaximumShield], + (ushort)this._player.Attributes[Stats.MaximumAbility]).ConfigureAwait(false); + return; + } + + // Workaround with multiple points for older clients + var player = this._player; + var map = player.CurrentMap!; + + await player.InvokeViewPlugInAsync(p => p.ObjectsOutOfScopeAsync(player.GetAsEnumerable())).ConfigureAwait(false); + await player.InvokeViewPlugInAsync(p => p.UpdateCharacterStatsAsync()).ConfigureAwait(false); + await player.InvokeViewPlugInAsync(p => p.UpdateInventoryListAsync()).ConfigureAwait(false); + var currentGate = new Persistence.BasicModel.ExitGate + { + Map = map.Definition, + X1 = player.Position.X, + X2 = player.Position.X, + Y1 = player.Position.Y, + Y2 = player.Position.Y, + }; + + await player.WarpToAsync(currentGate).ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/UpdateCharacterStatsExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/UpdateCharacterStatsExtendedPlugIn.cs new file mode 100644 index 000000000..51864ce28 --- /dev/null +++ b/src/GameServer/RemoteView/Character/UpdateCharacterStatsExtendedPlugIn.cs @@ -0,0 +1,71 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(UpdateCharacterStatsExtendedPlugIn), "The extended implementation of the IUpdateCharacterStatsPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("851C4579-FB3D-454C-A238-217542E8E6B8")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class UpdateCharacterStatsExtendedPlugIn : IUpdateCharacterStatsPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public UpdateCharacterStatsExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask UpdateCharacterStatsAsync() + { + var connection = this._player.Connection; + if (connection is null || this._player.Account is null) + { + return; + } + + await connection.SendCharacterInformationExtendedAsync( + this._player.Position.X, + this._player.Position.Y, + this._player.SelectedCharacter!.CurrentMap!.Number.ToUnsigned(), + (ulong)this._player.SelectedCharacter.Experience, + (ulong)this._player.GameServerContext.ExperienceTable[(int)this._player.Attributes![Stats.Level] + 1], + (ushort)Math.Max(0, this._player.SelectedCharacter.LevelUpPoints), + (ushort)this._player.Attributes[Stats.BaseStrength], + (ushort)this._player.Attributes[Stats.BaseAgility], + (ushort)this._player.Attributes[Stats.BaseVitality], + (ushort)this._player.Attributes[Stats.BaseEnergy], + (ushort)this._player.Attributes[Stats.BaseLeadership], + (uint)this._player.Attributes[Stats.CurrentHealth], + (uint)this._player.Attributes[Stats.MaximumHealth], + (uint)this._player.Attributes[Stats.CurrentMana], + (uint)this._player.Attributes[Stats.MaximumMana], + (uint)this._player.Attributes[Stats.CurrentShield], + (uint)this._player.Attributes[Stats.MaximumShield], + (uint)this._player.Attributes[Stats.CurrentAbility], + (uint)this._player.Attributes[Stats.MaximumAbility], + (uint)this._player.Money, + this._player.SelectedCharacter.State.Convert(), + this._player.SelectedCharacter.CharacterStatus.Convert(), + (ushort)this._player.SelectedCharacter.UsedFruitPoints, + this._player.SelectedCharacter.GetMaximumFruitPoints(), + (ushort)this._player.SelectedCharacter.UsedNegFruitPoints, + this._player.SelectedCharacter.GetMaximumFruitPoints(), + (byte)this._player.SelectedCharacter.InventoryExtensions) + .ConfigureAwait(false); + + if (this._player.SelectedCharacter.CharacterClass!.IsMasterClass) + { + await this._player.InvokeViewPlugInAsync(p => p.SendMasterStatsAsync()).ConfigureAwait(false); + } + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/UpdateCurrentHealthExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/UpdateCurrentHealthExtendedPlugIn.cs new file mode 100644 index 000000000..0e14aead3 --- /dev/null +++ b/src/GameServer/RemoteView/Character/UpdateCurrentHealthExtendedPlugIn.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(UpdateCurrentHealthExtendedPlugIn), "The extended implementation of the IUpdateCurrentHealthPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("C609BC7E-170B-4C79-94E5-D97AB9A3CB4B")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class UpdateCurrentHealthExtendedPlugIn : IUpdateCurrentHealthPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public UpdateCurrentHealthExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask UpdateCurrentHealthAsync() + { + if (this._player.Attributes is null) + { + return; + } + + await this._player.Connection.SendCurrentHealthAndShieldExtendedAsync( + (uint)Math.Max(this._player.Attributes[Stats.CurrentHealth], 0f), + (uint)Math.Max(this._player.Attributes[Stats.CurrentShield], 0f)).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/UpdateCurrentManaExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/UpdateCurrentManaExtendedPlugIn.cs new file mode 100644 index 000000000..853af77bb --- /dev/null +++ b/src/GameServer/RemoteView/Character/UpdateCurrentManaExtendedPlugIn.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(UpdateCurrentManaExtendedPlugIn), "The extended implementation of the IUpdateCurrentManaPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("1F99BFB4-35FC-489B-AB3C-E0738314DF37")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class UpdateCurrentManaExtendedPlugIn : IUpdateCurrentManaPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public UpdateCurrentManaExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask UpdateCurrentManaAsync() + { + if (this._player.Attributes is null) + { + return; + } + + await this._player.Connection.SendCurrentManaAndAbilityExtendedAsync( + (uint)this._player.Attributes[Stats.CurrentMana], + (uint)this._player.Attributes[Stats.CurrentAbility]).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/UpdateLevelExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/UpdateLevelExtendedPlugIn.cs new file mode 100644 index 000000000..08b8bf468 --- /dev/null +++ b/src/GameServer/RemoteView/Character/UpdateLevelExtendedPlugIn.cs @@ -0,0 +1,78 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Interfaces; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(UpdateLevelExtendedPlugIn), "The extended implementation of the IUpdateLevelPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("6F358202-6678-4417-9537-D8739AEF78C2")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class UpdateLevelExtendedPlugIn : IUpdateLevelPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public UpdateLevelExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask UpdateLevelAsync() + { + var selectedCharacter = this._player.SelectedCharacter; + var charStats = this._player.Attributes; + var connection = this._player.Connection; + if (selectedCharacter is null || charStats is null || connection is null) + { + return; + } + + await connection.SendCharacterLevelUpdateExtendedAsync( + (ushort)charStats[Stats.Level], + (ushort)Math.Max(selectedCharacter.LevelUpPoints, 0), + (uint)charStats[Stats.MaximumHealth], + (uint)charStats[Stats.MaximumMana], + (uint)charStats[Stats.MaximumShield], + (uint)charStats[Stats.MaximumAbility], + (ushort)selectedCharacter.UsedFruitPoints, + selectedCharacter.GetMaximumFruitPoints(), + (ushort)selectedCharacter.UsedNegFruitPoints, + selectedCharacter.GetMaximumFruitPoints()).ConfigureAwait(false); + + await this._player.InvokeViewPlugInAsync(p => p.ShowMessageAsync($"Congratulations, you are Level {charStats[Stats.Level]} now.", MessageType.BlueNormal)).ConfigureAwait(false); + } + + /// + public async ValueTask UpdateMasterLevelAsync() + { + var selectedCharacter = this._player.SelectedCharacter; + var charStats = this._player.Attributes; + var connection = this._player.Connection; + if (selectedCharacter is null || charStats is null || connection is null) + { + return; + } + + await connection.SendMasterCharacterLevelUpdateExtendedAsync( + (ushort)charStats[Stats.MasterLevel], + (ushort)charStats[Stats.MasterPointsPerLevelUp], + (ushort)selectedCharacter.MasterLevelUpPoints, + (ushort)this._player.GameContext.Configuration.MaximumMasterLevel, + (uint)charStats[Stats.MaximumHealth], + (uint)charStats[Stats.MaximumMana], + (uint)charStats[Stats.MaximumShield], + (uint)charStats[Stats.MaximumAbility]).ConfigureAwait(false); + + await this._player.InvokeViewPlugInAsync(p => p.ShowMessageAsync($"Congratulations, you are Master Level {charStats[Stats.MasterLevel]} now.", MessageType.BlueNormal)).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/UpdateMasterStatsExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/UpdateMasterStatsExtendedPlugIn.cs new file mode 100644 index 000000000..b71325b8c --- /dev/null +++ b/src/GameServer/RemoteView/Character/UpdateMasterStatsExtendedPlugIn.cs @@ -0,0 +1,49 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(UpdateMasterStatsExtendedPlugIn), "The extended implementation of the IUpdateMasterStatsPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("EF19E11B-AE26-44F0-AB3E-5ADD5CDEBC56")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class UpdateMasterStatsExtendedPlugIn : IUpdateMasterStatsPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public UpdateMasterStatsExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask SendMasterStatsAsync() + { + var character = this._player.SelectedCharacter; + var connection = this._player.Connection; + if (character is null || this._player.Attributes is null || connection is null) + { + return; + } + + await connection.SendMasterStatsUpdateExtendedAsync( + (ushort)this._player.Attributes[Stats.MasterLevel], + (ulong)character.MasterExperience, + (ulong)this._player.GameServerContext.MasterExperienceTable[(int)this._player.Attributes[Stats.MasterLevel] + 1], + (ushort)character.MasterLevelUpPoints, + (ushort)this._player.Attributes[Stats.MaximumHealth], + (ushort)this._player.Attributes[Stats.MaximumMana], + (ushort)this._player.Attributes[Stats.MaximumShield], + (ushort)this._player.Attributes[Stats.MaximumAbility]).ConfigureAwait(false); + + await this._player.InvokeViewPlugInAsync(p => p.UpdateMasterSkillsAsync()).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/UpdateMaximumHealthExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/UpdateMaximumHealthExtendedPlugIn.cs new file mode 100644 index 000000000..7caac9b9c --- /dev/null +++ b/src/GameServer/RemoteView/Character/UpdateMaximumHealthExtendedPlugIn.cs @@ -0,0 +1,39 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(UpdateMaximumHealthExtendedPlugIn), "The extended implementation of the IUpdateMaximumHealthPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("7A287D6D-5C32-4FA9-9A0D-A4E0DEB053D1")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class UpdateMaximumHealthExtendedPlugIn : IUpdateMaximumHealthPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public UpdateMaximumHealthExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask UpdateMaximumHealthAsync() + { + if (this._player.Attributes is null + || !(this._player.Connection?.Connected ?? false)) + { + return; + } + + await this._player.Connection.SendMaximumHealthAndShieldExtendedAsync( + (uint)this._player.Attributes[Stats.MaximumHealth], + (uint)this._player.Attributes[Stats.MaximumShield]).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Character/UpdateMaximumManaExtendedPlugIn.cs b/src/GameServer/RemoteView/Character/UpdateMaximumManaExtendedPlugIn.cs new file mode 100644 index 000000000..93e9466c1 --- /dev/null +++ b/src/GameServer/RemoteView/Character/UpdateMaximumManaExtendedPlugIn.cs @@ -0,0 +1,39 @@ +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Character; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +namespace MUnique.OpenMU.GameServer.RemoteView.Character; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(UpdateMaximumManaExtendedPlugIn), "The extended implementation of the IUpdateMaximumManaPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("25AF11D5-FA10-4634-AF5A-CBF6F5E8BDFE")] +[MinimumClient(106, 3, ClientLanguage.Invariant)] +public class UpdateMaximumManaExtendedPlugIn : IUpdateMaximumManaPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public UpdateMaximumManaExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + public async ValueTask UpdateMaximumManaAsync() + { + if (this._player.Attributes is null + || !(this._player.Connection?.Connected ?? false)) + { + return; + } + + await this._player.Connection.SendMaximumManaAndAbilityExtendedAsync( + (uint)this._player.Attributes[Stats.MaximumMana], + (uint)this._player.Attributes[Stats.MaximumAbility]).ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/Inventory/RequestedItemConsumptionFailedExtendedPlugIn.cs b/src/GameServer/RemoteView/Inventory/RequestedItemConsumptionFailedExtendedPlugIn.cs new file mode 100644 index 000000000..3d8183a9c --- /dev/null +++ b/src/GameServer/RemoteView/Inventory/RequestedItemConsumptionFailedExtendedPlugIn.cs @@ -0,0 +1,44 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.GameServer.RemoteView.Inventory; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic.Attributes; +using MUnique.OpenMU.GameLogic.Views.Inventory; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(RequestedItemConsumptionFailedExtendedPlugIn), "The extended implementation of the IRequestedItemConsumptionFailedPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("8F98AAF4-E329-4DE2-B8D5-9169B64E20B2")] +[MinimumClient(106, 3, ClientLanguage.English)] +public class RequestedItemConsumptionFailedExtendedPlugIn : IRequestedItemConsumptionFailedPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public RequestedItemConsumptionFailedExtendedPlugIn(RemotePlayer player) => this._player = player; + + /// + /// The server sends the current health/shield to the client, with . + public async ValueTask RequestedItemConsumptionFailedAsync() + { + if (this._player.Attributes is null) + { + return; + } + + await this._player.Connection.SendItemConsumptionFailedExtendedAsync( + (uint)Math.Max(this._player.Attributes[Stats.CurrentHealth], 0f), + (uint)Math.Max(this._player.Attributes[Stats.CurrentShield], 0f)) + .ConfigureAwait(false); + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/World/ShowHitExtendedPlugIn.cs b/src/GameServer/RemoteView/World/ShowHitExtendedPlugIn.cs new file mode 100644 index 000000000..cb74a3515 --- /dev/null +++ b/src/GameServer/RemoteView/World/ShowHitExtendedPlugIn.cs @@ -0,0 +1,88 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.GameServer.RemoteView.World; + +using System.Runtime.InteropServices; +using MUnique.OpenMU.GameLogic; +using MUnique.OpenMU.GameLogic.Views; +using MUnique.OpenMU.GameLogic.Views.World; +using MUnique.OpenMU.Network.Packets.ServerToClient; +using MUnique.OpenMU.Network.PlugIns; +using MUnique.OpenMU.PlugIns; + +/// +/// The extended implementation of the which is forwarding everything to the game client with specific data packets. +/// +[PlugIn(nameof(ShowHitExtendedPlugIn), "The extended implementation of the IShowHitPlugIn which is forwarding everything to the game client with specific data packets.")] +[Guid("E79C8065-21A8-4774-B84F-5B8658F6A820")] +[MinimumClient(106, 3, ClientLanguage.English)] +public class ShowHitExtendedPlugIn : IShowHitPlugIn +{ + private readonly RemotePlayer _player; + + /// + /// Initializes a new instance of the class. + /// + /// The player. + public ShowHitExtendedPlugIn(RemotePlayer player) + { + this._player = player; + } + + /// + /// This Packet is sent to the Client when a Player or Monster got hit and damaged. + /// It includes which Player/Monster got hit by who, and the Damage Type. + /// It is obvious that the mu online protocol only supports 16 bits for each damage value. To prevent bugs (own player health) + /// and to make it somehow visible that the damage exceeds 65k, we send more than one packet, if the 16bits are not enough. + /// + /// + public async ValueTask ShowHitAsync(IAttackable target, HitInfo hitInfo) + { + if (this._player.Connection is not { } connection) + { + return; + } + + var targetId = target.GetId(this._player); + await connection.SendObjectHitExtendedAsync( + this.GetDamageKind(hitInfo.Attributes), + + hitInfo.Attributes.HasFlag(DamageAttributes.Double), + hitInfo.Attributes.HasFlag(DamageAttributes.Triple), + targetId, + hitInfo.HealthDamage, + hitInfo.ShieldDamage).ConfigureAwait(false); + } + + private DamageKind GetDamageKind(DamageAttributes attributes) + { + if (attributes.HasFlag(DamageAttributes.IgnoreDefense)) + { + return DamageKind.IgnoreDefenseCyan; + } + + if (attributes.HasFlag(DamageAttributes.Excellent)) + { + return DamageKind.ExcellentLightGreen; + } + + if (attributes.HasFlag(DamageAttributes.Critical)) + { + return DamageKind.CriticalBlue; + } + + if (attributes.HasFlag(DamageAttributes.Reflected)) + { + return DamageKind.ReflectedDarkPink; + } + + if (attributes.HasFlag(DamageAttributes.Poison)) + { + return DamageKind.PoisonDarkGreen; + } + + return DamageKind.NormalRed; + } +} \ No newline at end of file diff --git a/src/GameServer/RemoteView/World/ShowHitPlugIn.cs b/src/GameServer/RemoteView/World/ShowHitPlugIn.cs index 0bc6e1fe8..4aaf59b39 100644 --- a/src/GameServer/RemoteView/World/ShowHitPlugIn.cs +++ b/src/GameServer/RemoteView/World/ShowHitPlugIn.cs @@ -99,33 +99,33 @@ private byte DetermineOperation() } } - private ObjectHit.DamageKind GetDamageKind(DamageAttributes attributes) + private DamageKind GetDamageKind(DamageAttributes attributes) { if (attributes.HasFlag(DamageAttributes.IgnoreDefense)) { - return ObjectHit.DamageKind.IgnoreDefenseCyan; + return DamageKind.IgnoreDefenseCyan; } if (attributes.HasFlag(DamageAttributes.Excellent)) { - return ObjectHit.DamageKind.ExcellentLightGreen; + return DamageKind.ExcellentLightGreen; } if (attributes.HasFlag(DamageAttributes.Critical)) { - return ObjectHit.DamageKind.CriticalBlue; + return DamageKind.CriticalBlue; } if (attributes.HasFlag(DamageAttributes.Reflected)) { - return ObjectHit.DamageKind.ReflectedDarkPink; + return DamageKind.ReflectedDarkPink; } if (attributes.HasFlag(DamageAttributes.Poison)) { - return ObjectHit.DamageKind.PoisonDarkGreen; + return DamageKind.PoisonDarkGreen; } - return ObjectHit.DamageKind.NormalRed; + return DamageKind.NormalRed; } } \ No newline at end of file diff --git a/src/Network/Packets/ServerToClient/ConnectionExtensions.cs b/src/Network/Packets/ServerToClient/ConnectionExtensions.cs index a19cc8cce..ac233c468 100644 --- a/src/Network/Packets/ServerToClient/ConnectionExtensions.cs +++ b/src/Network/Packets/ServerToClient/ConnectionExtensions.cs @@ -966,7 +966,7 @@ int WritePacket() /// Is sent by the server when: An object got hit in two cases: 1. When the own player is hit; 2. When the own player attacked some other object which got hit. /// Causes reaction on client side: The damage is shown at the object which received the hit. /// - public static async ValueTask SendObjectHitAsync(this IConnection? connection, byte @headerCode, ushort @objectId, ushort @healthDamage, ObjectHit.DamageKind @kind, bool @isDoubleDamage, bool @isTripleDamage, ushort @shieldDamage) + public static async ValueTask SendObjectHitAsync(this IConnection? connection, byte @headerCode, ushort @objectId, ushort @healthDamage, DamageKind @kind, bool @isDoubleDamage, bool @isTripleDamage, ushort @shieldDamage) { if (connection is null) { @@ -991,6 +991,44 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The kind. + /// The is double damage. + /// The is triple damage. + /// The object id. + /// The health damage. + /// The shield damage. + /// + /// Is sent by the server when: An object got hit in two cases: 1. When the own player is hit; 2. When the own player attacked some other object which got hit. + /// Causes reaction on client side: The damage is shown at the object which received the hit. + /// + public static async ValueTask SendObjectHitExtendedAsync(this IConnection? connection, DamageKind @kind, bool @isDoubleDamage, bool @isTripleDamage, ushort @objectId, uint @healthDamage, uint @shieldDamage) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = ObjectHitExtendedRef.Length; + var packet = new ObjectHitExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Kind = @kind; + packet.IsDoubleDamage = @isDoubleDamage; + packet.IsTripleDamage = @isTripleDamage; + packet.ObjectId = @objectId; + packet.HealthDamage = @healthDamage; + packet.ShieldDamage = @shieldDamage; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -1131,6 +1169,42 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The type. + /// The added experience. + /// The damage of last hit. + /// The killed object id. + /// The killer object id. + /// + /// Is sent by the server when: A player gained experience. + /// Causes reaction on client side: The experience is added to the experience counter and bar. + /// + public static async ValueTask SendExperienceGainedExtendedAsync(this IConnection? connection, ExperienceGainedExtended.AddResult @type, uint @addedExperience, uint @damageOfLastHit, ushort @killedObjectId, ushort @killerObjectId) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = ExperienceGainedExtendedRef.Length; + var packet = new ExperienceGainedExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Type = @type; + packet.AddedExperience = @addedExperience; + packet.DamageOfLastHit = @damageOfLastHit; + packet.KilledObjectId = @killedObjectId; + packet.KillerObjectId = @killerObjectId; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -1521,6 +1595,36 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The health. + /// The shield. + /// + /// Is sent by the server when: Periodically, or if the current health or shield changed on the server side, e.g. by hits. + /// Causes reaction on client side: The health and shield bar is updated on the game client user interface. + /// + public static async ValueTask SendCurrentHealthAndShieldExtendedAsync(this IConnection? connection, uint @health, uint @shield) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = CurrentHealthAndShieldExtendedRef.Length; + var packet = new CurrentHealthAndShieldExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Health = @health; + packet.Shield = @shield; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -1551,6 +1655,36 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The health. + /// The shield. + /// + /// Is sent by the server when: When the maximum health changed, e.g. by adding stat points or changed items. + /// Causes reaction on client side: The health and shield bar is updated on the game client user interface. + /// + public static async ValueTask SendMaximumHealthAndShieldExtendedAsync(this IConnection? connection, uint @health, uint @shield) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = MaximumHealthAndShieldExtendedRef.Length; + var packet = new MaximumHealthAndShieldExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Health = @health; + packet.Shield = @shield; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -1581,6 +1715,36 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The health. + /// The shield. + /// + /// Is sent by the server when: When the consumption of an item failed. + /// Causes reaction on client side: The game client gets a feedback about a failed consumption, and allows for do further consumption requests. + /// + public static async ValueTask SendItemConsumptionFailedExtendedAsync(this IConnection? connection, uint @health, uint @shield) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = ItemConsumptionFailedExtendedRef.Length; + var packet = new ItemConsumptionFailedExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Health = @health; + packet.Shield = @shield; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -1611,6 +1775,36 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The mana. + /// The ability. + /// + /// Is sent by the server when: The currently available mana or ability has changed, e.g. by using a skill. + /// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. + /// + public static async ValueTask SendCurrentManaAndAbilityExtendedAsync(this IConnection? connection, uint @mana, uint @ability) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = CurrentManaAndAbilityExtendedRef.Length; + var packet = new CurrentManaAndAbilityExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Mana = @mana; + packet.Ability = @ability; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -1641,6 +1835,36 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The mana. + /// The ability. + /// + /// Is sent by the server when: The maximum available mana or ability has changed, e.g. by adding stat points. + /// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. + /// + public static async ValueTask SendMaximumManaAndAbilityExtendedAsync(this IConnection? connection, uint @mana, uint @ability) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = MaximumManaAndAbilityExtendedRef.Length; + var packet = new MaximumManaAndAbilityExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Mana = @mana; + packet.Ability = @ability; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -2559,6 +2783,44 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The attribute. + /// The added amount. + /// The updated maximum health. + /// The updated maximum mana. + /// The updated maximum shield. + /// The updated maximum ability. + /// + /// Is sent by the server when: After the server processed a character stat increase request packet. + /// Causes reaction on client side: If it was successful, adds a point to the requested stat type. + /// + public static async ValueTask SendCharacterStatIncreaseResponseExtendedAsync(this IConnection? connection, CharacterStatAttribute @attribute, ushort @addedAmount, uint @updatedMaximumHealth, uint @updatedMaximumMana, uint @updatedMaximumShield, uint @updatedMaximumAbility) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = CharacterStatIncreaseResponseExtendedRef.Length; + var packet = new CharacterStatIncreaseResponseExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Attribute = @attribute; + packet.AddedAmount = @addedAmount; + packet.UpdatedMaximumHealth = @updatedMaximumHealth; + packet.UpdatedMaximumMana = @updatedMaximumMana; + packet.UpdatedMaximumShield = @updatedMaximumShield; + packet.UpdatedMaximumAbility = @updatedMaximumAbility; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -2713,6 +2975,132 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The level. + /// The level up points. + /// The maximum health. + /// The maximum mana. + /// The maximum shield. + /// The maximum ability. + /// The fruit points. + /// The maximum fruit points. + /// The negative fruit points. + /// The maximum negative fruit points. + /// + /// Is sent by the server when: After a character leveled up. + /// Causes reaction on client side: Updates the level (and other related stats) in the game client and shows an effect. + /// + public static async ValueTask SendCharacterLevelUpdateExtendedAsync(this IConnection? connection, ushort @level, ushort @levelUpPoints, uint @maximumHealth, uint @maximumMana, uint @maximumShield, uint @maximumAbility, ushort @fruitPoints, ushort @maximumFruitPoints, ushort @negativeFruitPoints, ushort @maximumNegativeFruitPoints) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = CharacterLevelUpdateExtendedRef.Length; + var packet = new CharacterLevelUpdateExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.Level = @level; + packet.LevelUpPoints = @levelUpPoints; + packet.MaximumHealth = @maximumHealth; + packet.MaximumMana = @maximumMana; + packet.MaximumShield = @maximumShield; + packet.MaximumAbility = @maximumAbility; + packet.FruitPoints = @fruitPoints; + packet.MaximumFruitPoints = @maximumFruitPoints; + packet.NegativeFruitPoints = @negativeFruitPoints; + packet.MaximumNegativeFruitPoints = @maximumNegativeFruitPoints; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + + /// + /// Sends a to this connection. + /// + /// The connection. + /// The x. + /// The y. + /// The map id. + /// The current experience. + /// The experience for next level. + /// The level up points. + /// The strength. + /// The agility. + /// The vitality. + /// The energy. + /// The leadership. + /// The current health. + /// The maximum health. + /// The current mana. + /// The maximum mana. + /// The current shield. + /// The maximum shield. + /// The current ability. + /// The maximum ability. + /// The money. + /// The hero state. + /// The status. + /// The used fruit points. + /// The max fruit points. + /// The used negative fruit points. + /// The max negative fruit points. + /// The inventory extensions. + /// + /// Is sent by the server when: After the character was selected by the player and entered the game. + /// Causes reaction on client side: The characters enters the game world. + /// + public static async ValueTask SendCharacterInformationExtendedAsync(this IConnection? connection, byte @x, byte @y, ushort @mapId, ulong @currentExperience, ulong @experienceForNextLevel, ushort @levelUpPoints, ushort @strength, ushort @agility, ushort @vitality, ushort @energy, ushort @leadership, uint @currentHealth, uint @maximumHealth, uint @currentMana, uint @maximumMana, uint @currentShield, uint @maximumShield, uint @currentAbility, uint @maximumAbility, uint @money, CharacterHeroState @heroState, CharacterStatus @status, ushort @usedFruitPoints, ushort @maxFruitPoints, ushort @usedNegativeFruitPoints, ushort @maxNegativeFruitPoints, byte @inventoryExtensions) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = CharacterInformationExtendedRef.Length; + var packet = new CharacterInformationExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.X = @x; + packet.Y = @y; + packet.MapId = @mapId; + packet.CurrentExperience = @currentExperience; + packet.ExperienceForNextLevel = @experienceForNextLevel; + packet.LevelUpPoints = @levelUpPoints; + packet.Strength = @strength; + packet.Agility = @agility; + packet.Vitality = @vitality; + packet.Energy = @energy; + packet.Leadership = @leadership; + packet.CurrentHealth = @currentHealth; + packet.MaximumHealth = @maximumHealth; + packet.CurrentMana = @currentMana; + packet.MaximumMana = @maximumMana; + packet.CurrentShield = @currentShield; + packet.MaximumShield = @maximumShield; + packet.CurrentAbility = @currentAbility; + packet.MaximumAbility = @maximumAbility; + packet.Money = @money; + packet.HeroState = @heroState; + packet.Status = @status; + packet.UsedFruitPoints = @usedFruitPoints; + packet.MaxFruitPoints = @maxFruitPoints; + packet.UsedNegativeFruitPoints = @usedNegativeFruitPoints; + packet.MaxNegativeFruitPoints = @maxNegativeFruitPoints; + packet.InventoryExtensions = @inventoryExtensions; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -3165,6 +3553,48 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The master level. + /// The master experience. + /// The master experience of next level. + /// The master level up points. + /// The maximum health. + /// The maximum mana. + /// The maximum shield. + /// The maximum ability. + /// + /// Is sent by the server when: After entering the game with a master class character. + /// Causes reaction on client side: The master related data is available. + /// + public static async ValueTask SendMasterStatsUpdateExtendedAsync(this IConnection? connection, ushort @masterLevel, ulong @masterExperience, ulong @masterExperienceOfNextLevel, ushort @masterLevelUpPoints, uint @maximumHealth, uint @maximumMana, uint @maximumShield, uint @maximumAbility) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = MasterStatsUpdateExtendedRef.Length; + var packet = new MasterStatsUpdateExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.MasterLevel = @masterLevel; + packet.MasterExperience = @masterExperience; + packet.MasterExperienceOfNextLevel = @masterExperienceOfNextLevel; + packet.MasterLevelUpPoints = @masterLevelUpPoints; + packet.MaximumHealth = @maximumHealth; + packet.MaximumMana = @maximumMana; + packet.MaximumShield = @maximumShield; + packet.MaximumAbility = @maximumAbility; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// @@ -3207,6 +3637,48 @@ int WritePacket() await connection.SendAsync(WritePacket).ConfigureAwait(false); } + /// + /// Sends a to this connection. + /// + /// The connection. + /// The master level. + /// The gained master points. + /// The current master points. + /// The maximum master points. + /// The maximum health. + /// The maximum mana. + /// The maximum shield. + /// The maximum ability. + /// + /// Is sent by the server when: After a master character leveled up. + /// Causes reaction on client side: Updates the master level (and other related stats) in the game client and shows an effect. + /// + public static async ValueTask SendMasterCharacterLevelUpdateExtendedAsync(this IConnection? connection, ushort @masterLevel, ushort @gainedMasterPoints, ushort @currentMasterPoints, ushort @maximumMasterPoints, uint @maximumHealth, uint @maximumMana, uint @maximumShield, uint @maximumAbility) + { + if (connection is null) + { + return; + } + + int WritePacket() + { + var length = MasterCharacterLevelUpdateExtendedRef.Length; + var packet = new MasterCharacterLevelUpdateExtendedRef(connection.Output.GetSpan(length)[..length]); + packet.MasterLevel = @masterLevel; + packet.GainedMasterPoints = @gainedMasterPoints; + packet.CurrentMasterPoints = @currentMasterPoints; + packet.MaximumMasterPoints = @maximumMasterPoints; + packet.MaximumHealth = @maximumHealth; + packet.MaximumMana = @maximumMana; + packet.MaximumShield = @maximumShield; + packet.MaximumAbility = @maximumAbility; + + return packet.Header.Length; + } + + await connection.SendAsync(WritePacket).ConfigureAwait(false); + } + /// /// Sends a to this connection. /// diff --git a/src/Network/Packets/ServerToClient/ServerToClientPackets.cs b/src/Network/Packets/ServerToClient/ServerToClientPackets.cs index a5456be8f..e5ef9b91f 100644 --- a/src/Network/Packets/ServerToClient/ServerToClientPackets.cs +++ b/src/Network/Packets/ServerToClient/ServerToClientPackets.cs @@ -5874,52 +5874,6 @@ public string Message /// public readonly struct ObjectHit { - /// - /// Defines the kind of the damage. - /// - public enum DamageKind - { - /// - /// Red color, used by normal damage. - /// - NormalRed = 0, - - /// - /// Cyan color, usually used by ignore defense damage. - /// - IgnoreDefenseCyan = 1, - - /// - /// Light green color, usually used by excellent damage. - /// - ExcellentLightGreen = 2, - - /// - /// Blue color, usually used by critical damage. - /// - CriticalBlue = 3, - - /// - /// Light pink color. - /// - LightPink = 4, - - /// - /// Dark green color, usually used by poison damage. - /// - PoisonDarkGreen = 5, - - /// - /// Dark pink color, usually used by reflected damage. - /// - ReflectedDarkPink = 6, - - /// - /// White color. - /// - White = 7, - } - private readonly Memory _data; /// @@ -5998,7 +5952,7 @@ public ushort HealthDamage /// /// Gets or sets the kind. /// - public ObjectHit.DamageKind Kind + public DamageKind Kind { get => (DamageKind)this._data.Span[7..].GetByteValue(4, 0); set => this._data.Span[7..].SetByteValue((byte)value, 4, 0); @@ -6047,6 +6001,130 @@ public ushort ShieldDamage } +/// +/// Is sent by the server when: An object got hit in two cases: 1. When the own player is hit; 2. When the own player attacked some other object which got hit. +/// Causes reaction on client side: The damage is shown at the object which received the hit. +/// +public readonly struct ObjectHitExtended +{ + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public ObjectHitExtended(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ObjectHitExtended(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x11; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 16; + + /// + /// Gets the header of this packet. + /// + public C1Header Header => new (this._data); + + /// + /// Gets or sets the kind. + /// + public DamageKind Kind + { + get => (DamageKind)this._data.Span[3..].GetByteValue(4, 0); + set => this._data.Span[3..].SetByteValue((byte)value, 4, 0); + } + + /// + /// Gets or sets the is double damage. + /// + public bool IsDoubleDamage + { + get => this._data.Span[3..].GetBoolean(6); + set => this._data.Span[3..].SetBoolean(value, 6); + } + + /// + /// Gets or sets the is triple damage. + /// + public bool IsTripleDamage + { + get => this._data.Span[3..].GetBoolean(7); + set => this._data.Span[3..].SetBoolean(value, 7); + } + + /// + /// Gets or sets the object id. + /// + public ushort ObjectId + { + get => ReadUInt16LittleEndian(this._data.Span[4..]); + set => WriteUInt16LittleEndian(this._data.Span[4..], value); + } + + /// + /// Gets or sets the health damage. + /// + public uint HealthDamage + { + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); + } + + /// + /// Gets or sets the shield damage. + /// + public uint ShieldDamage + { + get => ReadUInt32LittleEndian(this._data.Span[12..]); + set => WriteUInt32LittleEndian(this._data.Span[12..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ObjectHitExtended(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(ObjectHitExtended packet) => packet._data; +} + + /// /// Is sent by the server when: An object in the observed scope (including the own player) moved instantly. /// Causes reaction on client side: The position of the object is updated on client side. @@ -6491,28 +6569,59 @@ public ushort DamageOfLastHit /// -/// Is sent by the server when: The map was changed on the server side. -/// Causes reaction on client side: The game client changes to the specified map and coordinates. +/// Is sent by the server when: A player gained experience. +/// Causes reaction on client side: The experience is added to the experience counter and bar. /// -public readonly struct MapChanged +public readonly struct ExperienceGainedExtended { + /// + /// Defines the result and type of experience which is added. + /// + public enum AddResult + { + /// + /// The normal experience is added. + /// + Normal = 1, + + /// + /// The master experience is added. + /// + Master = 2, + + /// + /// The maximum level has been reached, no experience is added. + /// + MaxLevelReached = 0x10, + + /// + /// The maximum master level has been reached, no master experience is added. + /// + MaxMasterLevelReached = 0x20, + + /// + /// The monster level is too low for master experience, no master experience is added. + /// + MonsterLevelTooLowForMasterExperience = 0x21, + } + private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MapChanged(Memory data) + public ExperienceGainedExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MapChanged(Memory data, bool initialize) + private ExperienceGainedExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -6521,8 +6630,6 @@ private MapChanged(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; - this.IsMapChange = true; } } @@ -6534,82 +6641,76 @@ private MapChanged(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x1C; - - /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. - /// - public static byte SubCode => 0x0F; + public static byte Code => 0x16; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 15; + public static int Length => 16; /// /// Gets the header of this packet. /// - public C3HeaderWithSubCode Header => new (this._data); + public C3Header Header => new (this._data); /// - /// Gets or sets if false, it shows the teleport animation (white bubbles), and the client doesn't remove all of the objects in its scope. + /// Gets or sets the type. /// - public bool IsMapChange + public ExperienceGainedExtended.AddResult Type { - get => this._data.Span[4..].GetBoolean(); - set => this._data.Span[4..].SetBoolean(value); + get => (AddResult)this._data.Span[3]; + set => this._data.Span[3] = (byte)value; } /// - /// Gets or sets the map number. + /// Gets or sets the added experience. /// - public ushort MapNumber + public uint AddedExperience { - get => ReadUInt16BigEndian(this._data.Span[5..]); - set => WriteUInt16BigEndian(this._data.Span[5..], value); + get => ReadUInt32LittleEndian(this._data.Span[4..]); + set => WriteUInt32LittleEndian(this._data.Span[4..], value); } /// - /// Gets or sets the position x. + /// Gets or sets the damage of last hit. /// - public byte PositionX + public uint DamageOfLastHit { - get => this._data.Span[7]; - set => this._data.Span[7] = value; + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); } /// - /// Gets or sets the position y. + /// Gets or sets the killed object id. /// - public byte PositionY + public ushort KilledObjectId { - get => this._data.Span[8]; - set => this._data.Span[8] = value; + get => ReadUInt16LittleEndian(this._data.Span[12..]); + set => WriteUInt16LittleEndian(this._data.Span[12..], value); } /// - /// Gets or sets the rotation. + /// Gets or sets the killer object id. /// - public byte Rotation + public ushort KillerObjectId { - get => this._data.Span[9]; - set => this._data.Span[9] = value; + get => ReadUInt16LittleEndian(this._data.Span[14..]); + set => WriteUInt16LittleEndian(this._data.Span[14..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MapChanged(Memory packet) => new (packet, false); + public static implicit operator ExperienceGainedExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(MapChanged packet) => packet._data; + public static implicit operator Memory(ExperienceGainedExtended packet) => packet._data; } @@ -6617,25 +6718,25 @@ public byte Rotation /// Is sent by the server when: The map was changed on the server side. /// Causes reaction on client side: The game client changes to the specified map and coordinates. /// -public readonly struct MapChanged075 +public readonly struct MapChanged { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MapChanged075(Memory data) + public MapChanged(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MapChanged075(Memory data, bool initialize) + private MapChanged(Memory data, bool initialize) { this._data = data; if (initialize) @@ -6644,6 +6745,7 @@ private MapChanged075(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; this.IsMapChange = true; } } @@ -6658,15 +6760,137 @@ private MapChanged075(Memory data, bool initialize) /// public static byte Code => 0x1C; + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x0F; + /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 15; /// /// Gets the header of this packet. /// - public C3Header Header => new (this._data); + public C3HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets if false, it shows the teleport animation (white bubbles), and the client doesn't remove all of the objects in its scope. + /// + public bool IsMapChange + { + get => this._data.Span[4..].GetBoolean(); + set => this._data.Span[4..].SetBoolean(value); + } + + /// + /// Gets or sets the map number. + /// + public ushort MapNumber + { + get => ReadUInt16BigEndian(this._data.Span[5..]); + set => WriteUInt16BigEndian(this._data.Span[5..], value); + } + + /// + /// Gets or sets the position x. + /// + public byte PositionX + { + get => this._data.Span[7]; + set => this._data.Span[7] = value; + } + + /// + /// Gets or sets the position y. + /// + public byte PositionY + { + get => this._data.Span[8]; + set => this._data.Span[8] = value; + } + + /// + /// Gets or sets the rotation. + /// + public byte Rotation + { + get => this._data.Span[9]; + set => this._data.Span[9] = value; + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator MapChanged(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(MapChanged packet) => packet._data; +} + + +/// +/// Is sent by the server when: The map was changed on the server side. +/// Causes reaction on client side: The game client changes to the specified map and coordinates. +/// +public readonly struct MapChanged075 +{ + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public MapChanged075(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private MapChanged075(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + this.IsMapChange = true; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC3; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x1C; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 8; + + /// + /// Gets the header of this packet. + /// + public C3Header Header => new (this._data); /// /// Gets or sets if false, it shows the teleport animation (white bubbles), and the client doesn't remove all of the objects in its scope. @@ -8006,28 +8230,28 @@ public ushort Shield /// -/// Is sent by the server when: When the maximum health changed, e.g. by adding stat points or changed items. +/// Is sent by the server when: Periodically, or if the current health or shield changed on the server side, e.g. by hits. /// Causes reaction on client side: The health and shield bar is updated on the game client user interface. /// -public readonly struct MaximumHealthAndShield +public readonly struct CurrentHealthAndShieldExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MaximumHealthAndShield(Memory data) + public CurrentHealthAndShieldExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MaximumHealthAndShield(Memory data, bool initialize) + private CurrentHealthAndShieldExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8054,12 +8278,12 @@ private MaximumHealthAndShield(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFE; + public static byte SubCode => 0xFF; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 9; + public static int Length => 12; /// /// Gets the header of this packet. @@ -8069,60 +8293,60 @@ private MaximumHealthAndShield(Memory data, bool initialize) /// /// Gets or sets the health. /// - public ushort Health + public uint Health { - get => ReadUInt16BigEndian(this._data.Span[4..]); - set => WriteUInt16BigEndian(this._data.Span[4..], value); + get => ReadUInt32LittleEndian(this._data.Span[4..]); + set => WriteUInt32LittleEndian(this._data.Span[4..], value); } /// /// Gets or sets the shield. /// - public ushort Shield + public uint Shield { - get => ReadUInt16BigEndian(this._data.Span[7..]); - set => WriteUInt16BigEndian(this._data.Span[7..], value); + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MaximumHealthAndShield(Memory packet) => new (packet, false); + public static implicit operator CurrentHealthAndShieldExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(MaximumHealthAndShield packet) => packet._data; + public static implicit operator Memory(CurrentHealthAndShieldExtended packet) => packet._data; } /// -/// Is sent by the server when: When the consumption of an item failed. -/// Causes reaction on client side: The game client gets a feedback about a failed consumption, and allows for do further consumption requests. +/// Is sent by the server when: When the maximum health changed, e.g. by adding stat points or changed items. +/// Causes reaction on client side: The health and shield bar is updated on the game client user interface. /// -public readonly struct ItemConsumptionFailed +public readonly struct MaximumHealthAndShield { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemConsumptionFailed(Memory data) + public MaximumHealthAndShield(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemConsumptionFailed(Memory data, bool initialize) + private MaximumHealthAndShield(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8149,7 +8373,7 @@ private ItemConsumptionFailed(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFD; + public static byte SubCode => 0xFE; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. @@ -8180,44 +8404,44 @@ public ushort Shield } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemConsumptionFailed(Memory packet) => new (packet, false); + public static implicit operator MaximumHealthAndShield(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(ItemConsumptionFailed packet) => packet._data; + public static implicit operator Memory(MaximumHealthAndShield packet) => packet._data; } /// -/// Is sent by the server when: The currently available mana or ability has changed, e.g. by using a skill. -/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. +/// Is sent by the server when: When the maximum health changed, e.g. by adding stat points or changed items. +/// Causes reaction on client side: The health and shield bar is updated on the game client user interface. /// -public readonly struct CurrentManaAndAbility +public readonly struct MaximumHealthAndShieldExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CurrentManaAndAbility(Memory data) + public MaximumHealthAndShieldExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CurrentManaAndAbility(Memory data, bool initialize) + private MaximumHealthAndShieldExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8238,18 +8462,18 @@ private CurrentManaAndAbility(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x27; + public static byte Code => 0x26; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFF; + public static byte SubCode => 0xFE; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 12; /// /// Gets the header of this packet. @@ -8257,62 +8481,62 @@ private CurrentManaAndAbility(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the mana. + /// Gets or sets the health. /// - public ushort Mana + public uint Health { - get => ReadUInt16BigEndian(this._data.Span[4..]); - set => WriteUInt16BigEndian(this._data.Span[4..], value); + get => ReadUInt32LittleEndian(this._data.Span[4..]); + set => WriteUInt32LittleEndian(this._data.Span[4..], value); } /// - /// Gets or sets the ability. + /// Gets or sets the shield. /// - public ushort Ability + public uint Shield { - get => ReadUInt16BigEndian(this._data.Span[6..]); - set => WriteUInt16BigEndian(this._data.Span[6..], value); + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CurrentManaAndAbility(Memory packet) => new (packet, false); + public static implicit operator MaximumHealthAndShieldExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CurrentManaAndAbility packet) => packet._data; + public static implicit operator Memory(MaximumHealthAndShieldExtended packet) => packet._data; } /// -/// Is sent by the server when: The maximum available mana or ability has changed, e.g. by adding stat points. -/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. +/// Is sent by the server when: When the consumption of an item failed. +/// Causes reaction on client side: The game client gets a feedback about a failed consumption, and allows for do further consumption requests. /// -public readonly struct MaximumManaAndAbility +public readonly struct ItemConsumptionFailed { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MaximumManaAndAbility(Memory data) + public ItemConsumptionFailed(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MaximumManaAndAbility(Memory data, bool initialize) + private ItemConsumptionFailed(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8333,18 +8557,18 @@ private MaximumManaAndAbility(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x27; + public static byte Code => 0x26; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFE; + public static byte SubCode => 0xFD; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 9; /// /// Gets the header of this packet. @@ -8352,62 +8576,62 @@ private MaximumManaAndAbility(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the mana. + /// Gets or sets the health. /// - public ushort Mana + public ushort Health { get => ReadUInt16BigEndian(this._data.Span[4..]); set => WriteUInt16BigEndian(this._data.Span[4..], value); } /// - /// Gets or sets the ability. + /// Gets or sets the shield. /// - public ushort Ability + public ushort Shield { - get => ReadUInt16BigEndian(this._data.Span[6..]); - set => WriteUInt16BigEndian(this._data.Span[6..], value); + get => ReadUInt16BigEndian(this._data.Span[7..]); + set => WriteUInt16BigEndian(this._data.Span[7..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MaximumManaAndAbility(Memory packet) => new (packet, false); + public static implicit operator ItemConsumptionFailed(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(MaximumManaAndAbility packet) => packet._data; + public static implicit operator Memory(ItemConsumptionFailed packet) => packet._data; } /// -/// Is sent by the server when: The item has been removed from the inventory of the player. -/// Causes reaction on client side: The client removes the item in the inventory user interface. +/// Is sent by the server when: When the consumption of an item failed. +/// Causes reaction on client side: The game client gets a feedback about a failed consumption, and allows for do further consumption requests. /// -public readonly struct ItemRemoved +public readonly struct ItemConsumptionFailedExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemRemoved(Memory data) + public ItemConsumptionFailedExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemRemoved(Memory data, bool initialize) + private ItemConsumptionFailedExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8416,7 +8640,7 @@ private ItemRemoved(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); - this.TrueFlag = 1; + header.SubCode = SubCode; } } @@ -8428,96 +8652,81 @@ private ItemRemoved(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x28; + public static byte Code => 0x26; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public static int Length => 5; + public static byte SubCode => 0xFD; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 12; /// /// Gets the header of this packet. /// - public C1Header Header => new (this._data); + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the affected slot of the item in the inventory. + /// Gets or sets the health. /// - public byte InventorySlot + public uint Health { - get => this._data.Span[3]; - set => this._data.Span[3] = value; + get => ReadUInt32LittleEndian(this._data.Span[4..]); + set => WriteUInt32LittleEndian(this._data.Span[4..], value); } /// - /// Gets or sets the true flag. + /// Gets or sets the shield. /// - public byte TrueFlag + public uint Shield { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemRemoved(Memory packet) => new (packet, false); + public static implicit operator ItemConsumptionFailedExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(ItemRemoved packet) => packet._data; + public static implicit operator Memory(ItemConsumptionFailedExtended packet) => packet._data; } /// -/// Is sent by the server when: The client requested to consume a special item, e.g. a bottle of Ale. -/// Causes reaction on client side: The player is shown in a red color and has increased attack speed. +/// Is sent by the server when: The currently available mana or ability has changed, e.g. by using a skill. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly struct ConsumeItemWithEffect +public readonly struct CurrentManaAndAbility { - /// - /// Defines a consumed item. - /// - public enum ConsumedItemType - { - /// - /// The player consumes a bottle of ale, usually 80 seconds effect time. - /// - Ale = 0, - - /// - /// The player consumes a redemy of love, usually 90 seconds effect time. - /// - RedemyOfLove = 1, - - /// - /// The player consumes a potion of soul, usually 60 seconds effect time. - /// - PotionOfSoul = 77, - } - private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ConsumeItemWithEffect(Memory data) + public CurrentManaAndAbility(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ConsumeItemWithEffect(Memory data, bool initialize) + private CurrentManaAndAbility(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8526,86 +8735,93 @@ private ConsumeItemWithEffect(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC3; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x29; + public static byte Code => 0x27; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0xFF; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 6; + public static int Length => 8; /// /// Gets the header of this packet. /// - public C3Header Header => new (this._data); + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the item type. + /// Gets or sets the mana. /// - public ConsumeItemWithEffect.ConsumedItemType ItemType + public ushort Mana { - get => (ConsumedItemType)this._data.Span[3]; - set => this._data.Span[3] = (byte)value; + get => ReadUInt16BigEndian(this._data.Span[4..]); + set => WriteUInt16BigEndian(this._data.Span[4..], value); } /// - /// Gets or sets the effect time in seconds. + /// Gets or sets the ability. /// - public ushort EffectTimeInSeconds + public ushort Ability { - get => ReadUInt16BigEndian(this._data.Span[4..]); - set => WriteUInt16BigEndian(this._data.Span[4..], value); + get => ReadUInt16BigEndian(this._data.Span[6..]); + set => WriteUInt16BigEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ConsumeItemWithEffect(Memory packet) => new (packet, false); + public static implicit operator CurrentManaAndAbility(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(ConsumeItemWithEffect packet) => packet._data; + public static implicit operator Memory(CurrentManaAndAbility packet) => packet._data; } /// -/// Is sent by the server when: The durability of an item in the inventory of the player has been changed. -/// Causes reaction on client side: The client updates the item in the inventory user interface. +/// Is sent by the server when: The currently available mana or ability has changed, e.g. by using a skill. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly struct ItemDurabilityChanged +public readonly struct CurrentManaAndAbilityExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemDurabilityChanged(Memory data) + public CurrentManaAndAbilityExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemDurabilityChanged(Memory data, bool initialize) + private CurrentManaAndAbilityExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8614,6 +8830,7 @@ private ItemDurabilityChanged(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } @@ -8625,176 +8842,81 @@ private ItemDurabilityChanged(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x2A; + public static byte Code => 0x27; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public static int Length => 6; + public static byte SubCode => 0xFF; /// - /// Gets the header of this packet. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public C1Header Header => new (this._data); + public static int Length => 12; /// - /// Gets or sets the inventory slot. + /// Gets the header of this packet. /// - public byte InventorySlot - { - get => this._data.Span[3]; - set => this._data.Span[3] = value; - } + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the durability. + /// Gets or sets the mana. /// - public byte Durability + public uint Mana { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => ReadUInt32LittleEndian(this._data.Span[4..]); + set => WriteUInt32LittleEndian(this._data.Span[4..], value); } /// - /// Gets or sets true, if the change resulted from an item consumption; otherwise, false + /// Gets or sets the ability. /// - public bool ByConsumption + public uint Ability { - get => this._data.Span[5..].GetBoolean(); - set => this._data.Span[5..].SetBoolean(value); + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemDurabilityChanged(Memory packet) => new (packet, false); + public static implicit operator CurrentManaAndAbilityExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(ItemDurabilityChanged packet) => packet._data; + public static implicit operator Memory(CurrentManaAndAbilityExtended packet) => packet._data; } /// -/// Is sent by the server when: The player requested to consume a fruit. -/// Causes reaction on client side: The client updates the user interface, by changing the added stat points and used fruit points. +/// Is sent by the server when: The maximum available mana or ability has changed, e.g. by adding stat points. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly struct FruitConsumptionResponse +public readonly struct MaximumManaAndAbility { - /// - /// Defines the result of the fruit consumption request. - /// - public enum FruitConsumptionResult - { - /// - /// Consumption to add points was successful. - /// - PlusSuccess = 0, - - /// - /// Consumption to add points failed. - /// - PlusFailed = 1, - - /// - /// Consumption to add points was prevented because some conditions were not correct. - /// - PlusPrevented = 2, - - /// - /// Consumption to remove points was successful. - /// - MinusSuccess = 3, - - /// - /// Consumption to remove points failed. - /// - MinusFailed = 4, - - /// - /// Consumption to remove points was prevented because some conditions were not correct. - /// - MinusPrevented = 5, - - /// - /// Consumption to remove points was successful, removed by a fruit acquired through the cash shop. - /// - MinusSuccessCashShopFruit = 6, - - /// - /// Consumption was prevented because an item was equipped. - /// - PreventedByEquippedItems = 16, - - /// - /// Consumption to add points was prevented because the maximum amount of points have been added. - /// - PlusPreventedByMaximum = 33, - - /// - /// Consumption to remove points was prevented because the maximum amount of points have been removed. - /// - MinusPreventedByMaximum = 37, - - /// - /// Consumption to remove points was prevented because the base amount of stat points of the character class cannot be undercut. - /// - MinusPreventedByDefault = 38, - } - - /// - /// Defines the type of stat which the fruit modifies. - /// - public enum FruitStatType - { - /// - /// Fruit which modifies the energy stat. - /// - Energy = 0, - - /// - /// Fruit which modifies the vitality stat. - /// - Vitality = 1, - - /// - /// Fruit which modifies the agility stat. - /// - Agility = 2, - - /// - /// Fruit which modifies the strength stat. - /// - Strength = 3, - - /// - /// Fruit which modifies the leadership stat. - /// - Leadership = 4, - } - private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public FruitConsumptionResponse(Memory data) + public MaximumManaAndAbility(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private FruitConsumptionResponse(Memory data, bool initialize) + private MaximumManaAndAbility(Memory data, bool initialize) { this._data = data; if (initialize) @@ -8803,6 +8925,7 @@ private FruitConsumptionResponse(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } @@ -8814,212 +8937,176 @@ private FruitConsumptionResponse(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x2C; + public static byte Code => 0x27; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public static int Length => 7; + public static byte SubCode => 0xFE; /// - /// Gets the header of this packet. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public C1Header Header => new (this._data); + public static int Length => 8; /// - /// Gets or sets the result. + /// Gets the header of this packet. /// - public FruitConsumptionResponse.FruitConsumptionResult Result - { - get => (FruitConsumptionResult)this._data.Span[3]; - set => this._data.Span[3] = (byte)value; - } + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the stat points. + /// Gets or sets the mana. /// - public ushort StatPoints + public ushort Mana { - get => ReadUInt16LittleEndian(this._data.Span[4..]); - set => WriteUInt16LittleEndian(this._data.Span[4..], value); + get => ReadUInt16BigEndian(this._data.Span[4..]); + set => WriteUInt16BigEndian(this._data.Span[4..], value); } /// - /// Gets or sets the stat type. + /// Gets or sets the ability. /// - public FruitConsumptionResponse.FruitStatType StatType + public ushort Ability { - get => (FruitStatType)this._data.Span[6]; - set => this._data.Span[6] = (byte)value; + get => ReadUInt16BigEndian(this._data.Span[6..]); + set => WriteUInt16BigEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator FruitConsumptionResponse(Memory packet) => new (packet, false); + public static implicit operator MaximumManaAndAbility(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(FruitConsumptionResponse packet) => packet._data; + public static implicit operator Memory(MaximumManaAndAbility packet) => packet._data; } /// -/// Is sent by the server when: The player requested to consume an item which gives a magic effect. -/// Causes reaction on client side: The client updates the user interface, it shows the remaining time at the effect icon. +/// Is sent by the server when: The maximum available mana or ability has changed, e.g. by adding stat points. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly struct EffectItemConsumption +public readonly struct MaximumManaAndAbilityExtended { + private readonly Memory _data; + /// - /// Defines the origin of the effect. + /// Initializes a new instance of the struct. /// - public enum EffectOrigin + /// The underlying data. + public MaximumManaAndAbilityExtended(Memory data) + : this(data, true) { - /// - /// Not defined. - /// - Undefined = 0, - - /// - /// Options of Halloween and Cherry Blossom Event items. - /// - HalloweenAndCherryBlossomEvent = 1, - - /// - /// Options of cash shop items, like Seals. - /// - CashShopItem = 2, } /// - /// Defines the effect option. + /// Initializes a new instance of the struct. /// - public enum EffectAction + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private MaximumManaAndAbilityExtended(Memory data, bool initialize) { - /// - /// Effect is added. - /// - Add = 0, - - /// - /// Effect is removed. - /// - Remove = 1, - - /// - /// Effect is removed, because its getting replaced. - /// - Replace = 2, + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } } /// - /// Defines the kind of effect which was applied. + /// Gets the header type of this data packet. /// - public enum EffectType - { - /// - /// Attack speed increase. - /// - AttackSpeed = 1, - - /// - /// Damage increase. - /// - Damage = 2, - - /// - /// Defense increase. - /// - Defense = 3, - - /// - /// Maximum Health increase. - /// - MaximumHealth = 4, - - /// - /// Maximum Mana increase. - /// - MaximumMana = 5, - - /// - /// Experience rate increase. - /// - ExperienceRate = 6, - - /// - /// Drop rate increase. - /// - DropRate = 7, + public static byte HeaderType => 0xC1; - /// - /// Sustenance effect, means no experience is gained during this effect. - /// - Sustenance = 8, + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x27; - /// - /// Strength stat increase. - /// - Strength = 9, + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0xFE; - /// - /// Agility stat increase. - /// - Agility = 10, + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 12; - /// - /// Vitality stat increase. - /// - Vitality = 11, + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCode Header => new (this._data); - /// - /// Energy stat increase. - /// - Energy = 12, + /// + /// Gets or sets the mana. + /// + public uint Mana + { + get => ReadUInt32LittleEndian(this._data.Span[4..]); + set => WriteUInt32LittleEndian(this._data.Span[4..], value); + } - /// - /// Leadership stat increase. - /// - Leadership = 13, + /// + /// Gets or sets the ability. + /// + public uint Ability + { + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); + } - /// - /// Physical damage increase. - /// - PhysicalDamage = 14, + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator MaximumManaAndAbilityExtended(Memory packet) => new (packet, false); - /// - /// Wizardry damage increase. - /// - WizardryDamage = 15, + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(MaximumManaAndAbilityExtended packet) => packet._data; +} - /// - /// Mobility increase. - /// - Mobility = 16, - } +/// +/// Is sent by the server when: The item has been removed from the inventory of the player. +/// Causes reaction on client side: The client removes the item in the inventory user interface. +/// +public readonly struct ItemRemoved +{ private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public EffectItemConsumption(Memory data) + public ItemRemoved(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private EffectItemConsumption(Memory data, bool initialize) + private ItemRemoved(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9028,6 +9115,7 @@ private EffectItemConsumption(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + this.TrueFlag = 1; } } @@ -9039,12 +9127,12 @@ private EffectItemConsumption(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x2D; + public static byte Code => 0x28; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 17; + public static int Length => 5; /// /// Gets the header of this packet. @@ -9052,215 +9140,1188 @@ private EffectItemConsumption(Memory data, bool initialize) public C1Header Header => new (this._data); /// - /// Gets or sets the origin. + /// Gets or sets the affected slot of the item in the inventory. /// - public EffectItemConsumption.EffectOrigin Origin + public byte InventorySlot { - get => (EffectOrigin)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; + get => this._data.Span[3]; + set => this._data.Span[3] = value; } /// - /// Gets or sets the type. + /// Gets or sets the true flag. /// - public EffectItemConsumption.EffectType Type + public byte TrueFlag { - get => (EffectType)this._data.Span[6]; - set => this._data.Span[6] = (byte)value; + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Gets or sets the action. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public EffectItemConsumption.EffectAction Action - { - get => (EffectAction)this._data.Span[8]; - set => this._data.Span[8] = (byte)value; - } + /// The packet as span. + /// The packet as struct. + public static implicit operator ItemRemoved(Memory packet) => new (packet, false); /// - /// Gets or sets the remaining seconds. + /// Performs an implicit conversion from to a Memory of bytes. /// - public uint RemainingSeconds + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(ItemRemoved packet) => packet._data; +} + + +/// +/// Is sent by the server when: The client requested to consume a special item, e.g. a bottle of Ale. +/// Causes reaction on client side: The player is shown in a red color and has increased attack speed. +/// +public readonly struct ConsumeItemWithEffect +{ + /// + /// Defines a consumed item. + /// + public enum ConsumedItemType { - get => ReadUInt32LittleEndian(this._data.Span[12..]); - set => WriteUInt32LittleEndian(this._data.Span[12..], value); + /// + /// The player consumes a bottle of ale, usually 80 seconds effect time. + /// + Ale = 0, + + /// + /// The player consumes a redemy of love, usually 90 seconds effect time. + /// + RedemyOfLove = 1, + + /// + /// The player consumes a potion of soul, usually 60 seconds effect time. + /// + PotionOfSoul = 77, } + private readonly Memory _data; + /// - /// Gets or sets the magic effect number. + /// Initializes a new instance of the struct. /// - public byte MagicEffectNumber + /// The underlying data. + public ConsumeItemWithEffect(Memory data) + : this(data, true) { - get => this._data.Span[16]; - set => this._data.Span[16] = value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ConsumeItemWithEffect(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC3; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x29; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 6; + + /// + /// Gets the header of this packet. + /// + public C3Header Header => new (this._data); + + /// + /// Gets or sets the item type. + /// + public ConsumeItemWithEffect.ConsumedItemType ItemType + { + get => (ConsumedItemType)this._data.Span[3]; + set => this._data.Span[3] = (byte)value; + } + + /// + /// Gets or sets the effect time in seconds. + /// + public ushort EffectTimeInSeconds + { + get => ReadUInt16BigEndian(this._data.Span[4..]); + set => WriteUInt16BigEndian(this._data.Span[4..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator EffectItemConsumption(Memory packet) => new (packet, false); + public static implicit operator ConsumeItemWithEffect(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(EffectItemConsumption packet) => packet._data; + public static implicit operator Memory(ConsumeItemWithEffect packet) => packet._data; } /// -/// Is sent by the server when: After the client talked to an NPC which should cause a dialog to open on the client side. -/// Causes reaction on client side: The client opens the specified dialog. +/// Is sent by the server when: The durability of an item in the inventory of the player has been changed. +/// Causes reaction on client side: The client updates the item in the inventory user interface. /// -public readonly struct NpcWindowResponse +public readonly struct ItemDurabilityChanged { + private readonly Memory _data; + /// - /// Defines the kind of npc window which should be shown on the client. + /// Initializes a new instance of the struct. /// - public enum NpcWindow + /// The underlying data. + public ItemDurabilityChanged(Memory data) + : this(data, true) { - /// - /// A merchant window. - /// - Merchant = 0, + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ItemDurabilityChanged(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x2A; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 6; + + /// + /// Gets the header of this packet. + /// + public C1Header Header => new (this._data); + + /// + /// Gets or sets the inventory slot. + /// + public byte InventorySlot + { + get => this._data.Span[3]; + set => this._data.Span[3] = value; + } + + /// + /// Gets or sets the durability. + /// + public byte Durability + { + get => this._data.Span[4]; + set => this._data.Span[4] = value; + } + + /// + /// Gets or sets true, if the change resulted from an item consumption; otherwise, false + /// + public bool ByConsumption + { + get => this._data.Span[5..].GetBoolean(); + set => this._data.Span[5..].SetBoolean(value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ItemDurabilityChanged(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(ItemDurabilityChanged packet) => packet._data; +} + +/// +/// Is sent by the server when: The player requested to consume a fruit. +/// Causes reaction on client side: The client updates the user interface, by changing the added stat points and used fruit points. +/// +public readonly struct FruitConsumptionResponse +{ + /// + /// Defines the result of the fruit consumption request. + /// + public enum FruitConsumptionResult + { /// - /// Another merchant window. + /// Consumption to add points was successful. /// - Merchant1 = 1, + PlusSuccess = 0, /// - /// A vault storage. + /// Consumption to add points failed. /// - VaultStorage = 2, + PlusFailed = 1, /// - /// A chaos machine window. + /// Consumption to add points was prevented because some conditions were not correct. /// - ChaosMachine = 3, + PlusPrevented = 2, /// - /// A devil square window. + /// Consumption to remove points was successful. /// - DevilSquare = 4, + MinusSuccess = 3, /// - /// A blood castle window. + /// Consumption to remove points failed. /// - BloodCastle = 6, + MinusFailed = 4, /// - /// The pet trainer window. + /// Consumption to remove points was prevented because some conditions were not correct. /// - PetTrainer = 7, + MinusPrevented = 5, /// - /// The lahap window. + /// Consumption to remove points was successful, removed by a fruit acquired through the cash shop. /// - Lahap = 9, + MinusSuccessCashShopFruit = 6, /// - /// The castle senior window. + /// Consumption was prevented because an item was equipped. /// - CastleSeniorNPC = 12, + PreventedByEquippedItems = 16, /// - /// The elphis refinery window. + /// Consumption to add points was prevented because the maximum amount of points have been added. /// - ElphisRefinery = 17, + PlusPreventedByMaximum = 33, /// - /// The refine stone making window. + /// Consumption to remove points was prevented because the maximum amount of points have been removed. /// - RefineStoneMaking = 18, + MinusPreventedByMaximum = 37, /// - /// The jewel of harmony option removal window. + /// Consumption to remove points was prevented because the base amount of stat points of the character class cannot be undercut. /// - RemoveJohOption = 19, + MinusPreventedByDefault = 38, + } + /// + /// Defines the type of stat which the fruit modifies. + /// + public enum FruitStatType + { /// - /// The illusion temple window. + /// Fruit which modifies the energy stat. /// - IllusionTemple = 20, + Energy = 0, /// - /// The chaos card combination window. + /// Fruit which modifies the vitality stat. /// - ChaosCardCombination = 21, + Vitality = 1, /// - /// The cherry blossom branches assembly window. + /// Fruit which modifies the agility stat. /// - CherryBlossomBranchesAssembly = 22, + Agility = 2, /// - /// The seed master window. + /// Fruit which modifies the strength stat. /// - SeedMaster = 23, + Strength = 3, /// - /// The seed researcher window. + /// Fruit which modifies the leadership stat. /// - SeedResearcher = 24, + Leadership = 4, + } + + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public FruitConsumptionResponse(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private FruitConsumptionResponse(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x2C; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 7; + + /// + /// Gets the header of this packet. + /// + public C1Header Header => new (this._data); + + /// + /// Gets or sets the result. + /// + public FruitConsumptionResponse.FruitConsumptionResult Result + { + get => (FruitConsumptionResult)this._data.Span[3]; + set => this._data.Span[3] = (byte)value; + } + + /// + /// Gets or sets the stat points. + /// + public ushort StatPoints + { + get => ReadUInt16LittleEndian(this._data.Span[4..]); + set => WriteUInt16LittleEndian(this._data.Span[4..], value); + } + + /// + /// Gets or sets the stat type. + /// + public FruitConsumptionResponse.FruitStatType StatType + { + get => (FruitStatType)this._data.Span[6]; + set => this._data.Span[6] = (byte)value; + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator FruitConsumptionResponse(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(FruitConsumptionResponse packet) => packet._data; +} + + +/// +/// Is sent by the server when: The player requested to consume an item which gives a magic effect. +/// Causes reaction on client side: The client updates the user interface, it shows the remaining time at the effect icon. +/// +public readonly struct EffectItemConsumption +{ + /// + /// Defines the origin of the effect. + /// + public enum EffectOrigin + { + /// + /// Not defined. + /// + Undefined = 0, /// - /// The stat reinitializer window. + /// Options of Halloween and Cherry Blossom Event items. /// - StatReInitializer = 25, + HalloweenAndCherryBlossomEvent = 1, /// - /// The delgado lucky coin registration window. + /// Options of cash shop items, like Seals. /// - DelgadoLuckyCoinRegistration = 32, + CashShopItem = 2, + } + /// + /// Defines the effect option. + /// + public enum EffectAction + { /// - /// The doorkeeper titus duel watch window. + /// Effect is added. /// - DoorkeeperTitusDuelWatch = 33, + Add = 0, /// - /// The lugard doppelganger entry window. + /// Effect is removed. /// - LugardDoppelgangerEntry = 35, + Remove = 1, /// - /// The jerint gaion event entry window. + /// Effect is removed, because its getting replaced. /// - JerintGaionEvententry = 36, + Replace = 2, + } + + /// + /// Defines the kind of effect which was applied. + /// + public enum EffectType + { + /// + /// Attack speed increase. + /// + AttackSpeed = 1, + + /// + /// Damage increase. + /// + Damage = 2, + + /// + /// Defense increase. + /// + Defense = 3, + + /// + /// Maximum Health increase. + /// + MaximumHealth = 4, + + /// + /// Maximum Mana increase. + /// + MaximumMana = 5, + + /// + /// Experience rate increase. + /// + ExperienceRate = 6, + + /// + /// Drop rate increase. + /// + DropRate = 7, + + /// + /// Sustenance effect, means no experience is gained during this effect. + /// + Sustenance = 8, + + /// + /// Strength stat increase. + /// + Strength = 9, + + /// + /// Agility stat increase. + /// + Agility = 10, + + /// + /// Vitality stat increase. + /// + Vitality = 11, + + /// + /// Energy stat increase. + /// + Energy = 12, + + /// + /// Leadership stat increase. + /// + Leadership = 13, + + /// + /// Physical damage increase. + /// + PhysicalDamage = 14, + + /// + /// Wizardry damage increase. + /// + WizardryDamage = 15, + + /// + /// Mobility increase. + /// + Mobility = 16, + } + + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public EffectItemConsumption(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private EffectItemConsumption(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x2D; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 17; + + /// + /// Gets the header of this packet. + /// + public C1Header Header => new (this._data); + + /// + /// Gets or sets the origin. + /// + public EffectItemConsumption.EffectOrigin Origin + { + get => (EffectOrigin)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; + } + + /// + /// Gets or sets the type. + /// + public EffectItemConsumption.EffectType Type + { + get => (EffectType)this._data.Span[6]; + set => this._data.Span[6] = (byte)value; + } + + /// + /// Gets or sets the action. + /// + public EffectItemConsumption.EffectAction Action + { + get => (EffectAction)this._data.Span[8]; + set => this._data.Span[8] = (byte)value; + } + + /// + /// Gets or sets the remaining seconds. + /// + public uint RemainingSeconds + { + get => ReadUInt32LittleEndian(this._data.Span[12..]); + set => WriteUInt32LittleEndian(this._data.Span[12..], value); + } + + /// + /// Gets or sets the magic effect number. + /// + public byte MagicEffectNumber + { + get => this._data.Span[16]; + set => this._data.Span[16] = value; + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator EffectItemConsumption(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(EffectItemConsumption packet) => packet._data; +} + + +/// +/// Is sent by the server when: After the client talked to an NPC which should cause a dialog to open on the client side. +/// Causes reaction on client side: The client opens the specified dialog. +/// +public readonly struct NpcWindowResponse +{ + /// + /// Defines the kind of npc window which should be shown on the client. + /// + public enum NpcWindow + { + /// + /// A merchant window. + /// + Merchant = 0, + + /// + /// Another merchant window. + /// + Merchant1 = 1, + + /// + /// A vault storage. + /// + VaultStorage = 2, + + /// + /// A chaos machine window. + /// + ChaosMachine = 3, + + /// + /// A devil square window. + /// + DevilSquare = 4, + + /// + /// A blood castle window. + /// + BloodCastle = 6, + + /// + /// The pet trainer window. + /// + PetTrainer = 7, + + /// + /// The lahap window. + /// + Lahap = 9, + + /// + /// The castle senior window. + /// + CastleSeniorNPC = 12, + + /// + /// The elphis refinery window. + /// + ElphisRefinery = 17, + + /// + /// The refine stone making window. + /// + RefineStoneMaking = 18, + + /// + /// The jewel of harmony option removal window. + /// + RemoveJohOption = 19, + + /// + /// The illusion temple window. + /// + IllusionTemple = 20, + + /// + /// The chaos card combination window. + /// + ChaosCardCombination = 21, + + /// + /// The cherry blossom branches assembly window. + /// + CherryBlossomBranchesAssembly = 22, + + /// + /// The seed master window. + /// + SeedMaster = 23, + + /// + /// The seed researcher window. + /// + SeedResearcher = 24, + + /// + /// The stat reinitializer window. + /// + StatReInitializer = 25, + + /// + /// The delgado lucky coin registration window. + /// + DelgadoLuckyCoinRegistration = 32, + + /// + /// The doorkeeper titus duel watch window. + /// + DoorkeeperTitusDuelWatch = 33, + + /// + /// The lugard doppelganger entry window. + /// + LugardDoppelgangerEntry = 35, + + /// + /// The jerint gaion event entry window. + /// + JerintGaionEvententry = 36, + + /// + /// The julia warp market server window. + /// + JuliaWarpMarketServer = 37, + + /// + /// The dialog window which allows to exchange or refine Lucky Item. Used by NPC "David". + /// + CombineLuckyItem = 38, + } + + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public NpcWindowResponse(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private NpcWindowResponse(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC3; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x30; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 11; + + /// + /// Gets the header of this packet. + /// + public C3Header Header => new (this._data); + + /// + /// Gets or sets the window. + /// + public NpcWindowResponse.NpcWindow Window + { + get => (NpcWindow)this._data.Span[3]; + set => this._data.Span[3] = (byte)value; + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator NpcWindowResponse(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(NpcWindowResponse packet) => packet._data; +} + + +/// +/// Is sent by the server when: The player opens a merchant npc or the vault. It's sent after the dialog was opened by another message. +/// Causes reaction on client side: The client shows the items in the opened dialog. +/// +public readonly struct StoreItemList +{ + /// + /// Defines the kind of npc window which should be shown on the client. + /// + public enum ItemWindow + { + /// + /// A normal window. + /// + Normal = 0, + + /// + /// A chaos machine window. + /// + ChaosMachine = 3, + + /// + /// A failed resurrection (of Dark Horse or Dark Raven) storage dialog. + /// + ResurrectionFailed = 5, + } + + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public StoreItemList(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private StoreItemList(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (ushort)data.Length; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC2; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x31; + + /// + /// Gets the header of this packet. + /// + public C2Header Header => new (this._data); + + /// + /// Gets or sets the type. + /// + public StoreItemList.ItemWindow Type + { + get => (ItemWindow)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; + } + + /// + /// Gets or sets the item count. + /// + public byte ItemCount + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } + + /// + /// Gets the of the specified index. + /// + public StoredItem this[int index, int storedItemLength] => new (this._data.Slice(6 + index * storedItemLength)); + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator StoreItemList(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(StoreItemList packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of and it's size. + /// + /// The count of from which the size will be calculated. + /// The length of from which the size will be calculated. + + public static int GetRequiredSize(int itemsCount, int structLength) => itemsCount * structLength + 6; +} + + +/// +/// Is sent by the server when: The request of buying an item from a NPC failed. +/// Causes reaction on client side: The client is responsive again. Without this message, it may stuck. +/// +public readonly struct NpcItemBuyFailed +{ + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public NpcItemBuyFailed(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private NpcItemBuyFailed(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x32; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0xFF; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 4; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCode Header => new (this._data); + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator NpcItemBuyFailed(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(NpcItemBuyFailed packet) => packet._data; +} + + +/// +/// Is sent by the server when: The request of buying an item from a player or npc was successful. +/// Causes reaction on client side: The bought item is added to the inventory. +/// +public readonly struct ItemBought +{ + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public ItemBought(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ItemBought(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)data.Length; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x32; + + /// + /// Gets the header of this packet. + /// + public C1Header Header => new (this._data); + + /// + /// Gets or sets the inventory slot. + /// + public byte InventorySlot + { + get => this._data.Span[3]; + set => this._data.Span[3] = value; + } + + /// + /// Gets or sets the item data. + /// + public Span ItemData + { + get => this._data.Slice(4).Span; + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ItemBought(Memory packet) => new (packet, false); - /// - /// The julia warp market server window. - /// - JuliaWarpMarketServer = 37, + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(ItemBought packet) => packet._data; - /// - /// The dialog window which allows to exchange or refine Lucky Item. Used by NPC "David". - /// - CombineLuckyItem = 38, - } + /// + /// Calculates the size of the packet for the specified length of . + /// + /// The length in bytes of on which the required size depends. + + public static int GetRequiredSize(int itemDataLength) => itemDataLength + 4; +} + +/// +/// Is sent by the server when: The result of a previous item sell request. +/// Causes reaction on client side: The amount of specified money is set at the players inventory. +/// +public readonly struct NpcItemSellResult +{ private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public NpcWindowResponse(Memory data) + public NpcItemSellResult(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private NpcWindowResponse(Memory data, bool initialize) + private NpcItemSellResult(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9280,12 +10341,12 @@ private NpcWindowResponse(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x30; + public static byte Code => 0x33; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 11; + public static int Length => 8; /// /// Gets the header of this packet. @@ -9293,74 +10354,103 @@ private NpcWindowResponse(Memory data, bool initialize) public C3Header Header => new (this._data); /// - /// Gets or sets the window. + /// Gets or sets the success. /// - public NpcWindowResponse.NpcWindow Window + public bool Success { - get => (NpcWindow)this._data.Span[3]; - set => this._data.Span[3] = (byte)value; + get => this._data.Span[3..].GetBoolean(); + set => this._data.Span[3..].SetBoolean(value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the money. + /// + public uint Money + { + get => ReadUInt32LittleEndian(this._data.Span[4..]); + set => WriteUInt32LittleEndian(this._data.Span[4..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator NpcWindowResponse(Memory packet) => new (packet, false); + public static implicit operator NpcItemSellResult(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(NpcWindowResponse packet) => packet._data; + public static implicit operator Memory(NpcItemSellResult packet) => packet._data; } /// -/// Is sent by the server when: The player opens a merchant npc or the vault. It's sent after the dialog was opened by another message. -/// Causes reaction on client side: The client shows the items in the opened dialog. +/// Is sent by the server when: The player requested to set a price for an item of the players shop. +/// Causes reaction on client side: The item gets a price on the user interface. /// -public readonly struct StoreItemList +public readonly struct PlayerShopSetItemPriceResponse { /// - /// Defines the kind of npc window which should be shown on the client. + /// Describes the possible results of setting an item price in a player shop. /// - public enum ItemWindow + public enum ItemPriceSetResult { /// - /// A normal window. + /// Failed, e.g. because the shop feature is deactivated /// - Normal = 0, + Failed = 0, /// - /// A chaos machine window. + /// The price has been set successfully /// - ChaosMachine = 3, + Success = 1, /// - /// A failed resurrection (of Dark Horse or Dark Raven) storage dialog. + /// Failed because the item slot was out of range /// - ResurrectionFailed = 5, + ItemSlotOutOfRange = 2, + + /// + /// Failed because the item could not be found + /// + ItemNotFound = 3, + + /// + /// Failed because the price was negative + /// + PriceNegative = 4, + + /// + /// Failed because the item is blocked + /// + ItemIsBlocked = 5, + + /// + /// Failed because the character level is too low (below level 6) + /// + CharacterLevelTooLow = 6, } private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public StoreItemList(Memory data) + public PlayerShopSetItemPriceResponse(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private StoreItemList(Memory data, bool initialize) + private PlayerShopSetItemPriceResponse(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9368,95 +10458,94 @@ private StoreItemList(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC3; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x31; + public static byte Code => 0x3F; /// - /// Gets the header of this packet. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public C2Header Header => new (this._data); + public static byte SubCode => 0x01; /// - /// Gets or sets the type. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public StoreItemList.ItemWindow Type - { - get => (ItemWindow)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; - } + public static int Length => 6; /// - /// Gets or sets the item count. + /// Gets the header of this packet. /// - public byte ItemCount + public C3HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets the inventory slot. + /// + public byte InventorySlot { get => this._data.Span[5]; set => this._data.Span[5] = value; } /// - /// Gets the of the specified index. + /// Gets or sets the result. /// - public StoredItem this[int index, int storedItemLength] => new (this._data.Slice(6 + index * storedItemLength)); + public PlayerShopSetItemPriceResponse.ItemPriceSetResult Result + { + get => (ItemPriceSetResult)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; + } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator StoreItemList(Memory packet) => new (packet, false); + public static implicit operator PlayerShopSetItemPriceResponse(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(StoreItemList packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified count of and it's size. - /// - /// The count of from which the size will be calculated. - /// The length of from which the size will be calculated. - - public static int GetRequiredSize(int itemsCount, int structLength) => itemsCount * structLength + 6; + public static implicit operator Memory(PlayerShopSetItemPriceResponse packet) => packet._data; } /// -/// Is sent by the server when: The request of buying an item from a NPC failed. -/// Causes reaction on client side: The client is responsive again. Without this message, it may stuck. +/// Is sent by the server when: After a player in scope requested to close his shop or after all items has been sold. +/// Causes reaction on client side: The player shop not shown as open anymore. /// -public readonly struct NpcItemBuyFailed +public readonly struct PlayerShopClosed { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public NpcItemBuyFailed(Memory data) + public PlayerShopClosed(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private NpcItemBuyFailed(Memory data, bool initialize) + private PlayerShopClosed(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9466,6 +10555,7 @@ private NpcItemBuyFailed(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Success = true; } } @@ -9477,18 +10567,18 @@ private NpcItemBuyFailed(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x32; + public static byte Code => 0x3F; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFF; + public static byte SubCode => 0x3; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 4; + public static int Length => 7; /// /// Gets the header of this packet. @@ -9496,44 +10586,62 @@ private NpcItemBuyFailed(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the success. + /// + public bool Success + { + get => this._data.Span[4..].GetBoolean(); + set => this._data.Span[4..].SetBoolean(value); + } + + /// + /// Gets or sets the player id. + /// + public ushort PlayerId + { + get => ReadUInt16BigEndian(this._data.Span[5..]); + set => WriteUInt16BigEndian(this._data.Span[5..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator NpcItemBuyFailed(Memory packet) => new (packet, false); + public static implicit operator PlayerShopClosed(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(NpcItemBuyFailed packet) => packet._data; + public static implicit operator Memory(PlayerShopClosed packet) => packet._data; } /// -/// Is sent by the server when: The request of buying an item from a player or npc was successful. -/// Causes reaction on client side: The bought item is added to the inventory. +/// Is sent by the server when: An item of the players shop was sold to another player. +/// Causes reaction on client side: The item is removed from the players inventory and a blue system message appears. /// -public readonly struct ItemBought +public readonly struct PlayerShopItemSoldToPlayer { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemBought(Memory data) + public PlayerShopItemSoldToPlayer(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemBought(Memory data, bool initialize) + private PlayerShopItemSoldToPlayer(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9541,7 +10649,8 @@ private ItemBought(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } @@ -9553,76 +10662,81 @@ private ItemBought(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x32; + public static byte Code => 0x3F; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x08; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 15; /// /// Gets the header of this packet. /// - public C1Header Header => new (this._data); + public C1HeaderWithSubCode Header => new (this._data); /// /// Gets or sets the inventory slot. /// public byte InventorySlot { - get => this._data.Span[3]; - set => this._data.Span[3] = value; + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Gets or sets the item data. + /// Gets or sets the buyer name. /// - public Span ItemData + public string BuyerName { - get => this._data.Slice(4).Span; + get => this._data.Span.ExtractString(5, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(5, 10).Span.WriteString(value, System.Text.Encoding.UTF8); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemBought(Memory packet) => new (packet, false); + public static implicit operator PlayerShopItemSoldToPlayer(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(ItemBought packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified length of . - /// - /// The length in bytes of on which the required size depends. - - public static int GetRequiredSize(int itemDataLength) => itemDataLength + 4; + public static implicit operator Memory(PlayerShopItemSoldToPlayer packet) => packet._data; } /// -/// Is sent by the server when: The result of a previous item sell request. -/// Causes reaction on client side: The amount of specified money is set at the players inventory. +/// Is sent by the server when: After the player requested to close his shop or after all items has been sold. +/// Causes reaction on client side: The player shop dialog is closed for the shop of the specified player. /// -public readonly struct NpcItemSellResult +public readonly struct ClosePlayerShopDialog { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public NpcItemSellResult(Memory data) + public ClosePlayerShopDialog(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private NpcItemSellResult(Memory data, bool initialize) + private ClosePlayerShopDialog(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9631,127 +10745,100 @@ private NpcItemSellResult(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC3; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x33; + public static byte Code => 0x3F; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public static int Length => 8; + public static byte SubCode => 0x12; /// - /// Gets the header of this packet. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public C3Header Header => new (this._data); + public static int Length => 6; /// - /// Gets or sets the success. + /// Gets the header of this packet. /// - public bool Success - { - get => this._data.Span[3..].GetBoolean(); - set => this._data.Span[3..].SetBoolean(value); - } + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the money. + /// Gets or sets the player id. /// - public uint Money + public ushort PlayerId { - get => ReadUInt32LittleEndian(this._data.Span[4..]); - set => WriteUInt32LittleEndian(this._data.Span[4..], value); + get => ReadUInt16BigEndian(this._data.Span[4..]); + set => WriteUInt16BigEndian(this._data.Span[4..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator NpcItemSellResult(Memory packet) => new (packet, false); + public static implicit operator ClosePlayerShopDialog(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(NpcItemSellResult packet) => packet._data; + public static implicit operator Memory(ClosePlayerShopDialog packet) => packet._data; } /// -/// Is sent by the server when: The player requested to set a price for an item of the players shop. -/// Causes reaction on client side: The item gets a price on the user interface. +/// Is sent by the server when: After the player requested to open a shop of another player. +/// Causes reaction on client side: The player shop dialog is shown with the provided item data. /// -public readonly struct PlayerShopSetItemPriceResponse +public readonly struct PlayerShopItemList { /// - /// Describes the possible results of setting an item price in a player shop. + /// The kind of action which led to the list message. /// - public enum ItemPriceSetResult + public enum ActionKind { /// - /// Failed, e.g. because the shop feature is deactivated - /// - Failed = 0, - - /// - /// The price has been set successfully - /// - Success = 1, - - /// - /// Failed because the item slot was out of range - /// - ItemSlotOutOfRange = 2, - - /// - /// Failed because the item could not be found - /// - ItemNotFound = 3, - - /// - /// Failed because the price was negative - /// - PriceNegative = 4, - - /// - /// Failed because the item is blocked + /// The list was requested. /// - ItemIsBlocked = 5, + ByRequest = 5, /// - /// Failed because the character level is too low (below level 6) + /// The list was changed, e.g. because an item was sold. /// - CharacterLevelTooLow = 6, + UpdateAfterItemChange = 19, } private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopSetItemPriceResponse(Memory data) + public PlayerShopItemList(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopSetItemPriceResponse(Memory data, bool initialize) + private PlayerShopItemList(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9759,15 +10846,16 @@ private PlayerShopSetItemPriceResponse(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); + header.Length = (ushort)data.Length; header.SubCode = SubCode; + this.Success = true; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC3; + public static byte HeaderType => 0xC2; /// /// Gets the operation code of this data packet. @@ -9778,75 +10866,118 @@ private PlayerShopSetItemPriceResponse(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x01; + public static byte SubCode => 0x05; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the header of this packet. /// - public static int Length => 6; + public C2HeaderWithSubCode Header => new (this._data); /// - /// Gets the header of this packet. + /// Gets or sets the action. /// - public C3HeaderWithSubCode Header => new (this._data); + public PlayerShopItemList.ActionKind Action + { + get => (ActionKind)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; + } /// - /// Gets or sets the inventory slot. + /// Gets or sets the success. /// - public byte InventorySlot + public bool Success { - get => this._data.Span[5]; - set => this._data.Span[5] = value; + get => this._data.Span[5..].GetBoolean(); + set => this._data.Span[5..].SetBoolean(value); } /// - /// Gets or sets the result. + /// Gets or sets the player id. /// - public PlayerShopSetItemPriceResponse.ItemPriceSetResult Result + public ushort PlayerId { - get => (ItemPriceSetResult)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; + get => ReadUInt16BigEndian(this._data.Span[6..]); + set => WriteUInt16BigEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the player name. + /// + public string PlayerName + { + get => this._data.Span.ExtractString(8, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(8, 10).Span.WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Gets or sets the shop name. + /// + public string ShopName + { + get => this._data.Span.ExtractString(18, 36, System.Text.Encoding.UTF8); + set => this._data.Slice(18, 36).Span.WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Gets or sets the item count. + /// + public byte ItemCount + { + get => this._data.Span[54]; + set => this._data.Span[54] = value; + } + + /// + /// Gets the of the specified index. + /// + public PlayerShopItem this[int index] => new (this._data.Slice(55 + index * PlayerShopItem.Length)); + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayerShopSetItemPriceResponse(Memory packet) => new (packet, false); + public static implicit operator PlayerShopItemList(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(PlayerShopSetItemPriceResponse packet) => packet._data; + public static implicit operator Memory(PlayerShopItemList packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of . + /// + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int itemsCount) => itemsCount * PlayerShopItem.Length + 55; } /// -/// Is sent by the server when: After a player in scope requested to close his shop or after all items has been sold. -/// Causes reaction on client side: The player shop not shown as open anymore. +/// Is sent by the server when: After the player gets into scope of a player with an opened shop. +/// Causes reaction on client side: The player shop title is shown at the specified players. /// -public readonly struct PlayerShopClosed +public readonly struct PlayerShops { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopClosed(Memory data) + public PlayerShops(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopClosed(Memory data, bool initialize) + private PlayerShops(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9854,16 +10985,15 @@ private PlayerShopClosed(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); + header.Length = (ushort)data.Length; header.SubCode = SubCode; - this.Success = true; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC1; + public static byte HeaderType => 0xC2; /// /// Gets the operation code of this data packet. @@ -9874,75 +11004,114 @@ private PlayerShopClosed(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x3; + public static byte SubCode => 0x00; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the header of this packet. /// - public static int Length => 7; + public C2HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets the shop count. + /// + public byte ShopCount + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } + + /// + /// Gets the of the specified index. + /// + public PlayerShop this[int index] => new (this._data.Slice(6 + index * PlayerShop.Length)); + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator PlayerShops(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(PlayerShops packet) => packet._data; /// - /// Gets the header of this packet. + /// Calculates the size of the packet for the specified count of . /// - public C1HeaderWithSubCode Header => new (this._data); + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int shopsCount) => shopsCount * PlayerShop.Length + 6; + + +/// +/// Data of the shop of a player.. +/// +public readonly struct PlayerShop +{ + private readonly Memory _data; /// - /// Gets or sets the success. + /// Initializes a new instance of the struct. /// - public bool Success + /// The underlying data. + public PlayerShop(Memory data) { - get => this._data.Span[4..].GetBoolean(); - set => this._data.Span[4..].SetBoolean(value); + this._data = data; } + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 38; + /// /// Gets or sets the player id. /// public ushort PlayerId { - get => ReadUInt16BigEndian(this._data.Span[5..]); - set => WriteUInt16BigEndian(this._data.Span[5..], value); + get => ReadUInt16BigEndian(this._data.Span); + set => WriteUInt16BigEndian(this._data.Span, value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator PlayerShopClosed(Memory packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the store name. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(PlayerShopClosed packet) => packet._data; + public string StoreName + { + get => this._data.Span.ExtractString(2, 36, System.Text.Encoding.UTF8); + set => this._data.Slice(2, 36).Span.WriteString(value, System.Text.Encoding.UTF8); + } +} } /// -/// Is sent by the server when: An item of the players shop was sold to another player. -/// Causes reaction on client side: The item is removed from the players inventory and a blue system message appears. +/// Is sent by the server when: The player wears a monster transformation ring. +/// Causes reaction on client side: The character appears as monster, defined by the Skin property. /// -public readonly struct PlayerShopItemSoldToPlayer +public readonly struct AddTransformedCharactersToScope075 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopItemSoldToPlayer(Memory data) + public AddTransformedCharactersToScope075(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopItemSoldToPlayer(Memory data, bool initialize) + private AddTransformedCharactersToScope075(Memory data, bool initialize) { this._data = data; if (initialize) @@ -9950,196 +11119,225 @@ private PlayerShopItemSoldToPlayer(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; + header.Length = (ushort)data.Length; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC1; + public static byte HeaderType => 0xC2; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x3F; - - /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. - /// - public static byte SubCode => 0x08; - - /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. - /// - public static int Length => 15; + public static byte Code => 0x45; /// /// Gets the header of this packet. /// - public C1HeaderWithSubCode Header => new (this._data); + public C2Header Header => new (this._data); /// - /// Gets or sets the inventory slot. + /// Gets or sets the character count. /// - public byte InventorySlot + public byte CharacterCount { get => this._data.Span[4]; set => this._data.Span[4] = value; } /// - /// Gets or sets the buyer name. + /// Gets the of the specified index. /// - public string BuyerName - { - get => this._data.Span.ExtractString(5, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(5, 10).Span.WriteString(value, System.Text.Encoding.UTF8); - } + public CharacterData this[int index] => new (this._data.Slice(5 + index * CharacterData.Length)); /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayerShopItemSoldToPlayer(Memory packet) => new (packet, false); + public static implicit operator AddTransformedCharactersToScope075(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(PlayerShopItemSoldToPlayer packet) => packet._data; -} + public static implicit operator Memory(AddTransformedCharactersToScope075 packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of . + /// + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 5; /// -/// Is sent by the server when: After the player requested to close his shop or after all items has been sold. -/// Causes reaction on client side: The player shop dialog is closed for the shop of the specified player. +/// Contains the data of an transformed character.. /// -public readonly struct ClosePlayerShopDialog +public readonly struct CharacterData { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ClosePlayerShopDialog(Memory data) - : this(data, true) + public CharacterData(Memory data) { + this._data = data; } /// - /// Initializes a new instance of the struct. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private ClosePlayerShopDialog(Memory data, bool initialize) + public static int Length => 19; + + /// + /// Gets or sets the id. + /// + public ushort Id { - this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; - } + get => ReadUInt16BigEndian(this._data.Span); + set => WriteUInt16BigEndian(this._data.Span, value); } /// - /// Gets the header type of this data packet. + /// Gets or sets the current position x. /// - public static byte HeaderType => 0xC1; + public byte CurrentPositionX + { + get => this._data.Span[2]; + set => this._data.Span[2] = value; + } /// - /// Gets the operation code of this data packet. + /// Gets or sets the current position y. /// - public static byte Code => 0x3F; + public byte CurrentPositionY + { + get => this._data.Span[3]; + set => this._data.Span[3] = value; + } /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets or sets the skin. /// - public static byte SubCode => 0x12; + public byte Skin + { + get => this._data.Span[4]; + set => this._data.Span[4] = value; + } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the is poisoned. /// - public static int Length => 6; + public bool IsPoisoned + { + get => this._data.Span[5..].GetBoolean(0); + set => this._data.Span[5..].SetBoolean(value, 0); + } /// - /// Gets the header of this packet. + /// Gets or sets the is iced. /// - public C1HeaderWithSubCode Header => new (this._data); + public bool IsIced + { + get => this._data.Span[5..].GetBoolean(1); + set => this._data.Span[5..].SetBoolean(value, 1); + } /// - /// Gets or sets the player id. + /// Gets or sets the is damage buffed. /// - public ushort PlayerId + public bool IsDamageBuffed { - get => ReadUInt16BigEndian(this._data.Span[4..]); - set => WriteUInt16BigEndian(this._data.Span[4..], value); + get => this._data.Span[5..].GetBoolean(2); + set => this._data.Span[5..].SetBoolean(value, 2); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the is defense buffed. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator ClosePlayerShopDialog(Memory packet) => new (packet, false); + public bool IsDefenseBuffed + { + get => this._data.Span[5..].GetBoolean(3); + set => this._data.Span[5..].SetBoolean(value, 3); + } /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the name. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(ClosePlayerShopDialog packet) => packet._data; -} + public string Name + { + get => this._data.Span.ExtractString(6, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(6, 10).Span.WriteString(value, System.Text.Encoding.UTF8); + } + /// + /// Gets or sets the target position x. + /// + public byte TargetPositionX + { + get => this._data.Span[16]; + set => this._data.Span[16] = value; + } -/// -/// Is sent by the server when: After the player requested to open a shop of another player. -/// Causes reaction on client side: The player shop dialog is shown with the provided item data. -/// -public readonly struct PlayerShopItemList -{ /// - /// The kind of action which led to the list message. + /// Gets or sets the target position y. /// - public enum ActionKind + public byte TargetPositionY { - /// - /// The list was requested. - /// - ByRequest = 5, + get => this._data.Span[17]; + set => this._data.Span[17] = value; + } - /// - /// The list was changed, e.g. because an item was sold. - /// - UpdateAfterItemChange = 19, + /// + /// Gets or sets the rotation. + /// + public byte Rotation + { + get => this._data.Span[18..].GetByteValue(4, 4); + set => this._data.Span[18..].SetByteValue(value, 4, 4); + } + + /// + /// Gets or sets the hero state. + /// + public CharacterHeroState HeroState + { + get => (CharacterHeroState)this._data.Span[18..].GetByteValue(4, 0); + set => this._data.Span[18..].SetByteValue((byte)value, 4, 0); } +} +} + +/// +/// Is sent by the server when: The player wears a monster transformation ring. +/// Causes reaction on client side: The character appears as monster, defined by the Skin property. +/// +public readonly partial struct AddTransformedCharactersToScope +{ private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopItemList(Memory data) + public AddTransformedCharactersToScope(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopItemList(Memory data, bool initialize) + private AddTransformedCharactersToScope(Memory data, bool initialize) { this._data = data; if (initialize) @@ -10148,8 +11346,6 @@ private PlayerShopItemList(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (ushort)data.Length; - header.SubCode = SubCode; - this.Success = true; } } @@ -10161,205 +11357,185 @@ private PlayerShopItemList(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x3F; - - /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. - /// - public static byte SubCode => 0x05; + public static byte Code => 0x45; /// /// Gets the header of this packet. /// - public C2HeaderWithSubCode Header => new (this._data); + public C2Header Header => new (this._data); /// - /// Gets or sets the action. + /// Gets or sets the character count. /// - public PlayerShopItemList.ActionKind Action + public byte CharacterCount { - get => (ActionKind)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Gets or sets the success. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public bool Success - { - get => this._data.Span[5..].GetBoolean(); - set => this._data.Span[5..].SetBoolean(value); - } + /// The packet as span. + /// The packet as struct. + public static implicit operator AddTransformedCharactersToScope(Memory packet) => new (packet, false); /// - /// Gets or sets the player id. + /// Performs an implicit conversion from to a Memory of bytes. /// - public ushort PlayerId - { - get => ReadUInt16BigEndian(this._data.Span[6..]); - set => WriteUInt16BigEndian(this._data.Span[6..], value); - } + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(AddTransformedCharactersToScope packet) => packet._data; /// - /// Gets or sets the player name. + /// Calculates the size of the packet for the specified count of and it's size. /// - public string PlayerName - { - get => this._data.Span.ExtractString(8, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(8, 10).Span.WriteString(value, System.Text.Encoding.UTF8); - } + /// The count of from which the size will be calculated. + /// The length of from which the size will be calculated. + + public static int GetRequiredSize(int charactersCount, int structLength) => charactersCount * structLength + 5; + + +/// +/// Contains the data of an transformed character.. +/// +public readonly struct CharacterData +{ + private readonly Memory _data; /// - /// Gets or sets the shop name. + /// Initializes a new instance of the struct. /// - public string ShopName + /// The underlying data. + public CharacterData(Memory data) { - get => this._data.Span.ExtractString(18, 36, System.Text.Encoding.UTF8); - set => this._data.Slice(18, 36).Span.WriteString(value, System.Text.Encoding.UTF8); + this._data = data; } /// - /// Gets or sets the item count. + /// Gets or sets the id. /// - public byte ItemCount + public ushort Id { - get => this._data.Span[54]; - set => this._data.Span[54] = value; + get => ReadUInt16BigEndian(this._data.Span); + set => WriteUInt16BigEndian(this._data.Span, value); } /// - /// Gets the of the specified index. - /// - public PlayerShopItem this[int index] => new (this._data.Slice(55 + index * PlayerShopItem.Length)); - - /// - /// Performs an implicit conversion from a Memory of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator PlayerShopItemList(Memory packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Memory of bytes. - /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(PlayerShopItemList packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified count of . + /// Gets or sets the current position x. /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int itemsCount) => itemsCount * PlayerShopItem.Length + 55; -} - - -/// -/// Is sent by the server when: After the player gets into scope of a player with an opened shop. -/// Causes reaction on client side: The player shop title is shown at the specified players. -/// -public readonly struct PlayerShops -{ - private readonly Memory _data; + public byte CurrentPositionX + { + get => this._data.Span[2]; + set => this._data.Span[2] = value; + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the current position y. /// - /// The underlying data. - public PlayerShops(Memory data) - : this(data, true) + public byte CurrentPositionY { + get => this._data.Span[3]; + set => this._data.Span[3] = value; } /// - /// Initializes a new instance of the struct. + /// Gets or sets the skin. /// - /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShops(Memory data, bool initialize) + public ushort Skin { - this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (ushort)data.Length; - header.SubCode = SubCode; - } + get => ReadUInt16BigEndian(this._data.Span[4..]); + set => WriteUInt16BigEndian(this._data.Span[4..], value); } /// - /// Gets the header type of this data packet. + /// Gets or sets the name. /// - public static byte HeaderType => 0xC2; + public string Name + { + get => this._data.Span.ExtractString(6, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(6, 10).Span.WriteString(value, System.Text.Encoding.UTF8); + } /// - /// Gets the operation code of this data packet. + /// Gets or sets the target position x. /// - public static byte Code => 0x3F; + public byte TargetPositionX + { + get => this._data.Span[16]; + set => this._data.Span[16] = value; + } /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets or sets the target position y. /// - public static byte SubCode => 0x00; + public byte TargetPositionY + { + get => this._data.Span[17]; + set => this._data.Span[17] = value; + } /// - /// Gets the header of this packet. + /// Gets or sets the rotation. /// - public C2HeaderWithSubCode Header => new (this._data); + public byte Rotation + { + get => this._data.Span[18..].GetByteValue(4, 4); + set => this._data.Span[18..].SetByteValue(value, 4, 4); + } /// - /// Gets or sets the shop count. + /// Gets or sets the hero state. /// - public byte ShopCount + public CharacterHeroState HeroState { - get => this._data.Span[5]; - set => this._data.Span[5] = value; + get => (CharacterHeroState)this._data.Span[18..].GetByteValue(4, 0); + set => this._data.Span[18..].SetByteValue((byte)value, 4, 0); } /// - /// Gets the of the specified index. + /// Gets or sets the appearance. /// - public PlayerShop this[int index] => new (this._data.Slice(6 + index * PlayerShop.Length)); + public Span Appearance + { + get => this._data.Slice(19, 18).Span; + } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets defines the number of effects which would be sent after this field. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator PlayerShops(Memory packet) => new (packet, false); + public byte EffectCount + { + get => this._data.Span[37]; + set => this._data.Span[37] = value; + } /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets the of the specified index. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(PlayerShops packet) => packet._data; + public EffectId this[int index] => new (this._data.Slice(38 + index * EffectId.Length)); /// - /// Calculates the size of the packet for the specified count of . + /// Calculates the size of the packet for the specified count of . /// - /// The count of from which the size will be calculated. + /// The count of from which the size will be calculated. - public static int GetRequiredSize(int shopsCount) => shopsCount * PlayerShop.Length + 6; + public static int GetRequiredSize(int effectsCount) => effectsCount * EffectId.Length + 38; +} /// -/// Data of the shop of a player.. +/// Contains the id of a magic effect.. /// -public readonly struct PlayerShop +public readonly struct EffectId { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShop(Memory data) + public EffectId(Memory data) { this._data = data; } @@ -10367,52 +11543,74 @@ public PlayerShop(Memory data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 38; - - /// - /// Gets or sets the player id. - /// - public ushort PlayerId - { - get => ReadUInt16BigEndian(this._data.Span); - set => WriteUInt16BigEndian(this._data.Span, value); - } + public static int Length => 1; /// - /// Gets or sets the store name. + /// Gets or sets the id. /// - public string StoreName + public byte Id { - get => this._data.Span.ExtractString(2, 36, System.Text.Encoding.UTF8); - set => this._data.Slice(2, 36).Span.WriteString(value, System.Text.Encoding.UTF8); + get => this._data.Span[0]; + set => this._data.Span[0] = value; } } } /// -/// Is sent by the server when: The player wears a monster transformation ring. -/// Causes reaction on client side: The character appears as monster, defined by the Skin property. +/// Is sent by the server when: The server wants to alter the terrain attributes of a map at runtime. +/// Causes reaction on client side: The client updates the terrain attributes on its side. /// -public readonly struct AddTransformedCharactersToScope075 +public readonly struct ChangeTerrainAttributes { + /// + /// Defines the attribute which should be set/unset. It's a Flags enumeration. + /// + public enum TerrainAttributeType + { + /// + /// The coordinate is a safezone. + /// + Safezone = 1, + + /// + /// The coordinate is occupied by a character. + /// + Character = 2, + + /// + /// The coordinate is blocked and can't be passed by a character. + /// + Blocked = 4, + + /// + /// The coordinate is blocked, because there is no ground and can't be passed by a character. + /// + NoGround = 8, + + /// + /// The coordinate is blocked by water and can't be passed by a character. + /// + Water = 16, + } + private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public AddTransformedCharactersToScope075(Memory data) + public ChangeTerrainAttributes(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private AddTransformedCharactersToScope075(Memory data, bool initialize) + private ChangeTerrainAttributes(Memory data, bool initialize) { this._data = data; if (initialize) @@ -10420,73 +11618,101 @@ private AddTransformedCharactersToScope075(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; + header.Length = (byte)data.Length; + this.Type = false; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x45; + public static byte Code => 0x46; /// /// Gets the header of this packet. /// - public C2Header Header => new (this._data); + public C1Header Header => new (this._data); /// - /// Gets or sets the character count. + /// Gets or sets the type. /// - public byte CharacterCount + public bool Type { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => this._data.Span[3..].GetBoolean(); + set => this._data.Span[3..].SetBoolean(value); } /// - /// Gets the of the specified index. + /// Gets or sets the attribute. /// - public CharacterData this[int index] => new (this._data.Slice(5 + index * CharacterData.Length)); + public ChangeTerrainAttributes.TerrainAttributeType Attribute + { + get => (TerrainAttributeType)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; + } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets when this is true, the attribute is removed on the client side. If it's false, then the attribute is added. + /// + public bool RemoveAttribute + { + get => this._data.Span[5..].GetBoolean(); + set => this._data.Span[5..].SetBoolean(value); + } + + /// + /// Gets or sets the area count. + /// + public byte AreaCount + { + get => this._data.Span[6]; + set => this._data.Span[6] = value; + } + + /// + /// Gets the of the specified index. + /// + public TerrainArea this[int index] => new (this._data.Slice(7 + index * TerrainArea.Length)); + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator AddTransformedCharactersToScope075(Memory packet) => new (packet, false); + public static implicit operator ChangeTerrainAttributes(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(AddTransformedCharactersToScope075 packet) => packet._data; + public static implicit operator Memory(ChangeTerrainAttributes packet) => packet._data; /// - /// Calculates the size of the packet for the specified count of . + /// Calculates the size of the packet for the specified count of . /// - /// The count of from which the size will be calculated. + /// The count of from which the size will be calculated. - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 5; + public static int GetRequiredSize(int areasCount) => areasCount * TerrainArea.Length + 7; /// -/// Contains the data of an transformed character.. +/// Defines the area which should be changed.. /// -public readonly struct CharacterData +public readonly struct TerrainArea { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterData(Memory data) + public TerrainArea(Memory data) { this._data = data; } @@ -10494,151 +11720,179 @@ public CharacterData(Memory data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 19; + public static int Length => 4; /// - /// Gets or sets the id. + /// Gets or sets the start x. /// - public ushort Id + public byte StartX { - get => ReadUInt16BigEndian(this._data.Span); - set => WriteUInt16BigEndian(this._data.Span, value); + get => this._data.Span[0]; + set => this._data.Span[0] = value; } /// - /// Gets or sets the current position x. + /// Gets or sets the start y. /// - public byte CurrentPositionX + public byte StartY + { + get => this._data.Span[1]; + set => this._data.Span[1] = value; + } + + /// + /// Gets or sets the end x. + /// + public byte EndX { get => this._data.Span[2]; set => this._data.Span[2] = value; } /// - /// Gets or sets the current position y. + /// Gets or sets the end y. /// - public byte CurrentPositionY + public byte EndY { get => this._data.Span[3]; set => this._data.Span[3] = value; } +} +} + +/// +/// Is sent by the server when: After a player achieved or lost something. +/// Causes reaction on client side: An effect is shown for the affected player. +/// +public readonly struct ShowEffect +{ /// - /// Gets or sets the skin. + /// Defines the effect which is shown for the player. /// - public byte Skin + public enum EffectType { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + /// + /// The player gained shield by drinking a potion. + /// + ShieldPotion = 3, + + /// + /// A level up effect is shown for the player. + /// + LevelUp = 16, + + /// + /// The players shield depleted. + /// + ShieldLost = 17, } + private readonly Memory _data; + /// - /// Gets or sets the is poisoned. + /// Initializes a new instance of the struct. /// - public bool IsPoisoned + /// The underlying data. + public ShowEffect(Memory data) + : this(data, true) { - get => this._data.Span[5..].GetBoolean(0); - set => this._data.Span[5..].SetBoolean(value, 0); } /// - /// Gets or sets the is iced. + /// Initializes a new instance of the struct. /// - public bool IsIced + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ShowEffect(Memory data, bool initialize) { - get => this._data.Span[5..].GetBoolean(1); - set => this._data.Span[5..].SetBoolean(value, 1); + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } } /// - /// Gets or sets the is damage buffed. + /// Gets the header type of this data packet. /// - public bool IsDamageBuffed - { - get => this._data.Span[5..].GetBoolean(2); - set => this._data.Span[5..].SetBoolean(value, 2); - } + public static byte HeaderType => 0xC1; /// - /// Gets or sets the is defense buffed. + /// Gets the operation code of this data packet. /// - public bool IsDefenseBuffed - { - get => this._data.Span[5..].GetBoolean(3); - set => this._data.Span[5..].SetBoolean(value, 3); - } + public static byte Code => 0x48; /// - /// Gets or sets the name. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public string Name - { - get => this._data.Span.ExtractString(6, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(6, 10).Span.WriteString(value, System.Text.Encoding.UTF8); - } + public static int Length => 6; /// - /// Gets or sets the target position x. + /// Gets the header of this packet. /// - public byte TargetPositionX - { - get => this._data.Span[16]; - set => this._data.Span[16] = value; - } + public C1Header Header => new (this._data); /// - /// Gets or sets the target position y. + /// Gets or sets the player id. /// - public byte TargetPositionY + public ushort PlayerId { - get => this._data.Span[17]; - set => this._data.Span[17] = value; + get => ReadUInt16BigEndian(this._data.Span[3..]); + set => WriteUInt16BigEndian(this._data.Span[3..], value); } /// - /// Gets or sets the rotation. + /// Gets or sets the effect. /// - public byte Rotation + public ShowEffect.EffectType Effect { - get => this._data.Span[18..].GetByteValue(4, 4); - set => this._data.Span[18..].SetByteValue(value, 4, 4); + get => (EffectType)this._data.Span[5]; + set => this._data.Span[5] = (byte)value; } /// - /// Gets or sets the hero state. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public CharacterHeroState HeroState - { - get => (CharacterHeroState)this._data.Span[18..].GetByteValue(4, 0); - set => this._data.Span[18..].SetByteValue((byte)value, 4, 0); - } -} + /// The packet as span. + /// The packet as struct. + public static implicit operator ShowEffect(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(ShowEffect packet) => packet._data; } /// -/// Is sent by the server when: The player wears a monster transformation ring. -/// Causes reaction on client side: The character appears as monster, defined by the Skin property. +/// Is sent by the server when: After the game client requested it, usually after a successful login. +/// Causes reaction on client side: The game client shows the available characters of the account. /// -public readonly partial struct AddTransformedCharactersToScope +public readonly struct CharacterList { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public AddTransformedCharactersToScope(Memory data) + public CharacterList(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private AddTransformedCharactersToScope(Memory data, bool initialize) + private CharacterList(Memory data, bool initialize) { this._data = data; if (initialize) @@ -10646,59 +11900,97 @@ private AddTransformedCharactersToScope(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; + header.Length = (byte)data.Length; + header.SubCode = SubCode; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x45; + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x00; /// /// Gets the header of this packet. /// - public C2Header Header => new (this._data); + public C1HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets the unlock flags. + /// + public CharacterCreationUnlockFlags UnlockFlags + { + get => (CharacterCreationUnlockFlags)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; + } + + /// + /// Gets or sets the move cnt. + /// + public byte MoveCnt + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } /// /// Gets or sets the character count. /// public byte CharacterCount { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => this._data.Span[6]; + set => this._data.Span[6] = value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the is vault extended. + /// + public bool IsVaultExtended + { + get => this._data.Span[7..].GetBoolean(); + set => this._data.Span[7..].SetBoolean(value); + } + + /// + /// Gets the of the specified index. + /// + public CharacterData this[int index] => new (this._data.Slice(8 + index * CharacterData.Length)); + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator AddTransformedCharactersToScope(Memory packet) => new (packet, false); + public static implicit operator CharacterList(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(AddTransformedCharactersToScope packet) => packet._data; + public static implicit operator Memory(CharacterList packet) => packet._data; /// - /// Calculates the size of the packet for the specified count of and it's size. + /// Calculates the size of the packet for the specified count of . /// /// The count of from which the size will be calculated. - /// The length of from which the size will be calculated. - - public static int GetRequiredSize(int charactersCount, int structLength) => charactersCount * structLength + 5; + + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 8; /// -/// Contains the data of an transformed character.. +/// Data of one character in the list.. /// public readonly struct CharacterData { @@ -10714,204 +12006,184 @@ public CharacterData(Memory data) } /// - /// Gets or sets the id. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public ushort Id - { - get => ReadUInt16BigEndian(this._data.Span); - set => WriteUInt16BigEndian(this._data.Span, value); - } + public static int Length => 34; /// - /// Gets or sets the current position x. + /// Gets or sets the slot index. /// - public byte CurrentPositionX + public byte SlotIndex { - get => this._data.Span[2]; - set => this._data.Span[2] = value; + get => this._data.Span[0]; + set => this._data.Span[0] = value; } /// - /// Gets or sets the current position y. + /// Gets or sets the name. /// - public byte CurrentPositionY + public string Name { - get => this._data.Span[3]; - set => this._data.Span[3] = value; + get => this._data.Span.ExtractString(1, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(1, 10).Span.WriteString(value, System.Text.Encoding.UTF8); } /// - /// Gets or sets the skin. + /// Gets or sets the level. /// - public ushort Skin + public ushort Level { - get => ReadUInt16BigEndian(this._data.Span[4..]); - set => WriteUInt16BigEndian(this._data.Span[4..], value); + get => ReadUInt16LittleEndian(this._data.Span[12..]); + set => WriteUInt16LittleEndian(this._data.Span[12..], value); } /// - /// Gets or sets the name. + /// Gets or sets the status. /// - public string Name + public CharacterStatus Status { - get => this._data.Span.ExtractString(6, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(6, 10).Span.WriteString(value, System.Text.Encoding.UTF8); + get => (CharacterStatus)this._data.Span[14..].GetByteValue(4, 0); + set => this._data.Span[14..].SetByteValue((byte)value, 4, 0); } /// - /// Gets or sets the target position x. + /// Gets or sets the is item block active. /// - public byte TargetPositionX + public bool IsItemBlockActive { - get => this._data.Span[16]; - set => this._data.Span[16] = value; + get => this._data.Span[14..].GetBoolean(4); + set => this._data.Span[14..].SetBoolean(value, 4); } /// - /// Gets or sets the target position y. + /// Gets or sets the appearance. /// - public byte TargetPositionY + public Span Appearance { - get => this._data.Span[17]; - set => this._data.Span[17] = value; + get => this._data.Slice(15, 18).Span; } /// - /// Gets or sets the rotation. + /// Gets or sets the guild position. /// - public byte Rotation + public GuildMemberRole GuildPosition { - get => this._data.Span[18..].GetByteValue(4, 4); - set => this._data.Span[18..].SetByteValue(value, 4, 4); + get => (GuildMemberRole)this._data.Span[33]; + set => this._data.Span[33] = (byte)value; } +} +} - /// - /// Gets or sets the hero state. - /// - public CharacterHeroState HeroState - { - get => (CharacterHeroState)this._data.Span[18..].GetByteValue(4, 0); - set => this._data.Span[18..].SetByteValue((byte)value, 4, 0); - } + +/// +/// Is sent by the server when: It's send right after the CharacterList, in the character selection screen, if the account has any unlocked character classes. +/// Causes reaction on client side: The client unlocks the specified character classes, so they can be created. +/// +public readonly struct CharacterClassCreationUnlock +{ + private readonly Memory _data; /// - /// Gets or sets the appearance. + /// Initializes a new instance of the struct. /// - public Span Appearance + /// The underlying data. + public CharacterClassCreationUnlock(Memory data) + : this(data, true) { - get => this._data.Slice(19, 18).Span; } /// - /// Gets or sets defines the number of effects which would be sent after this field. + /// Initializes a new instance of the struct. /// - public byte EffectCount + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private CharacterClassCreationUnlock(Memory data, bool initialize) { - get => this._data.Span[37]; - set => this._data.Span[37] = value; + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } } /// - /// Gets the of the specified index. + /// Gets the header type of this data packet. /// - public EffectId this[int index] => new (this._data.Slice(38 + index * EffectId.Length)); + public static byte HeaderType => 0xC1; /// - /// Calculates the size of the packet for the specified count of . + /// Gets the operation code of this data packet. /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int effectsCount) => effectsCount * EffectId.Length + 38; -} - - -/// -/// Contains the id of a magic effect.. -/// -public readonly struct EffectId -{ - private readonly Memory _data; + public static byte Code => 0xDE; /// - /// Initializes a new instance of the struct. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - /// The underlying data. - public EffectId(Memory data) - { - this._data = data; - } + public static byte SubCode => 0x00; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 1; + public static int Length => 5; /// - /// Gets or sets the id. + /// Gets the header of this packet. /// - public byte Id - { - get => this._data.Span[0]; - set => this._data.Span[0] = value; - } -} -} - + public C1HeaderWithSubCode Header => new (this._data); -/// -/// Is sent by the server when: The server wants to alter the terrain attributes of a map at runtime. -/// Causes reaction on client side: The client updates the terrain attributes on its side. -/// -public readonly struct ChangeTerrainAttributes -{ /// - /// Defines the attribute which should be set/unset. It's a Flags enumeration. + /// Gets or sets the unlock flags. /// - public enum TerrainAttributeType - { - /// - /// The coordinate is a safezone. - /// - Safezone = 1, - - /// - /// The coordinate is occupied by a character. - /// - Character = 2, + public CharacterCreationUnlockFlags UnlockFlags + { + get => (CharacterCreationUnlockFlags)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; + } - /// - /// The coordinate is blocked and can't be passed by a character. - /// - Blocked = 4, + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator CharacterClassCreationUnlock(Memory packet) => new (packet, false); - /// - /// The coordinate is blocked, because there is no ground and can't be passed by a character. - /// - NoGround = 8, + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(CharacterClassCreationUnlock packet) => packet._data; +} - /// - /// The coordinate is blocked by water and can't be passed by a character. - /// - Water = 16, - } +/// +/// Is sent by the server when: After the game client requested it, usually after a successful login. +/// Causes reaction on client side: The game client shows the available characters of the account. +/// +public readonly struct CharacterList075 +{ private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ChangeTerrainAttributes(Memory data) + public CharacterList075(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ChangeTerrainAttributes(Memory data, bool initialize) + private CharacterList075(Memory data, bool initialize) { this._data = data; if (initialize) @@ -10920,7 +12192,7 @@ private ChangeTerrainAttributes(Memory data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)data.Length; - this.Type = false; + header.SubCode = SubCode; } } @@ -10932,88 +12204,67 @@ private ChangeTerrainAttributes(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x46; - - /// - /// Gets the header of this packet. - /// - public C1Header Header => new (this._data); - - /// - /// Gets or sets the type. - /// - public bool Type - { - get => this._data.Span[3..].GetBoolean(); - set => this._data.Span[3..].SetBoolean(value); - } + public static byte Code => 0xF3; /// - /// Gets or sets the attribute. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public ChangeTerrainAttributes.TerrainAttributeType Attribute - { - get => (TerrainAttributeType)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; - } + public static byte SubCode => 0x00; /// - /// Gets or sets when this is true, the attribute is removed on the client side. If it's false, then the attribute is added. + /// Gets the header of this packet. /// - public bool RemoveAttribute - { - get => this._data.Span[5..].GetBoolean(); - set => this._data.Span[5..].SetBoolean(value); - } + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the area count. + /// Gets or sets the character count. /// - public byte AreaCount + public byte CharacterCount { - get => this._data.Span[6]; - set => this._data.Span[6] = value; + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Gets the of the specified index. + /// Gets the of the specified index. /// - public TerrainArea this[int index] => new (this._data.Slice(7 + index * TerrainArea.Length)); + public CharacterData this[int index] => new (this._data.Slice(5 + index * CharacterData.Length)); /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ChangeTerrainAttributes(Memory packet) => new (packet, false); + public static implicit operator CharacterList075(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(ChangeTerrainAttributes packet) => packet._data; + public static implicit operator Memory(CharacterList075 packet) => packet._data; /// - /// Calculates the size of the packet for the specified count of . + /// Calculates the size of the packet for the specified count of . /// - /// The count of from which the size will be calculated. + /// The count of from which the size will be calculated. - public static int GetRequiredSize(int areasCount) => areasCount * TerrainArea.Length + 7; + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 5; /// -/// Defines the area which should be changed.. +/// Data of one character in the list.. /// -public readonly struct TerrainArea +public readonly struct CharacterData { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public TerrainArea(Memory data) + public CharacterData(Memory data) { this._data = data; } @@ -11021,179 +12272,256 @@ public TerrainArea(Memory data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 4; + public static int Length => 24; /// - /// Gets or sets the start x. + /// Gets or sets the slot index. /// - public byte StartX + public byte SlotIndex { get => this._data.Span[0]; set => this._data.Span[0] = value; } /// - /// Gets or sets the start y. + /// Gets or sets the name. /// - public byte StartY + public string Name { - get => this._data.Span[1]; - set => this._data.Span[1] = value; + get => this._data.Span.ExtractString(1, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(1, 10).Span.WriteString(value, System.Text.Encoding.UTF8); } /// - /// Gets or sets the end x. + /// Gets or sets the level. /// - public byte EndX + public ushort Level { - get => this._data.Span[2]; - set => this._data.Span[2] = value; + get => ReadUInt16BigEndian(this._data.Span[11..]); + set => WriteUInt16BigEndian(this._data.Span[11..], value); } /// - /// Gets or sets the end y. + /// Gets or sets the status. /// - public byte EndY + public CharacterStatus Status { - get => this._data.Span[3]; - set => this._data.Span[3] = value; + get => (CharacterStatus)this._data.Span[13..].GetByteValue(4, 0); + set => this._data.Span[13..].SetByteValue((byte)value, 4, 0); + } + + /// + /// Gets or sets the is item block active. + /// + public bool IsItemBlockActive + { + get => this._data.Span[13..].GetBoolean(4); + set => this._data.Span[13..].SetBoolean(value, 4); + } + + /// + /// Gets or sets the appearance. + /// + public Span Appearance + { + get => this._data.Slice(14, 9).Span; } } } /// -/// Is sent by the server when: After a player achieved or lost something. -/// Causes reaction on client side: An effect is shown for the affected player. +/// Is sent by the server when: After the game client requested it, usually after a successful login. +/// Causes reaction on client side: The game client shows the available characters of the account. /// -public readonly struct ShowEffect +public readonly struct CharacterList095 { + private readonly Memory _data; + /// - /// Defines the effect which is shown for the player. + /// Initializes a new instance of the struct. /// - public enum EffectType + /// The underlying data. + public CharacterList095(Memory data) + : this(data, true) { - /// - /// The player gained shield by drinking a potion. - /// - ShieldPotion = 3, + } - /// - /// A level up effect is shown for the player. - /// - LevelUp = 16, + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private CharacterList095(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)data.Length; + header.SubCode = SubCode; + } + } - /// - /// The players shield depleted. - /// - ShieldLost = 17, + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x00; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets the character count. + /// + public byte CharacterCount + { + get => this._data.Span[4]; + set => this._data.Span[4] = value; } - private readonly Memory _data; + /// + /// Gets the of the specified index. + /// + public CharacterData this[int index] => new (this._data.Slice(5 + index * CharacterData.Length)); + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator CharacterList095(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(CharacterList095 packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of . + /// + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 5; + - /// - /// Initializes a new instance of the struct. - /// - /// The underlying data. - public ShowEffect(Memory data) - : this(data, true) - { - } +/// +/// Data of one character in the list.. +/// +public readonly struct CharacterData +{ + private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private ShowEffect(Memory data, bool initialize) + public CharacterData(Memory data) { this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - } } /// - /// Gets the header type of this data packet. - /// - public static byte HeaderType => 0xC1; - - /// - /// Gets the operation code of this data packet. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static byte Code => 0x48; + public static int Length => 26; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the slot index. /// - public static int Length => 6; + public byte SlotIndex + { + get => this._data.Span[0]; + set => this._data.Span[0] = value; + } /// - /// Gets the header of this packet. + /// Gets or sets the name. /// - public C1Header Header => new (this._data); + public string Name + { + get => this._data.Span.ExtractString(1, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(1, 10).Span.WriteString(value, System.Text.Encoding.UTF8); + } /// - /// Gets or sets the player id. + /// Gets or sets the level. /// - public ushort PlayerId + public ushort Level { - get => ReadUInt16BigEndian(this._data.Span[3..]); - set => WriteUInt16BigEndian(this._data.Span[3..], value); + get => ReadUInt16LittleEndian(this._data.Span[12..]); + set => WriteUInt16LittleEndian(this._data.Span[12..], value); } /// - /// Gets or sets the effect. + /// Gets or sets the status. /// - public ShowEffect.EffectType Effect + public CharacterStatus Status { - get => (EffectType)this._data.Span[5]; - set => this._data.Span[5] = (byte)value; + get => (CharacterStatus)this._data.Span[14..].GetByteValue(4, 0); + set => this._data.Span[14..].SetByteValue((byte)value, 4, 0); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the is item block active. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator ShowEffect(Memory packet) => new (packet, false); + public bool IsItemBlockActive + { + get => this._data.Span[14..].GetBoolean(4); + set => this._data.Span[14..].SetBoolean(value, 4); + } /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the appearance. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(ShowEffect packet) => packet._data; + public Span Appearance + { + get => this._data.Slice(15, 11).Span; + } +} } /// -/// Is sent by the server when: After the game client requested it, usually after a successful login. -/// Causes reaction on client side: The game client shows the available characters of the account. +/// Is sent by the server when: After the server successfully processed a character creation request. +/// Causes reaction on client side: The new character is shown in the character list /// -public readonly struct CharacterList +public readonly struct CharacterCreationSuccessful { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterList(Memory data) + public CharacterCreationSuccessful(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterList(Memory data, bool initialize) + private CharacterCreationSuccessful(Memory data, bool initialize) { this._data = data; if (initialize) @@ -11201,8 +12529,9 @@ private CharacterList(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Success = true; } } @@ -11220,7 +12549,12 @@ private CharacterList(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; + public static byte SubCode => 0x01; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 42; /// /// Gets the header of this packet. @@ -11228,177 +12562,190 @@ private CharacterList(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the unlock flags. + /// Gets or sets the success. /// - public CharacterCreationUnlockFlags UnlockFlags + public bool Success { - get => (CharacterCreationUnlockFlags)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; + get => this._data.Span[4..].GetBoolean(); + set => this._data.Span[4..].SetBoolean(value); } /// - /// Gets or sets the move cnt. + /// Gets or sets the character name. /// - public byte MoveCnt + public string CharacterName { - get => this._data.Span[5]; - set => this._data.Span[5] = value; + get => this._data.Span.ExtractString(5, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(5, 10).Span.WriteString(value, System.Text.Encoding.UTF8); } /// - /// Gets or sets the character count. + /// Gets or sets the character slot. /// - public byte CharacterCount + public byte CharacterSlot { - get => this._data.Span[6]; - set => this._data.Span[6] = value; + get => this._data.Span[15]; + set => this._data.Span[15] = value; } /// - /// Gets or sets the is vault extended. + /// Gets or sets the level. /// - public bool IsVaultExtended + public ushort Level { - get => this._data.Span[7..].GetBoolean(); - set => this._data.Span[7..].SetBoolean(value); + get => ReadUInt16LittleEndian(this._data.Span[16..]); + set => WriteUInt16LittleEndian(this._data.Span[16..], value); } /// - /// Gets the of the specified index. + /// Gets or sets the class. /// - public CharacterData this[int index] => new (this._data.Slice(8 + index * CharacterData.Length)); + public CharacterClassNumber Class + { + get => (CharacterClassNumber)this._data.Span[18..].GetByteValue(8, 3); + set => this._data.Span[18..].SetByteValue((byte)value, 8, 3); + } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the character status. + /// + public byte CharacterStatus + { + get => this._data.Span[19]; + set => this._data.Span[19] = value; + } + + /// + /// Gets or sets the preview data. + /// + public Span PreviewData + { + get => this._data.Slice(20).Span; + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterList(Memory packet) => new (packet, false); + public static implicit operator CharacterCreationSuccessful(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CharacterList packet) => packet._data; + public static implicit operator Memory(CharacterCreationSuccessful packet) => packet._data; /// - /// Calculates the size of the packet for the specified count of . + /// Calculates the size of the packet for the specified length of . /// - /// The count of from which the size will be calculated. + /// The length in bytes of on which the required size depends. - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 8; + public static int GetRequiredSize(int previewDataLength) => previewDataLength + 20; +} /// -/// Data of one character in the list.. +/// Is sent by the server when: After the server processed a character creation request without success. +/// Causes reaction on client side: A message is shown that it failed. /// -public readonly struct CharacterData +public readonly struct CharacterCreationFailed { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterData(Memory data) + public CharacterCreationFailed(Memory data) + : this(data, true) { - this._data = data; } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Initializes a new instance of the struct. /// - public static int Length => 34; + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private CharacterCreationFailed(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } + } /// - /// Gets or sets the slot index. + /// Gets the header type of this data packet. /// - public byte SlotIndex - { - get => this._data.Span[0]; - set => this._data.Span[0] = value; - } + public static byte HeaderType => 0xC1; /// - /// Gets or sets the name. + /// Gets the operation code of this data packet. /// - public string Name - { - get => this._data.Span.ExtractString(1, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(1, 10).Span.WriteString(value, System.Text.Encoding.UTF8); - } + public static byte Code => 0xF3; /// - /// Gets or sets the level. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public ushort Level - { - get => ReadUInt16LittleEndian(this._data.Span[12..]); - set => WriteUInt16LittleEndian(this._data.Span[12..], value); - } + public static byte SubCode => 0x01; /// - /// Gets or sets the status. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public CharacterStatus Status - { - get => (CharacterStatus)this._data.Span[14..].GetByteValue(4, 0); - set => this._data.Span[14..].SetByteValue((byte)value, 4, 0); - } + public static int Length => 5; /// - /// Gets or sets the is item block active. + /// Gets the header of this packet. /// - public bool IsItemBlockActive - { - get => this._data.Span[14..].GetBoolean(4); - set => this._data.Span[14..].SetBoolean(value, 4); - } + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the appearance. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public Span Appearance - { - get => this._data.Slice(15, 18).Span; - } + /// The packet as span. + /// The packet as struct. + public static implicit operator CharacterCreationFailed(Memory packet) => new (packet, false); /// - /// Gets or sets the guild position. + /// Performs an implicit conversion from to a Memory of bytes. /// - public GuildMemberRole GuildPosition - { - get => (GuildMemberRole)this._data.Span[33]; - set => this._data.Span[33] = (byte)value; - } -} + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(CharacterCreationFailed packet) => packet._data; } /// -/// Is sent by the server when: It's send right after the CharacterList, in the character selection screen, if the account has any unlocked character classes. -/// Causes reaction on client side: The client unlocks the specified character classes, so they can be created. +/// Is sent by the server when: The character respawned after death. +/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. /// -public readonly struct CharacterClassCreationUnlock +public readonly struct RespawnAfterDeath075 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterClassCreationUnlock(Memory data) + public RespawnAfterDeath075(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterClassCreationUnlock(Memory data, bool initialize) + private RespawnAfterDeath075(Memory data, bool initialize) { this._data = data; if (initialize) @@ -11419,18 +12766,18 @@ private CharacterClassCreationUnlock(Memory data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0xDE; + public static byte Code => 0xF3; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; + public static byte SubCode => 0x04; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 5; + public static int Length => 20; /// /// Gets the header of this packet. @@ -11438,53 +12785,116 @@ private CharacterClassCreationUnlock(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the unlock flags. + /// Gets or sets the position x. /// - public CharacterCreationUnlockFlags UnlockFlags + public byte PositionX { - get => (CharacterCreationUnlockFlags)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the position y. + /// + public byte PositionY + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } + + /// + /// Gets or sets the map number. + /// + public byte MapNumber + { + get => this._data.Span[6]; + set => this._data.Span[6] = value; + } + + /// + /// Gets or sets the direction. + /// + public byte Direction + { + get => this._data.Span[7]; + set => this._data.Span[7] = value; + } + + /// + /// Gets or sets the current health. + /// + public ushort CurrentHealth + { + get => ReadUInt16LittleEndian(this._data.Span[8..]); + set => WriteUInt16LittleEndian(this._data.Span[8..], value); + } + + /// + /// Gets or sets the current mana. + /// + public ushort CurrentMana + { + get => ReadUInt16LittleEndian(this._data.Span[10..]); + set => WriteUInt16LittleEndian(this._data.Span[10..], value); + } + + /// + /// Gets or sets the experience. + /// + public uint Experience + { + get => ReadUInt32LittleEndian(this._data.Span[12..]); + set => WriteUInt32LittleEndian(this._data.Span[12..], value); + } + + /// + /// Gets or sets the money. + /// + public uint Money + { + get => ReadUInt32LittleEndian(this._data.Span[16..]); + set => WriteUInt32LittleEndian(this._data.Span[16..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterClassCreationUnlock(Memory packet) => new (packet, false); + public static implicit operator RespawnAfterDeath075(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CharacterClassCreationUnlock packet) => packet._data; + public static implicit operator Memory(RespawnAfterDeath075 packet) => packet._data; } /// -/// Is sent by the server when: After the game client requested it, usually after a successful login. -/// Causes reaction on client side: The game client shows the available characters of the account. +/// Is sent by the server when: The character respawned after death. +/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. /// -public readonly struct CharacterList075 +public readonly struct RespawnAfterDeath095 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterList075(Memory data) + public RespawnAfterDeath095(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterList075(Memory data, bool initialize) + private RespawnAfterDeath095(Memory data, bool initialize) { this._data = data; if (initialize) @@ -11492,7 +12902,7 @@ private CharacterList075(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; } } @@ -11511,7 +12921,12 @@ private CharacterList075(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; + public static byte SubCode => 0x04; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 22; /// /// Gets the header of this packet. @@ -11519,141 +12934,125 @@ private CharacterList075(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the character count. + /// Gets or sets the position x. /// - public byte CharacterCount + public byte PositionX { get => this._data.Span[4]; set => this._data.Span[4] = value; } /// - /// Gets the of the specified index. - /// - public CharacterData this[int index] => new (this._data.Slice(5 + index * CharacterData.Length)); - - /// - /// Performs an implicit conversion from a Memory of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator CharacterList075(Memory packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the position y. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(CharacterList075 packet) => packet._data; + public byte PositionY + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } /// - /// Calculates the size of the packet for the specified count of . + /// Gets or sets the map number. /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 5; - - -/// -/// Data of one character in the list.. -/// -public readonly struct CharacterData -{ - private readonly Memory _data; + public byte MapNumber + { + get => this._data.Span[6]; + set => this._data.Span[6] = value; + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the direction. /// - /// The underlying data. - public CharacterData(Memory data) + public byte Direction { - this._data = data; + get => this._data.Span[7]; + set => this._data.Span[7] = value; } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the current health. /// - public static int Length => 24; + public ushort CurrentHealth + { + get => ReadUInt16LittleEndian(this._data.Span[8..]); + set => WriteUInt16LittleEndian(this._data.Span[8..], value); + } /// - /// Gets or sets the slot index. + /// Gets or sets the current mana. /// - public byte SlotIndex + public ushort CurrentMana { - get => this._data.Span[0]; - set => this._data.Span[0] = value; + get => ReadUInt16LittleEndian(this._data.Span[10..]); + set => WriteUInt16LittleEndian(this._data.Span[10..], value); } /// - /// Gets or sets the name. + /// Gets or sets the current ability. /// - public string Name + public ushort CurrentAbility { - get => this._data.Span.ExtractString(1, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(1, 10).Span.WriteString(value, System.Text.Encoding.UTF8); + get => ReadUInt16LittleEndian(this._data.Span[12..]); + set => WriteUInt16LittleEndian(this._data.Span[12..], value); } /// - /// Gets or sets the level. + /// Gets or sets the experience. /// - public ushort Level + public uint Experience { - get => ReadUInt16BigEndian(this._data.Span[11..]); - set => WriteUInt16BigEndian(this._data.Span[11..], value); + get => ReadUInt32LittleEndian(this._data.Span[14..]); + set => WriteUInt32LittleEndian(this._data.Span[14..], value); } /// - /// Gets or sets the status. + /// Gets or sets the money. /// - public CharacterStatus Status + public uint Money { - get => (CharacterStatus)this._data.Span[13..].GetByteValue(4, 0); - set => this._data.Span[13..].SetByteValue((byte)value, 4, 0); + get => ReadUInt32LittleEndian(this._data.Span[18..]); + set => WriteUInt32LittleEndian(this._data.Span[18..], value); } /// - /// Gets or sets the is item block active. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public bool IsItemBlockActive - { - get => this._data.Span[13..].GetBoolean(4); - set => this._data.Span[13..].SetBoolean(value, 4); - } + /// The packet as span. + /// The packet as struct. + public static implicit operator RespawnAfterDeath095(Memory packet) => new (packet, false); /// - /// Gets or sets the appearance. + /// Performs an implicit conversion from to a Memory of bytes. /// - public Span Appearance - { - get => this._data.Slice(14, 9).Span; - } -} + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(RespawnAfterDeath095 packet) => packet._data; } /// -/// Is sent by the server when: After the game client requested it, usually after a successful login. -/// Causes reaction on client side: The game client shows the available characters of the account. +/// Is sent by the server when: The character got damaged by being poisoned on old client versions. +/// Causes reaction on client side: Removes the damage from the health without showing a damage number. /// -public readonly struct CharacterList095 +public readonly struct PoisonDamage { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterList095(Memory data) + public PoisonDamage(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterList095(Memory data, bool initialize) + private PoisonDamage(Memory data, bool initialize) { this._data = data; if (initialize) @@ -11661,7 +13060,7 @@ private CharacterList095(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; } } @@ -11680,149 +13079,75 @@ private CharacterList095(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; - - /// - /// Gets the header of this packet. - /// - public C1HeaderWithSubCode Header => new (this._data); - - /// - /// Gets or sets the character count. - /// - public byte CharacterCount - { - get => this._data.Span[4]; - set => this._data.Span[4] = value; - } - - /// - /// Gets the of the specified index. - /// - public CharacterData this[int index] => new (this._data.Slice(5 + index * CharacterData.Length)); - - /// - /// Performs an implicit conversion from a Memory of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator CharacterList095(Memory packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Memory of bytes. - /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(CharacterList095 packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified count of . - /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterData.Length + 5; - - -/// -/// Data of one character in the list.. -/// -public readonly struct CharacterData -{ - private readonly Memory _data; - - /// - /// Initializes a new instance of the struct. - /// - /// The underlying data. - public CharacterData(Memory data) - { - this._data = data; - } + public static byte SubCode => 0x07; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 26; - - /// - /// Gets or sets the slot index. - /// - public byte SlotIndex - { - get => this._data.Span[0]; - set => this._data.Span[0] = value; - } + public static int Length => 8; /// - /// Gets or sets the name. + /// Gets the header of this packet. /// - public string Name - { - get => this._data.Span.ExtractString(1, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(1, 10).Span.WriteString(value, System.Text.Encoding.UTF8); - } + public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the level. + /// Gets or sets the health damage. /// - public ushort Level + public ushort HealthDamage { - get => ReadUInt16LittleEndian(this._data.Span[12..]); - set => WriteUInt16LittleEndian(this._data.Span[12..], value); + get => ReadUInt16BigEndian(this._data.Span[4..]); + set => WriteUInt16BigEndian(this._data.Span[4..], value); } /// - /// Gets or sets the status. + /// Gets or sets the current shield. /// - public CharacterStatus Status + public ushort CurrentShield { - get => (CharacterStatus)this._data.Span[14..].GetByteValue(4, 0); - set => this._data.Span[14..].SetByteValue((byte)value, 4, 0); + get => ReadUInt16BigEndian(this._data.Span[6..]); + set => WriteUInt16BigEndian(this._data.Span[6..], value); } /// - /// Gets or sets the is item block active. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public bool IsItemBlockActive - { - get => this._data.Span[14..].GetBoolean(4); - set => this._data.Span[14..].SetBoolean(value, 4); - } + /// The packet as span. + /// The packet as struct. + public static implicit operator PoisonDamage(Memory packet) => new (packet, false); /// - /// Gets or sets the appearance. + /// Performs an implicit conversion from to a Memory of bytes. /// - public Span Appearance - { - get => this._data.Slice(15, 11).Span; - } -} + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(PoisonDamage packet) => packet._data; } /// -/// Is sent by the server when: After the server successfully processed a character creation request. -/// Causes reaction on client side: The new character is shown in the character list +/// Is sent by the server when: After a the hero state of an observed character changed. +/// Causes reaction on client side: The color of the name of the character is changed accordingly and a message is shown. /// -public readonly struct CharacterCreationSuccessful +public readonly struct HeroStateChanged { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterCreationSuccessful(Memory data) + public HeroStateChanged(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterCreationSuccessful(Memory data, bool initialize) + private HeroStateChanged(Memory data, bool initialize) { this._data = data; if (initialize) @@ -11832,7 +13157,6 @@ private CharacterCreationSuccessful(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Success = true; } } @@ -11850,12 +13174,12 @@ private CharacterCreationSuccessful(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x01; + public static byte SubCode => 0x08; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 42; + public static int Length => 7; /// /// Gets the header of this packet. @@ -11863,113 +13187,62 @@ private CharacterCreationSuccessful(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the success. - /// - public bool Success - { - get => this._data.Span[4..].GetBoolean(); - set => this._data.Span[4..].SetBoolean(value); - } - - /// - /// Gets or sets the character name. - /// - public string CharacterName - { - get => this._data.Span.ExtractString(5, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(5, 10).Span.WriteString(value, System.Text.Encoding.UTF8); - } - - /// - /// Gets or sets the character slot. - /// - public byte CharacterSlot - { - get => this._data.Span[15]; - set => this._data.Span[15] = value; - } - - /// - /// Gets or sets the level. - /// - public ushort Level - { - get => ReadUInt16LittleEndian(this._data.Span[16..]); - set => WriteUInt16LittleEndian(this._data.Span[16..], value); - } - - /// - /// Gets or sets the class. - /// - public CharacterClassNumber Class - { - get => (CharacterClassNumber)this._data.Span[18..].GetByteValue(8, 3); - set => this._data.Span[18..].SetByteValue((byte)value, 8, 3); - } - - /// - /// Gets or sets the character status. + /// Gets or sets the player id. /// - public byte CharacterStatus + public ushort PlayerId { - get => this._data.Span[19]; - set => this._data.Span[19] = value; + get => ReadUInt16BigEndian(this._data.Span[4..]); + set => WriteUInt16BigEndian(this._data.Span[4..], value); } /// - /// Gets or sets the preview data. + /// Gets or sets the new state. /// - public Span PreviewData + public CharacterHeroState NewState { - get => this._data.Slice(20).Span; + get => (CharacterHeroState)this._data.Span[6]; + set => this._data.Span[6] = (byte)value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterCreationSuccessful(Memory packet) => new (packet, false); + public static implicit operator HeroStateChanged(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CharacterCreationSuccessful packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified length of . - /// - /// The length in bytes of on which the required size depends. - - public static int GetRequiredSize(int previewDataLength) => previewDataLength + 20; + public static implicit operator Memory(HeroStateChanged packet) => packet._data; } /// -/// Is sent by the server when: After the server processed a character creation request without success. -/// Causes reaction on client side: A message is shown that it failed. +/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. +/// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly struct CharacterCreationFailed +public readonly struct SkillAdded { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterCreationFailed(Memory data) + public SkillAdded(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterCreationFailed(Memory data, bool initialize) + private SkillAdded(Memory data, bool initialize) { this._data = data; if (initialize) @@ -11979,6 +13252,7 @@ private CharacterCreationFailed(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Flag = 0xFE; } } @@ -11988,65 +13262,101 @@ private CharacterCreationFailed(Memory data, bool initialize) public static byte HeaderType => 0xC1; /// - /// Gets the operation code of this data packet. + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x11; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 10; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets the flag. /// - public static byte Code => 0xF3; + public byte Flag + { + get => this._data.Span[4]; + set => this._data.Span[4] = value; + } /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets or sets the skill index. /// - public static byte SubCode => 0x01; + public byte SkillIndex + { + get => this._data.Span[6]; + set => this._data.Span[6] = value; + } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the skill number. /// - public static int Length => 5; + public ushort SkillNumber + { + get => ReadUInt16LittleEndian(this._data.Span[7..]); + set => WriteUInt16LittleEndian(this._data.Span[7..], value); + } /// - /// Gets the header of this packet. + /// Gets or sets the skill level. /// - public C1HeaderWithSubCode Header => new (this._data); + public byte SkillLevel + { + get => this._data.Span[9]; + set => this._data.Span[9] = value; + } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterCreationFailed(Memory packet) => new (packet, false); + public static implicit operator SkillAdded(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CharacterCreationFailed packet) => packet._data; + public static implicit operator Memory(SkillAdded packet) => packet._data; } /// -/// Is sent by the server when: The character respawned after death. -/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. +/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. +/// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly struct RespawnAfterDeath075 +public readonly struct SkillRemoved { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public RespawnAfterDeath075(Memory data) + public SkillRemoved(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private RespawnAfterDeath075(Memory data, bool initialize) + private SkillRemoved(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12056,6 +13366,7 @@ private RespawnAfterDeath075(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Flag = 0xFF; } } @@ -12073,12 +13384,12 @@ private RespawnAfterDeath075(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x04; + public static byte SubCode => 0x11; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 20; + public static int Length => 10; /// /// Gets the header of this packet. @@ -12086,116 +13397,71 @@ private RespawnAfterDeath075(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the position x. + /// Gets or sets the flag. /// - public byte PositionX + public byte Flag { get => this._data.Span[4]; set => this._data.Span[4] = value; } /// - /// Gets or sets the position y. - /// - public byte PositionY - { - get => this._data.Span[5]; - set => this._data.Span[5] = value; - } - - /// - /// Gets or sets the map number. + /// Gets or sets the skill index. /// - public byte MapNumber + public byte SkillIndex { get => this._data.Span[6]; set => this._data.Span[6] = value; } /// - /// Gets or sets the direction. - /// - public byte Direction - { - get => this._data.Span[7]; - set => this._data.Span[7] = value; - } - - /// - /// Gets or sets the current health. - /// - public ushort CurrentHealth - { - get => ReadUInt16LittleEndian(this._data.Span[8..]); - set => WriteUInt16LittleEndian(this._data.Span[8..], value); - } - - /// - /// Gets or sets the current mana. - /// - public ushort CurrentMana - { - get => ReadUInt16LittleEndian(this._data.Span[10..]); - set => WriteUInt16LittleEndian(this._data.Span[10..], value); - } - - /// - /// Gets or sets the experience. - /// - public uint Experience - { - get => ReadUInt32LittleEndian(this._data.Span[12..]); - set => WriteUInt32LittleEndian(this._data.Span[12..], value); - } - - /// - /// Gets or sets the money. + /// Gets or sets the skill number. /// - public uint Money + public ushort SkillNumber { - get => ReadUInt32LittleEndian(this._data.Span[16..]); - set => WriteUInt32LittleEndian(this._data.Span[16..], value); + get => ReadUInt16LittleEndian(this._data.Span[7..]); + set => WriteUInt16LittleEndian(this._data.Span[7..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator RespawnAfterDeath075(Memory packet) => new (packet, false); + public static implicit operator SkillRemoved(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(RespawnAfterDeath075 packet) => packet._data; + public static implicit operator Memory(SkillRemoved packet) => packet._data; } /// -/// Is sent by the server when: The character respawned after death. -/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. +/// Is sent by the server when: Usually, when the player entered the game with a character. When skills get added or removed, this message is sent as well, but with a misleading count. +/// Causes reaction on client side: The skill list gets initialized. /// -public readonly struct RespawnAfterDeath095 +public readonly struct SkillListUpdate { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public RespawnAfterDeath095(Memory data) + public SkillListUpdate(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private RespawnAfterDeath095(Memory data, bool initialize) + private SkillListUpdate(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12203,7 +13469,7 @@ private RespawnAfterDeath095(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); + header.Length = (byte)data.Length; header.SubCode = SubCode; } } @@ -12222,12 +13488,7 @@ private RespawnAfterDeath095(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x04; - - /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. - /// - public static int Length => 22; + public static byte SubCode => 0x11; /// /// Gets the header of this packet. @@ -12235,125 +13496,115 @@ private RespawnAfterDeath095(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the position x. + /// Gets or sets mixed usage: Skill list count (when list). 0xFE when adding a skill, 0xFF when removing a Skill. /// - public byte PositionX + public byte Count { get => this._data.Span[4]; set => this._data.Span[4] = value; } /// - /// Gets or sets the position y. + /// Gets the of the specified index. /// - public byte PositionY - { - get => this._data.Span[5]; - set => this._data.Span[5] = value; - } + public SkillEntry this[int index] => new (this._data.Slice(6 + index * SkillEntry.Length)); /// - /// Gets or sets the map number. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public byte MapNumber - { - get => this._data.Span[6]; - set => this._data.Span[6] = value; - } + /// The packet as span. + /// The packet as struct. + public static implicit operator SkillListUpdate(Memory packet) => new (packet, false); /// - /// Gets or sets the direction. + /// Performs an implicit conversion from to a Memory of bytes. /// - public byte Direction - { - get => this._data.Span[7]; - set => this._data.Span[7] = value; - } + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(SkillListUpdate packet) => packet._data; /// - /// Gets or sets the current health. + /// Calculates the size of the packet for the specified count of . /// - public ushort CurrentHealth - { - get => ReadUInt16LittleEndian(this._data.Span[8..]); - set => WriteUInt16LittleEndian(this._data.Span[8..], value); - } + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntry.Length + 6; + + +/// +/// Structure for a skill entry of the skill list.. +/// +public readonly struct SkillEntry +{ + private readonly Memory _data; /// - /// Gets or sets the current mana. + /// Initializes a new instance of the struct. /// - public ushort CurrentMana + /// The underlying data. + public SkillEntry(Memory data) { - get => ReadUInt16LittleEndian(this._data.Span[10..]); - set => WriteUInt16LittleEndian(this._data.Span[10..], value); + this._data = data; } /// - /// Gets or sets the current ability. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public ushort CurrentAbility - { - get => ReadUInt16LittleEndian(this._data.Span[12..]); - set => WriteUInt16LittleEndian(this._data.Span[12..], value); - } + public static int Length => 4; /// - /// Gets or sets the experience. + /// Gets or sets the skill index. /// - public uint Experience + public byte SkillIndex { - get => ReadUInt32LittleEndian(this._data.Span[14..]); - set => WriteUInt32LittleEndian(this._data.Span[14..], value); + get => this._data.Span[0]; + set => this._data.Span[0] = value; } /// - /// Gets or sets the money. + /// Gets or sets the skill number. /// - public uint Money + public ushort SkillNumber { - get => ReadUInt32LittleEndian(this._data.Span[18..]); - set => WriteUInt32LittleEndian(this._data.Span[18..], value); + get => ReadUInt16LittleEndian(this._data.Span[1..]); + set => WriteUInt16LittleEndian(this._data.Span[1..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator RespawnAfterDeath095(Memory packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the skill level. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(RespawnAfterDeath095 packet) => packet._data; + public byte SkillLevel + { + get => this._data.Span[3]; + set => this._data.Span[3] = value; + } +} } /// -/// Is sent by the server when: The character got damaged by being poisoned on old client versions. -/// Causes reaction on client side: Removes the damage from the health without showing a damage number. +/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. +/// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly struct PoisonDamage +public readonly struct SkillAdded075 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PoisonDamage(Memory data) + public SkillAdded075(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PoisonDamage(Memory data, bool initialize) + private SkillAdded075(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12363,6 +13614,7 @@ private PoisonDamage(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Flag = 1; } } @@ -12380,7 +13632,7 @@ private PoisonDamage(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x07; + public static byte SubCode => 0x11; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. @@ -12393,62 +13645,71 @@ private PoisonDamage(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the health damage. + /// Gets or sets the flag. /// - public ushort HealthDamage + public byte Flag { - get => ReadUInt16BigEndian(this._data.Span[4..]); - set => WriteUInt16BigEndian(this._data.Span[4..], value); + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Gets or sets the current shield. + /// Gets or sets the skill index. /// - public ushort CurrentShield + public byte SkillIndex + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } + + /// + /// Gets or sets the skill number and level. + /// + public ushort SkillNumberAndLevel { get => ReadUInt16BigEndian(this._data.Span[6..]); set => WriteUInt16BigEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PoisonDamage(Memory packet) => new (packet, false); + public static implicit operator SkillAdded075(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(PoisonDamage packet) => packet._data; + public static implicit operator Memory(SkillAdded075 packet) => packet._data; } /// -/// Is sent by the server when: After a the hero state of an observed character changed. -/// Causes reaction on client side: The color of the name of the character is changed accordingly and a message is shown. +/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. +/// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly struct HeroStateChanged +public readonly struct SkillRemoved075 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public HeroStateChanged(Memory data) + public SkillRemoved075(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private HeroStateChanged(Memory data, bool initialize) + private SkillRemoved075(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12458,6 +13719,7 @@ private HeroStateChanged(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Flag = 0; } } @@ -12475,12 +13737,12 @@ private HeroStateChanged(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x08; + public static byte SubCode => 0x11; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 7; + public static int Length => 10; /// /// Gets the header of this packet. @@ -12488,36 +13750,45 @@ private HeroStateChanged(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the player id. + /// Gets or sets the flag. /// - public ushort PlayerId + public byte Flag { - get => ReadUInt16BigEndian(this._data.Span[4..]); - set => WriteUInt16BigEndian(this._data.Span[4..], value); + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Gets or sets the new state. + /// Gets or sets the skill index. /// - public CharacterHeroState NewState + public byte SkillIndex { - get => (CharacterHeroState)this._data.Span[6]; - set => this._data.Span[6] = (byte)value; + get => this._data.Span[5]; + set => this._data.Span[5] = value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the skill number and level. + /// + public ushort SkillNumberAndLevel + { + get => ReadUInt16BigEndian(this._data.Span[6..]); + set => WriteUInt16BigEndian(this._data.Span[6..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator HeroStateChanged(Memory packet) => new (packet, false); + public static implicit operator SkillRemoved075(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(HeroStateChanged packet) => packet._data; + public static implicit operator Memory(SkillRemoved075 packet) => packet._data; } @@ -12525,25 +13796,25 @@ public CharacterHeroState NewState /// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. /// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly struct SkillAdded +public readonly struct SkillAdded095 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillAdded(Memory data) + public SkillAdded095(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillAdded(Memory data, bool initialize) + private SkillAdded095(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12576,7 +13847,7 @@ private SkillAdded(Memory data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 10; + public static int Length => 8; /// /// Gets the header of this packet. @@ -12597,41 +13868,32 @@ public byte Flag /// public byte SkillIndex { - get => this._data.Span[6]; - set => this._data.Span[6] = value; - } - - /// - /// Gets or sets the skill number. - /// - public ushort SkillNumber - { - get => ReadUInt16LittleEndian(this._data.Span[7..]); - set => WriteUInt16LittleEndian(this._data.Span[7..], value); + get => this._data.Span[5]; + set => this._data.Span[5] = value; } /// - /// Gets or sets the skill level. + /// Gets or sets the skill number and level. /// - public byte SkillLevel + public ushort SkillNumberAndLevel { - get => this._data.Span[9]; - set => this._data.Span[9] = value; + get => ReadUInt16BigEndian(this._data.Span[6..]); + set => WriteUInt16BigEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillAdded(Memory packet) => new (packet, false); + public static implicit operator SkillAdded095(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(SkillAdded packet) => packet._data; + public static implicit operator Memory(SkillAdded095 packet) => packet._data; } @@ -12639,25 +13901,25 @@ public byte SkillLevel /// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. /// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly struct SkillRemoved +public readonly struct SkillRemoved095 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillRemoved(Memory data) + public SkillRemoved095(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillRemoved(Memory data, bool initialize) + private SkillRemoved095(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12711,32 +13973,32 @@ public byte Flag /// public byte SkillIndex { - get => this._data.Span[6]; - set => this._data.Span[6] = value; + get => this._data.Span[5]; + set => this._data.Span[5] = value; } /// - /// Gets or sets the skill number. + /// Gets or sets the skill number and level. /// - public ushort SkillNumber + public ushort SkillNumberAndLevel { - get => ReadUInt16LittleEndian(this._data.Span[7..]); - set => WriteUInt16LittleEndian(this._data.Span[7..], value); + get => ReadUInt16BigEndian(this._data.Span[6..]); + set => WriteUInt16BigEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillRemoved(Memory packet) => new (packet, false); + public static implicit operator SkillRemoved095(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(SkillRemoved packet) => packet._data; + public static implicit operator Memory(SkillRemoved095 packet) => packet._data; } @@ -12744,25 +14006,25 @@ public ushort SkillNumber /// Is sent by the server when: Usually, when the player entered the game with a character. When skills get added or removed, this message is sent as well, but with a misleading count. /// Causes reaction on client side: The skill list gets initialized. /// -public readonly struct SkillListUpdate +public readonly struct SkillListUpdate075 { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillListUpdate(Memory data) + public SkillListUpdate075(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillListUpdate(Memory data, bool initialize) + private SkillListUpdate075(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12808,28 +14070,28 @@ public byte Count /// /// Gets the of the specified index. /// - public SkillEntry this[int index] => new (this._data.Slice(6 + index * SkillEntry.Length)); + public SkillEntry this[int index] => new (this._data.Slice(5 + index * SkillEntry.Length)); /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillListUpdate(Memory packet) => new (packet, false); + public static implicit operator SkillListUpdate075(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(SkillListUpdate packet) => packet._data; + public static implicit operator Memory(SkillListUpdate075 packet) => packet._data; /// /// Calculates the size of the packet for the specified count of . /// /// The count of from which the size will be calculated. - public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntry.Length + 6; + public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntry.Length + 5; /// @@ -12851,7 +14113,7 @@ public SkillEntry(Memory data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 4; + public static int Length => 3; /// /// Gets or sets the skill index. @@ -12863,49 +14125,40 @@ public byte SkillIndex } /// - /// Gets or sets the skill number. - /// - public ushort SkillNumber - { - get => ReadUInt16LittleEndian(this._data.Span[1..]); - set => WriteUInt16LittleEndian(this._data.Span[1..], value); - } - - /// - /// Gets or sets the skill level. + /// Gets or sets the skill number and level. /// - public byte SkillLevel + public ushort SkillNumberAndLevel { - get => this._data.Span[3]; - set => this._data.Span[3] = value; + get => ReadUInt16BigEndian(this._data.Span[1..]); + set => WriteUInt16BigEndian(this._data.Span[1..], value); } } } /// -/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the client focused the character successfully on the server side. +/// Causes reaction on client side: The client highlights the focused character. /// -public readonly struct SkillAdded075 +public readonly struct CharacterFocused { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillAdded075(Memory data) + public CharacterFocused(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillAdded075(Memory data, bool initialize) + private CharacterFocused(Memory data, bool initialize) { this._data = data; if (initialize) @@ -12915,7 +14168,6 @@ private SkillAdded075(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 1; } } @@ -12933,12 +14185,12 @@ private SkillAdded075(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x15; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 15; /// /// Gets the header of this packet. @@ -12946,71 +14198,53 @@ private SkillAdded075(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the flag. - /// - public byte Flag - { - get => this._data.Span[4]; - set => this._data.Span[4] = value; - } - - /// - /// Gets or sets the skill index. - /// - public byte SkillIndex - { - get => this._data.Span[5]; - set => this._data.Span[5] = value; - } - - /// - /// Gets or sets the skill number and level. + /// Gets or sets the character name. /// - public ushort SkillNumberAndLevel + public string CharacterName { - get => ReadUInt16BigEndian(this._data.Span[6..]); - set => WriteUInt16BigEndian(this._data.Span[6..], value); + get => this._data.Span.ExtractString(4, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(4, 10).Span.WriteString(value, System.Text.Encoding.UTF8); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillAdded075(Memory packet) => new (packet, false); + public static implicit operator CharacterFocused(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(SkillAdded075 packet) => packet._data; + public static implicit operator Memory(CharacterFocused packet) => packet._data; } /// -/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the server processed a character stat increase request packet. +/// Causes reaction on client side: If it was successful, adds a point to the requested stat type. /// -public readonly struct SkillRemoved075 +public readonly struct CharacterStatIncreaseResponse { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillRemoved075(Memory data) + public CharacterStatIncreaseResponse(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillRemoved075(Memory data, bool initialize) + private CharacterStatIncreaseResponse(Memory data, bool initialize) { this._data = data; if (initialize) @@ -13020,7 +14254,6 @@ private SkillRemoved075(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 0; } } @@ -13038,12 +14271,12 @@ private SkillRemoved075(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x06; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 10; + public static int Length => 12; /// /// Gets the header of this packet. @@ -13051,71 +14284,89 @@ private SkillRemoved075(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the flag. + /// Gets or sets the success. /// - public byte Flag + public bool Success { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => this._data.Span[4..].GetBoolean(4); + set => this._data.Span[4..].SetBoolean(value, 4); } /// - /// Gets or sets the skill index. + /// Gets or sets the attribute. /// - public byte SkillIndex + public CharacterStatAttribute Attribute { - get => this._data.Span[5]; - set => this._data.Span[5] = value; + get => (CharacterStatAttribute)this._data.Span[4..].GetByteValue(4, 0); + set => this._data.Span[4..].SetByteValue((byte)value, 4, 0); } /// - /// Gets or sets the skill number and level. + /// Gets or sets the updated dependent maximum stat. /// - public ushort SkillNumberAndLevel + public ushort UpdatedDependentMaximumStat { - get => ReadUInt16BigEndian(this._data.Span[6..]); - set => WriteUInt16BigEndian(this._data.Span[6..], value); + get => ReadUInt16LittleEndian(this._data.Span[6..]); + set => WriteUInt16LittleEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the updated maximum shield. + /// + public ushort UpdatedMaximumShield + { + get => ReadUInt16LittleEndian(this._data.Span[8..]); + set => WriteUInt16LittleEndian(this._data.Span[8..], value); + } + + /// + /// Gets or sets the updated maximum ability. + /// + public ushort UpdatedMaximumAbility + { + get => ReadUInt16LittleEndian(this._data.Span[10..]); + set => WriteUInt16LittleEndian(this._data.Span[10..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillRemoved075(Memory packet) => new (packet, false); + public static implicit operator CharacterStatIncreaseResponse(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(SkillRemoved075 packet) => packet._data; + public static implicit operator Memory(CharacterStatIncreaseResponse packet) => packet._data; } /// -/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the server processed a character stat increase request packet. +/// Causes reaction on client side: If it was successful, adds a point to the requested stat type. /// -public readonly struct SkillAdded095 +public readonly struct CharacterStatIncreaseResponseExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillAdded095(Memory data) + public CharacterStatIncreaseResponseExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillAdded095(Memory data, bool initialize) + private CharacterStatIncreaseResponseExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -13125,7 +14376,6 @@ private SkillAdded095(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 0xFE; } } @@ -13143,12 +14393,12 @@ private SkillAdded095(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x06; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 24; /// /// Gets the header of this packet. @@ -13156,71 +14406,119 @@ private SkillAdded095(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the flag. + /// Gets or sets the attribute. /// - public byte Flag + public CharacterStatAttribute Attribute { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => (CharacterStatAttribute)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; } /// - /// Gets or sets the skill index. + /// Gets or sets the added amount. /// - public byte SkillIndex + public ushort AddedAmount { - get => this._data.Span[5]; - set => this._data.Span[5] = value; + get => ReadUInt16LittleEndian(this._data.Span[6..]); + set => WriteUInt16LittleEndian(this._data.Span[6..], value); } /// - /// Gets or sets the skill number and level. + /// Gets or sets the updated maximum health. /// - public ushort SkillNumberAndLevel + public uint UpdatedMaximumHealth { - get => ReadUInt16BigEndian(this._data.Span[6..]); - set => WriteUInt16BigEndian(this._data.Span[6..], value); + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the updated maximum mana. + /// + public uint UpdatedMaximumMana + { + get => ReadUInt32LittleEndian(this._data.Span[12..]); + set => WriteUInt32LittleEndian(this._data.Span[12..], value); + } + + /// + /// Gets or sets the updated maximum shield. + /// + public uint UpdatedMaximumShield + { + get => ReadUInt32LittleEndian(this._data.Span[16..]); + set => WriteUInt32LittleEndian(this._data.Span[16..], value); + } + + /// + /// Gets or sets the updated maximum ability. + /// + public uint UpdatedMaximumAbility + { + get => ReadUInt32LittleEndian(this._data.Span[20..]); + set => WriteUInt32LittleEndian(this._data.Span[20..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillAdded095(Memory packet) => new (packet, false); + public static implicit operator CharacterStatIncreaseResponseExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(SkillAdded095 packet) => packet._data; + public static implicit operator Memory(CharacterStatIncreaseResponseExtended packet) => packet._data; } /// -/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the server processed a character delete response of the client. +/// Causes reaction on client side: If successful, the character is deleted from the character selection screen. Otherwise, a message is shown. /// -public readonly struct SkillRemoved095 +public readonly struct CharacterDeleteResponse { + /// + /// Result of a character delete request. + /// + public enum CharacterDeleteResult + { + /// + /// Deleting was not successful + /// + Unsuccessful = 0, + + /// + /// Deleting was successful + /// + Successful = 1, + + /// + /// Deleting was not successful because a wrong security code was entered + /// + WrongSecurityCode = 2, + } + private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillRemoved095(Memory data) + public CharacterDeleteResponse(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillRemoved095(Memory data, bool initialize) + private CharacterDeleteResponse(Memory data, bool initialize) { this._data = data; if (initialize) @@ -13230,7 +14528,6 @@ private SkillRemoved095(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 0xFF; } } @@ -13248,12 +14545,12 @@ private SkillRemoved095(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x02; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 10; + public static int Length => 5; /// /// Gets the header of this packet. @@ -13261,71 +14558,53 @@ private SkillRemoved095(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the flag. - /// - public byte Flag - { - get => this._data.Span[4]; - set => this._data.Span[4] = value; - } - - /// - /// Gets or sets the skill index. - /// - public byte SkillIndex - { - get => this._data.Span[5]; - set => this._data.Span[5] = value; - } - - /// - /// Gets or sets the skill number and level. + /// Gets or sets the result. /// - public ushort SkillNumberAndLevel + public CharacterDeleteResponse.CharacterDeleteResult Result { - get => ReadUInt16BigEndian(this._data.Span[6..]); - set => WriteUInt16BigEndian(this._data.Span[6..], value); + get => (CharacterDeleteResult)this._data.Span[4]; + set => this._data.Span[4] = (byte)value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillRemoved095(Memory packet) => new (packet, false); + public static implicit operator CharacterDeleteResponse(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(SkillRemoved095 packet) => packet._data; + public static implicit operator Memory(CharacterDeleteResponse packet) => packet._data; } /// -/// Is sent by the server when: Usually, when the player entered the game with a character. When skills get added or removed, this message is sent as well, but with a misleading count. -/// Causes reaction on client side: The skill list gets initialized. +/// Is sent by the server when: After a character leveled up. +/// Causes reaction on client side: Updates the level (and other related stats) in the game client and shows an effect. /// -public readonly struct SkillListUpdate075 +public readonly struct CharacterLevelUpdate { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillListUpdate075(Memory data) + public CharacterLevelUpdate(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillListUpdate075(Memory data, bool initialize) + private CharacterLevelUpdate(Memory data, bool initialize) { this._data = data; if (initialize) @@ -13333,7 +14612,7 @@ private SkillListUpdate075(Memory data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; } } @@ -13352,7 +14631,12 @@ private SkillListUpdate075(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x05; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 24; /// /// Gets the header of this packet. @@ -13360,106 +14644,134 @@ private SkillListUpdate075(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets mixed usage: Skill list count (when list). 0xFE when adding a skill, 0xFF when removing a Skill. + /// Gets or sets the level. + /// + public ushort Level + { + get => ReadUInt16LittleEndian(this._data.Span[4..]); + set => WriteUInt16LittleEndian(this._data.Span[4..], value); + } + + /// + /// Gets or sets the level up points. + /// + public ushort LevelUpPoints + { + get => ReadUInt16LittleEndian(this._data.Span[6..]); + set => WriteUInt16LittleEndian(this._data.Span[6..], value); + } + + /// + /// Gets or sets the maximum health. + /// + public ushort MaximumHealth + { + get => ReadUInt16LittleEndian(this._data.Span[8..]); + set => WriteUInt16LittleEndian(this._data.Span[8..], value); + } + + /// + /// Gets or sets the maximum mana. /// - public byte Count + public ushort MaximumMana { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => ReadUInt16LittleEndian(this._data.Span[10..]); + set => WriteUInt16LittleEndian(this._data.Span[10..], value); } /// - /// Gets the of the specified index. + /// Gets or sets the maximum shield. /// - public SkillEntry this[int index] => new (this._data.Slice(5 + index * SkillEntry.Length)); + public ushort MaximumShield + { + get => ReadUInt16LittleEndian(this._data.Span[12..]); + set => WriteUInt16LittleEndian(this._data.Span[12..], value); + } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the maximum ability. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator SkillListUpdate075(Memory packet) => new (packet, false); + public ushort MaximumAbility + { + get => ReadUInt16LittleEndian(this._data.Span[14..]); + set => WriteUInt16LittleEndian(this._data.Span[14..], value); + } /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the fruit points. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(SkillListUpdate075 packet) => packet._data; + public ushort FruitPoints + { + get => ReadUInt16LittleEndian(this._data.Span[16..]); + set => WriteUInt16LittleEndian(this._data.Span[16..], value); + } /// - /// Calculates the size of the packet for the specified count of . + /// Gets or sets the maximum fruit points. /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntry.Length + 5; - - -/// -/// Structure for a skill entry of the skill list.. -/// -public readonly struct SkillEntry -{ - private readonly Memory _data; + public ushort MaximumFruitPoints + { + get => ReadUInt16LittleEndian(this._data.Span[18..]); + set => WriteUInt16LittleEndian(this._data.Span[18..], value); + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the negative fruit points. /// - /// The underlying data. - public SkillEntry(Memory data) + public ushort NegativeFruitPoints { - this._data = data; + get => ReadUInt16LittleEndian(this._data.Span[20..]); + set => WriteUInt16LittleEndian(this._data.Span[20..], value); } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the maximum negative fruit points. /// - public static int Length => 3; + public ushort MaximumNegativeFruitPoints + { + get => ReadUInt16LittleEndian(this._data.Span[22..]); + set => WriteUInt16LittleEndian(this._data.Span[22..], value); + } /// - /// Gets or sets the skill index. + /// Performs an implicit conversion from a Memory of bytes to a . /// - public byte SkillIndex - { - get => this._data.Span[0]; - set => this._data.Span[0] = value; - } + /// The packet as span. + /// The packet as struct. + public static implicit operator CharacterLevelUpdate(Memory packet) => new (packet, false); /// - /// Gets or sets the skill number and level. + /// Performs an implicit conversion from to a Memory of bytes. /// - public ushort SkillNumberAndLevel - { - get => ReadUInt16BigEndian(this._data.Span[1..]); - set => WriteUInt16BigEndian(this._data.Span[1..], value); - } -} + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(CharacterLevelUpdate packet) => packet._data; } /// -/// Is sent by the server when: After the client focused the character successfully on the server side. -/// Causes reaction on client side: The client highlights the focused character. +/// Is sent by the server when: After the character was selected by the player and entered the game. +/// Causes reaction on client side: The characters enters the game world. /// -public readonly struct CharacterFocused +public readonly struct CharacterInformation { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterFocused(Memory data) + public CharacterInformation(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterFocused(Memory data, bool initialize) + private CharacterInformation(Memory data, bool initialize) { this._data = data; if (initialize) @@ -13475,7 +14787,7 @@ private CharacterFocused(Memory data, bool initialize) /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC1; + public static byte HeaderType => 0xC3; /// /// Gets the operation code of this data packet. @@ -13486,269 +14798,274 @@ private CharacterFocused(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x15; + public static byte SubCode => 0x03; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 15; + public static int Length => 72; /// /// Gets the header of this packet. /// - public C1HeaderWithSubCode Header => new (this._data); + public C3HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the character name. + /// Gets or sets the x. /// - public string CharacterName + public byte X { - get => this._data.Span.ExtractString(4, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(4, 10).Span.WriteString(value, System.Text.Encoding.UTF8); + get => this._data.Span[4]; + set => this._data.Span[4] = value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the y. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator CharacterFocused(Memory packet) => new (packet, false); + public byte Y + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the map id. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(CharacterFocused packet) => packet._data; -} + public ushort MapId + { + get => ReadUInt16LittleEndian(this._data.Span[6..]); + set => WriteUInt16LittleEndian(this._data.Span[6..], value); + } + /// + /// Gets or sets the current experience. + /// + public ulong CurrentExperience + { + get => ReadUInt64BigEndian(this._data.Span[8..]); + set => WriteUInt64BigEndian(this._data.Span[8..], value); + } -/// -/// Is sent by the server when: After the server processed a character stat increase request packet. -/// Causes reaction on client side: If it was successful, adds a point to the requested stat type. -/// -public readonly struct CharacterStatIncreaseResponse -{ - private readonly Memory _data; + /// + /// Gets or sets the experience for next level. + /// + public ulong ExperienceForNextLevel + { + get => ReadUInt64BigEndian(this._data.Span[16..]); + set => WriteUInt64BigEndian(this._data.Span[16..], value); + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the level up points. /// - /// The underlying data. - public CharacterStatIncreaseResponse(Memory data) - : this(data, true) + public ushort LevelUpPoints { + get => ReadUInt16LittleEndian(this._data.Span[24..]); + set => WriteUInt16LittleEndian(this._data.Span[24..], value); } /// - /// Initializes a new instance of the struct. + /// Gets or sets the strength. /// - /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterStatIncreaseResponse(Memory data, bool initialize) + public ushort Strength { - this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; - } + get => ReadUInt16LittleEndian(this._data.Span[26..]); + set => WriteUInt16LittleEndian(this._data.Span[26..], value); } /// - /// Gets the header type of this data packet. + /// Gets or sets the agility. /// - public static byte HeaderType => 0xC1; + public ushort Agility + { + get => ReadUInt16LittleEndian(this._data.Span[28..]); + set => WriteUInt16LittleEndian(this._data.Span[28..], value); + } /// - /// Gets the operation code of this data packet. + /// Gets or sets the vitality. /// - public static byte Code => 0xF3; + public ushort Vitality + { + get => ReadUInt16LittleEndian(this._data.Span[30..]); + set => WriteUInt16LittleEndian(this._data.Span[30..], value); + } /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets or sets the energy. /// - public static byte SubCode => 0x06; + public ushort Energy + { + get => ReadUInt16LittleEndian(this._data.Span[32..]); + set => WriteUInt16LittleEndian(this._data.Span[32..], value); + } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the current health. /// - public static int Length => 12; + public ushort CurrentHealth + { + get => ReadUInt16LittleEndian(this._data.Span[34..]); + set => WriteUInt16LittleEndian(this._data.Span[34..], value); + } /// - /// Gets the header of this packet. + /// Gets or sets the maximum health. /// - public C1HeaderWithSubCode Header => new (this._data); + public ushort MaximumHealth + { + get => ReadUInt16LittleEndian(this._data.Span[36..]); + set => WriteUInt16LittleEndian(this._data.Span[36..], value); + } /// - /// Gets or sets the success. + /// Gets or sets the current mana. /// - public bool Success + public ushort CurrentMana { - get => this._data.Span[4..].GetBoolean(4); - set => this._data.Span[4..].SetBoolean(value, 4); + get => ReadUInt16LittleEndian(this._data.Span[38..]); + set => WriteUInt16LittleEndian(this._data.Span[38..], value); } /// - /// Gets or sets the attribute. + /// Gets or sets the maximum mana. /// - public CharacterStatAttribute Attribute + public ushort MaximumMana { - get => (CharacterStatAttribute)this._data.Span[4..].GetByteValue(4, 0); - set => this._data.Span[4..].SetByteValue((byte)value, 4, 0); + get => ReadUInt16LittleEndian(this._data.Span[40..]); + set => WriteUInt16LittleEndian(this._data.Span[40..], value); } /// - /// Gets or sets the updated dependent maximum stat. + /// Gets or sets the current shield. /// - public ushort UpdatedDependentMaximumStat + public ushort CurrentShield { - get => ReadUInt16LittleEndian(this._data.Span[6..]); - set => WriteUInt16LittleEndian(this._data.Span[6..], value); + get => ReadUInt16LittleEndian(this._data.Span[42..]); + set => WriteUInt16LittleEndian(this._data.Span[42..], value); } /// - /// Gets or sets the updated maximum shield. + /// Gets or sets the maximum shield. /// - public ushort UpdatedMaximumShield + public ushort MaximumShield { - get => ReadUInt16LittleEndian(this._data.Span[8..]); - set => WriteUInt16LittleEndian(this._data.Span[8..], value); + get => ReadUInt16LittleEndian(this._data.Span[44..]); + set => WriteUInt16LittleEndian(this._data.Span[44..], value); } /// - /// Gets or sets the updated maximum ability. + /// Gets or sets the current ability. /// - public ushort UpdatedMaximumAbility + public ushort CurrentAbility { - get => ReadUInt16LittleEndian(this._data.Span[10..]); - set => WriteUInt16LittleEndian(this._data.Span[10..], value); + get => ReadUInt16LittleEndian(this._data.Span[46..]); + set => WriteUInt16LittleEndian(this._data.Span[46..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator CharacterStatIncreaseResponse(Memory packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Gets or sets the maximum ability. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Memory(CharacterStatIncreaseResponse packet) => packet._data; -} - + public ushort MaximumAbility + { + get => ReadUInt16LittleEndian(this._data.Span[48..]); + set => WriteUInt16LittleEndian(this._data.Span[48..], value); + } -/// -/// Is sent by the server when: After the server processed a character delete response of the client. -/// Causes reaction on client side: If successful, the character is deleted from the character selection screen. Otherwise, a message is shown. -/// -public readonly struct CharacterDeleteResponse -{ /// - /// Result of a character delete request. + /// Gets or sets the money. /// - public enum CharacterDeleteResult + public uint Money { - /// - /// Deleting was not successful - /// - Unsuccessful = 0, - - /// - /// Deleting was successful - /// - Successful = 1, - - /// - /// Deleting was not successful because a wrong security code was entered - /// - WrongSecurityCode = 2, + get => ReadUInt32LittleEndian(this._data.Span[52..]); + set => WriteUInt32LittleEndian(this._data.Span[52..], value); } - private readonly Memory _data; - /// - /// Initializes a new instance of the struct. + /// Gets or sets the hero state. /// - /// The underlying data. - public CharacterDeleteResponse(Memory data) - : this(data, true) + public CharacterHeroState HeroState { + get => (CharacterHeroState)this._data.Span[56]; + set => this._data.Span[56] = (byte)value; } /// - /// Initializes a new instance of the struct. + /// Gets or sets the status. /// - /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterDeleteResponse(Memory data, bool initialize) + public CharacterStatus Status { - this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; - } + get => (CharacterStatus)this._data.Span[57]; + set => this._data.Span[57] = (byte)value; } /// - /// Gets the header type of this data packet. + /// Gets or sets the used fruit points. /// - public static byte HeaderType => 0xC1; + public ushort UsedFruitPoints + { + get => ReadUInt16LittleEndian(this._data.Span[58..]); + set => WriteUInt16LittleEndian(this._data.Span[58..], value); + } /// - /// Gets the operation code of this data packet. + /// Gets or sets the max fruit points. /// - public static byte Code => 0xF3; + public ushort MaxFruitPoints + { + get => ReadUInt16LittleEndian(this._data.Span[60..]); + set => WriteUInt16LittleEndian(this._data.Span[60..], value); + } /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets or sets the leadership. /// - public static byte SubCode => 0x02; + public ushort Leadership + { + get => ReadUInt16LittleEndian(this._data.Span[62..]); + set => WriteUInt16LittleEndian(this._data.Span[62..], value); + } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the used negative fruit points. /// - public static int Length => 5; + public ushort UsedNegativeFruitPoints + { + get => ReadUInt16LittleEndian(this._data.Span[64..]); + set => WriteUInt16LittleEndian(this._data.Span[64..], value); + } /// - /// Gets the header of this packet. + /// Gets or sets the max negative fruit points. /// - public C1HeaderWithSubCode Header => new (this._data); + public ushort MaxNegativeFruitPoints + { + get => ReadUInt16LittleEndian(this._data.Span[66..]); + set => WriteUInt16LittleEndian(this._data.Span[66..], value); + } /// - /// Gets or sets the result. + /// Gets or sets the inventory extensions. /// - public CharacterDeleteResponse.CharacterDeleteResult Result + public byte InventoryExtensions { - get => (CharacterDeleteResult)this._data.Span[4]; - set => this._data.Span[4] = (byte)value; + get => this._data.Span[68]; + set => this._data.Span[68] = value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterDeleteResponse(Memory packet) => new (packet, false); + public static implicit operator CharacterInformation(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CharacterDeleteResponse packet) => packet._data; + public static implicit operator Memory(CharacterInformation packet) => packet._data; } @@ -13756,25 +15073,25 @@ public CharacterDeleteResponse.CharacterDeleteResult Result /// Is sent by the server when: After a character leveled up. /// Causes reaction on client side: Updates the level (and other related stats) in the game client and shows an effect. /// -public readonly struct CharacterLevelUpdate +public readonly struct CharacterLevelUpdateExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterLevelUpdate(Memory data) + public CharacterLevelUpdateExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterLevelUpdate(Memory data, bool initialize) + private CharacterLevelUpdateExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -13806,7 +15123,7 @@ private CharacterLevelUpdate(Memory data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 24; + public static int Length => 32; /// /// Gets the header of this packet. @@ -13834,37 +15151,37 @@ public ushort LevelUpPoints /// /// Gets or sets the maximum health. /// - public ushort MaximumHealth + public uint MaximumHealth { - get => ReadUInt16LittleEndian(this._data.Span[8..]); - set => WriteUInt16LittleEndian(this._data.Span[8..], value); + get => ReadUInt32LittleEndian(this._data.Span[8..]); + set => WriteUInt32LittleEndian(this._data.Span[8..], value); } /// /// Gets or sets the maximum mana. /// - public ushort MaximumMana + public uint MaximumMana { - get => ReadUInt16LittleEndian(this._data.Span[10..]); - set => WriteUInt16LittleEndian(this._data.Span[10..], value); + get => ReadUInt32LittleEndian(this._data.Span[12..]); + set => WriteUInt32LittleEndian(this._data.Span[12..], value); } /// /// Gets or sets the maximum shield. /// - public ushort MaximumShield + public uint MaximumShield { - get => ReadUInt16LittleEndian(this._data.Span[12..]); - set => WriteUInt16LittleEndian(this._data.Span[12..], value); + get => ReadUInt32LittleEndian(this._data.Span[16..]); + set => WriteUInt32LittleEndian(this._data.Span[16..], value); } /// /// Gets or sets the maximum ability. /// - public ushort MaximumAbility + public uint MaximumAbility { - get => ReadUInt16LittleEndian(this._data.Span[14..]); - set => WriteUInt16LittleEndian(this._data.Span[14..], value); + get => ReadUInt32LittleEndian(this._data.Span[20..]); + set => WriteUInt32LittleEndian(this._data.Span[20..], value); } /// @@ -13872,8 +15189,8 @@ public ushort MaximumAbility /// public ushort FruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[16..]); - set => WriteUInt16LittleEndian(this._data.Span[16..], value); + get => ReadUInt16LittleEndian(this._data.Span[24..]); + set => WriteUInt16LittleEndian(this._data.Span[24..], value); } /// @@ -13881,8 +15198,8 @@ public ushort FruitPoints /// public ushort MaximumFruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[18..]); - set => WriteUInt16LittleEndian(this._data.Span[18..], value); + get => ReadUInt16LittleEndian(this._data.Span[26..]); + set => WriteUInt16LittleEndian(this._data.Span[26..], value); } /// @@ -13890,8 +15207,8 @@ public ushort MaximumFruitPoints /// public ushort NegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[20..]); - set => WriteUInt16LittleEndian(this._data.Span[20..], value); + get => ReadUInt16LittleEndian(this._data.Span[28..]); + set => WriteUInt16LittleEndian(this._data.Span[28..], value); } /// @@ -13899,23 +15216,23 @@ public ushort NegativeFruitPoints /// public ushort MaximumNegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[22..]); - set => WriteUInt16LittleEndian(this._data.Span[22..], value); + get => ReadUInt16LittleEndian(this._data.Span[30..]); + set => WriteUInt16LittleEndian(this._data.Span[30..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterLevelUpdate(Memory packet) => new (packet, false); + public static implicit operator CharacterLevelUpdateExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CharacterLevelUpdate packet) => packet._data; + public static implicit operator Memory(CharacterLevelUpdateExtended packet) => packet._data; } @@ -13923,25 +15240,25 @@ public ushort MaximumNegativeFruitPoints /// Is sent by the server when: After the character was selected by the player and entered the game. /// Causes reaction on client side: The characters enters the game world. /// -public readonly struct CharacterInformation +public readonly struct CharacterInformationExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterInformation(Memory data) + public CharacterInformationExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterInformation(Memory data, bool initialize) + private CharacterInformationExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -13973,7 +15290,7 @@ private CharacterInformation(Memory data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 72; + public static int Length => 84; /// /// Gets the header of this packet. @@ -14071,75 +15388,84 @@ public ushort Energy } /// - /// Gets or sets the current health. + /// Gets or sets the leadership. /// - public ushort CurrentHealth + public ushort Leadership { get => ReadUInt16LittleEndian(this._data.Span[34..]); set => WriteUInt16LittleEndian(this._data.Span[34..], value); } + /// + /// Gets or sets the current health. + /// + public uint CurrentHealth + { + get => ReadUInt32LittleEndian(this._data.Span[36..]); + set => WriteUInt32LittleEndian(this._data.Span[36..], value); + } + /// /// Gets or sets the maximum health. /// - public ushort MaximumHealth + public uint MaximumHealth { - get => ReadUInt16LittleEndian(this._data.Span[36..]); - set => WriteUInt16LittleEndian(this._data.Span[36..], value); + get => ReadUInt32LittleEndian(this._data.Span[40..]); + set => WriteUInt32LittleEndian(this._data.Span[40..], value); } /// /// Gets or sets the current mana. /// - public ushort CurrentMana + public uint CurrentMana { - get => ReadUInt16LittleEndian(this._data.Span[38..]); - set => WriteUInt16LittleEndian(this._data.Span[38..], value); + get => ReadUInt32LittleEndian(this._data.Span[44..]); + set => WriteUInt32LittleEndian(this._data.Span[44..], value); } /// /// Gets or sets the maximum mana. /// - public ushort MaximumMana + public uint MaximumMana { - get => ReadUInt16LittleEndian(this._data.Span[40..]); - set => WriteUInt16LittleEndian(this._data.Span[40..], value); + get => ReadUInt32LittleEndian(this._data.Span[48..]); + set => WriteUInt32LittleEndian(this._data.Span[48..], value); } /// /// Gets or sets the current shield. /// - public ushort CurrentShield + public uint CurrentShield { - get => ReadUInt16LittleEndian(this._data.Span[42..]); - set => WriteUInt16LittleEndian(this._data.Span[42..], value); + get => ReadUInt32LittleEndian(this._data.Span[52..]); + set => WriteUInt32LittleEndian(this._data.Span[52..], value); } /// /// Gets or sets the maximum shield. /// - public ushort MaximumShield + public uint MaximumShield { - get => ReadUInt16LittleEndian(this._data.Span[44..]); - set => WriteUInt16LittleEndian(this._data.Span[44..], value); + get => ReadUInt32LittleEndian(this._data.Span[56..]); + set => WriteUInt32LittleEndian(this._data.Span[56..], value); } /// /// Gets or sets the current ability. /// - public ushort CurrentAbility + public uint CurrentAbility { - get => ReadUInt16LittleEndian(this._data.Span[46..]); - set => WriteUInt16LittleEndian(this._data.Span[46..], value); + get => ReadUInt32LittleEndian(this._data.Span[60..]); + set => WriteUInt32LittleEndian(this._data.Span[60..], value); } /// /// Gets or sets the maximum ability. /// - public ushort MaximumAbility + public uint MaximumAbility { - get => ReadUInt16LittleEndian(this._data.Span[48..]); - set => WriteUInt16LittleEndian(this._data.Span[48..], value); + get => ReadUInt32LittleEndian(this._data.Span[64..]); + set => WriteUInt32LittleEndian(this._data.Span[64..], value); } /// @@ -14147,8 +15473,8 @@ public ushort MaximumAbility /// public uint Money { - get => ReadUInt32LittleEndian(this._data.Span[52..]); - set => WriteUInt32LittleEndian(this._data.Span[52..], value); + get => ReadUInt32LittleEndian(this._data.Span[68..]); + set => WriteUInt32LittleEndian(this._data.Span[68..], value); } /// @@ -14156,8 +15482,8 @@ public uint Money /// public CharacterHeroState HeroState { - get => (CharacterHeroState)this._data.Span[56]; - set => this._data.Span[56] = (byte)value; + get => (CharacterHeroState)this._data.Span[72]; + set => this._data.Span[72] = (byte)value; } /// @@ -14165,8 +15491,8 @@ public CharacterHeroState HeroState /// public CharacterStatus Status { - get => (CharacterStatus)this._data.Span[57]; - set => this._data.Span[57] = (byte)value; + get => (CharacterStatus)this._data.Span[73]; + set => this._data.Span[73] = (byte)value; } /// @@ -14174,26 +15500,17 @@ public CharacterStatus Status /// public ushort UsedFruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[58..]); - set => WriteUInt16LittleEndian(this._data.Span[58..], value); - } - - /// - /// Gets or sets the max fruit points. - /// - public ushort MaxFruitPoints - { - get => ReadUInt16LittleEndian(this._data.Span[60..]); - set => WriteUInt16LittleEndian(this._data.Span[60..], value); + get => ReadUInt16LittleEndian(this._data.Span[74..]); + set => WriteUInt16LittleEndian(this._data.Span[74..], value); } /// - /// Gets or sets the leadership. + /// Gets or sets the max fruit points. /// - public ushort Leadership + public ushort MaxFruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[62..]); - set => WriteUInt16LittleEndian(this._data.Span[62..], value); + get => ReadUInt16LittleEndian(this._data.Span[76..]); + set => WriteUInt16LittleEndian(this._data.Span[76..], value); } /// @@ -14201,8 +15518,8 @@ public ushort Leadership /// public ushort UsedNegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[64..]); - set => WriteUInt16LittleEndian(this._data.Span[64..], value); + get => ReadUInt16LittleEndian(this._data.Span[78..]); + set => WriteUInt16LittleEndian(this._data.Span[78..], value); } /// @@ -14210,8 +15527,8 @@ public ushort UsedNegativeFruitPoints /// public ushort MaxNegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data.Span[66..]); - set => WriteUInt16LittleEndian(this._data.Span[66..], value); + get => ReadUInt16LittleEndian(this._data.Span[80..]); + set => WriteUInt16LittleEndian(this._data.Span[80..], value); } /// @@ -14219,23 +15536,23 @@ public ushort MaxNegativeFruitPoints /// public byte InventoryExtensions { - get => this._data.Span[68]; - set => this._data.Span[68] = value; + get => this._data.Span[81]; + set => this._data.Span[81] = value; } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterInformation(Memory packet) => new (packet, false); + public static implicit operator CharacterInformationExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(CharacterInformation packet) => packet._data; + public static implicit operator Memory(CharacterInformationExtended packet) => packet._data; } @@ -15605,71 +16922,316 @@ private PlayFanfareSound(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the effect type. + /// Gets or sets the effect type. + /// + public byte EffectType + { + get => this._data.Span[4]; + set => this._data.Span[4] = value; + } + + /// + /// Gets or sets the x. + /// + public byte X + { + get => this._data.Span[5]; + set => this._data.Span[5] = value; + } + + /// + /// Gets or sets the y. + /// + public byte Y + { + get => this._data.Span[6]; + set => this._data.Span[6] = value; + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator PlayFanfareSound(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(PlayFanfareSound packet) => packet._data; +} + + +/// +/// Is sent by the server when: E.g. when event items are dropped to the floor. +/// Causes reaction on client side: The client shows a swirl effect at the specified object. +/// +public readonly struct ShowSwirl +{ + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public ShowSwirl(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ShowSwirl(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + this.EffectType = 58; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x40; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 7; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets the effect type. + /// + public byte EffectType + { + get => this._data.Span[4]; + set => this._data.Span[4] = value; + } + + /// + /// Gets or sets the target object id. + /// + public ushort TargetObjectId + { + get => ReadUInt16BigEndian(this._data.Span[5..]); + set => WriteUInt16BigEndian(this._data.Span[5..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ShowSwirl(Memory packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Memory of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Memory(ShowSwirl packet) => packet._data; +} + + +/// +/// Is sent by the server when: After entering the game with a master class character. +/// Causes reaction on client side: The master related data is available. +/// +public readonly struct MasterStatsUpdate +{ + private readonly Memory _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public MasterStatsUpdate(Memory data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private MasterStatsUpdate(Memory data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x50; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 32; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCode Header => new (this._data); + + /// + /// Gets or sets the master level. + /// + public ushort MasterLevel + { + get => ReadUInt16LittleEndian(this._data.Span[4..]); + set => WriteUInt16LittleEndian(this._data.Span[4..], value); + } + + /// + /// Gets or sets the master experience. + /// + public ulong MasterExperience + { + get => ReadUInt64BigEndian(this._data.Span[6..]); + set => WriteUInt64BigEndian(this._data.Span[6..], value); + } + + /// + /// Gets or sets the master experience of next level. + /// + public ulong MasterExperienceOfNextLevel + { + get => ReadUInt64BigEndian(this._data.Span[14..]); + set => WriteUInt64BigEndian(this._data.Span[14..], value); + } + + /// + /// Gets or sets the master level up points. + /// + public ushort MasterLevelUpPoints + { + get => ReadUInt16LittleEndian(this._data.Span[22..]); + set => WriteUInt16LittleEndian(this._data.Span[22..], value); + } + + /// + /// Gets or sets the maximum health. + /// + public ushort MaximumHealth + { + get => ReadUInt16LittleEndian(this._data.Span[24..]); + set => WriteUInt16LittleEndian(this._data.Span[24..], value); + } + + /// + /// Gets or sets the maximum mana. /// - public byte EffectType + public ushort MaximumMana { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => ReadUInt16LittleEndian(this._data.Span[26..]); + set => WriteUInt16LittleEndian(this._data.Span[26..], value); } /// - /// Gets or sets the x. + /// Gets or sets the maximum shield. /// - public byte X + public ushort MaximumShield { - get => this._data.Span[5]; - set => this._data.Span[5] = value; + get => ReadUInt16LittleEndian(this._data.Span[28..]); + set => WriteUInt16LittleEndian(this._data.Span[28..], value); } /// - /// Gets or sets the y. + /// Gets or sets the maximum ability. /// - public byte Y + public ushort MaximumAbility { - get => this._data.Span[6]; - set => this._data.Span[6] = value; + get => ReadUInt16LittleEndian(this._data.Span[30..]); + set => WriteUInt16LittleEndian(this._data.Span[30..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayFanfareSound(Memory packet) => new (packet, false); + public static implicit operator MasterStatsUpdate(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(PlayFanfareSound packet) => packet._data; + public static implicit operator Memory(MasterStatsUpdate packet) => packet._data; } /// -/// Is sent by the server when: E.g. when event items are dropped to the floor. -/// Causes reaction on client side: The client shows a swirl effect at the specified object. +/// Is sent by the server when: After entering the game with a master class character. +/// Causes reaction on client side: The master related data is available. /// -public readonly struct ShowSwirl +public readonly struct MasterStatsUpdateExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ShowSwirl(Memory data) + public MasterStatsUpdateExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ShowSwirl(Memory data, bool initialize) + private MasterStatsUpdateExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -15679,7 +17241,6 @@ private ShowSwirl(Memory data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.EffectType = 58; } } @@ -15697,12 +17258,12 @@ private ShowSwirl(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x40; + public static byte SubCode => 0x50; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 7; + public static int Length => 40; /// /// Gets the header of this packet. @@ -15710,62 +17271,116 @@ private ShowSwirl(Memory data, bool initialize) public C1HeaderWithSubCode Header => new (this._data); /// - /// Gets or sets the effect type. + /// Gets or sets the master level. /// - public byte EffectType + public ushort MasterLevel { - get => this._data.Span[4]; - set => this._data.Span[4] = value; + get => ReadUInt16LittleEndian(this._data.Span[4..]); + set => WriteUInt16LittleEndian(this._data.Span[4..], value); } /// - /// Gets or sets the target object id. + /// Gets or sets the master experience. /// - public ushort TargetObjectId + public ulong MasterExperience { - get => ReadUInt16BigEndian(this._data.Span[5..]); - set => WriteUInt16BigEndian(this._data.Span[5..], value); + get => ReadUInt64BigEndian(this._data.Span[6..]); + set => WriteUInt64BigEndian(this._data.Span[6..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Gets or sets the master experience of next level. + /// + public ulong MasterExperienceOfNextLevel + { + get => ReadUInt64BigEndian(this._data.Span[14..]); + set => WriteUInt64BigEndian(this._data.Span[14..], value); + } + + /// + /// Gets or sets the master level up points. + /// + public ushort MasterLevelUpPoints + { + get => ReadUInt16LittleEndian(this._data.Span[22..]); + set => WriteUInt16LittleEndian(this._data.Span[22..], value); + } + + /// + /// Gets or sets the maximum health. + /// + public uint MaximumHealth + { + get => ReadUInt32LittleEndian(this._data.Span[24..]); + set => WriteUInt32LittleEndian(this._data.Span[24..], value); + } + + /// + /// Gets or sets the maximum mana. + /// + public uint MaximumMana + { + get => ReadUInt32LittleEndian(this._data.Span[28..]); + set => WriteUInt32LittleEndian(this._data.Span[28..], value); + } + + /// + /// Gets or sets the maximum shield. + /// + public uint MaximumShield + { + get => ReadUInt32LittleEndian(this._data.Span[32..]); + set => WriteUInt32LittleEndian(this._data.Span[32..], value); + } + + /// + /// Gets or sets the maximum ability. + /// + public uint MaximumAbility + { + get => ReadUInt32LittleEndian(this._data.Span[36..]); + set => WriteUInt32LittleEndian(this._data.Span[36..], value); + } + + /// + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ShowSwirl(Memory packet) => new (packet, false); + public static implicit operator MasterStatsUpdateExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(ShowSwirl packet) => packet._data; + public static implicit operator Memory(MasterStatsUpdateExtended packet) => packet._data; } /// -/// Is sent by the server when: After entering the game with a master class character. -/// Causes reaction on client side: The master related data is available. +/// Is sent by the server when: After a master character leveled up. +/// Causes reaction on client side: Updates the master level (and other related stats) in the game client and shows an effect. /// -public readonly struct MasterStatsUpdate +public readonly struct MasterCharacterLevelUpdate { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MasterStatsUpdate(Memory data) + public MasterCharacterLevelUpdate(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MasterStatsUpdate(Memory data, bool initialize) + private MasterCharacterLevelUpdate(Memory data, bool initialize) { this._data = data; if (initialize) @@ -15792,12 +17407,12 @@ private MasterStatsUpdate(Memory data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x50; + public static byte SubCode => 0x51; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 32; + public static int Length => 20; /// /// Gets the header of this packet. @@ -15814,30 +17429,30 @@ public ushort MasterLevel } /// - /// Gets or sets the master experience. + /// Gets or sets the gained master points. /// - public ulong MasterExperience + public ushort GainedMasterPoints { - get => ReadUInt64BigEndian(this._data.Span[6..]); - set => WriteUInt64BigEndian(this._data.Span[6..], value); + get => ReadUInt16LittleEndian(this._data.Span[6..]); + set => WriteUInt16LittleEndian(this._data.Span[6..], value); } /// - /// Gets or sets the master experience of next level. + /// Gets or sets the current master points. /// - public ulong MasterExperienceOfNextLevel + public ushort CurrentMasterPoints { - get => ReadUInt64BigEndian(this._data.Span[14..]); - set => WriteUInt64BigEndian(this._data.Span[14..], value); + get => ReadUInt16LittleEndian(this._data.Span[8..]); + set => WriteUInt16LittleEndian(this._data.Span[8..], value); } /// - /// Gets or sets the master level up points. + /// Gets or sets the maximum master points. /// - public ushort MasterLevelUpPoints + public ushort MaximumMasterPoints { - get => ReadUInt16LittleEndian(this._data.Span[22..]); - set => WriteUInt16LittleEndian(this._data.Span[22..], value); + get => ReadUInt16LittleEndian(this._data.Span[10..]); + set => WriteUInt16LittleEndian(this._data.Span[10..], value); } /// @@ -15845,8 +17460,8 @@ public ushort MasterLevelUpPoints /// public ushort MaximumHealth { - get => ReadUInt16LittleEndian(this._data.Span[24..]); - set => WriteUInt16LittleEndian(this._data.Span[24..], value); + get => ReadUInt16LittleEndian(this._data.Span[12..]); + set => WriteUInt16LittleEndian(this._data.Span[12..], value); } /// @@ -15854,8 +17469,8 @@ public ushort MaximumHealth /// public ushort MaximumMana { - get => ReadUInt16LittleEndian(this._data.Span[26..]); - set => WriteUInt16LittleEndian(this._data.Span[26..], value); + get => ReadUInt16LittleEndian(this._data.Span[14..]); + set => WriteUInt16LittleEndian(this._data.Span[14..], value); } /// @@ -15863,8 +17478,8 @@ public ushort MaximumMana /// public ushort MaximumShield { - get => ReadUInt16LittleEndian(this._data.Span[28..]); - set => WriteUInt16LittleEndian(this._data.Span[28..], value); + get => ReadUInt16LittleEndian(this._data.Span[16..]); + set => WriteUInt16LittleEndian(this._data.Span[16..], value); } /// @@ -15872,23 +17487,23 @@ public ushort MaximumShield /// public ushort MaximumAbility { - get => ReadUInt16LittleEndian(this._data.Span[30..]); - set => WriteUInt16LittleEndian(this._data.Span[30..], value); + get => ReadUInt16LittleEndian(this._data.Span[18..]); + set => WriteUInt16LittleEndian(this._data.Span[18..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MasterStatsUpdate(Memory packet) => new (packet, false); + public static implicit operator MasterCharacterLevelUpdate(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(MasterStatsUpdate packet) => packet._data; + public static implicit operator Memory(MasterCharacterLevelUpdate packet) => packet._data; } @@ -15896,25 +17511,25 @@ public ushort MaximumAbility /// Is sent by the server when: After a master character leveled up. /// Causes reaction on client side: Updates the master level (and other related stats) in the game client and shows an effect. /// -public readonly struct MasterCharacterLevelUpdate +public readonly struct MasterCharacterLevelUpdateExtended { private readonly Memory _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MasterCharacterLevelUpdate(Memory data) + public MasterCharacterLevelUpdateExtended(Memory data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MasterCharacterLevelUpdate(Memory data, bool initialize) + private MasterCharacterLevelUpdateExtended(Memory data, bool initialize) { this._data = data; if (initialize) @@ -15946,7 +17561,7 @@ private MasterCharacterLevelUpdate(Memory data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 20; + public static int Length => 28; /// /// Gets the header of this packet. @@ -15992,52 +17607,52 @@ public ushort MaximumMasterPoints /// /// Gets or sets the maximum health. /// - public ushort MaximumHealth + public uint MaximumHealth { - get => ReadUInt16LittleEndian(this._data.Span[12..]); - set => WriteUInt16LittleEndian(this._data.Span[12..], value); + get => ReadUInt32LittleEndian(this._data.Span[12..]); + set => WriteUInt32LittleEndian(this._data.Span[12..], value); } /// /// Gets or sets the maximum mana. /// - public ushort MaximumMana + public uint MaximumMana { - get => ReadUInt16LittleEndian(this._data.Span[14..]); - set => WriteUInt16LittleEndian(this._data.Span[14..], value); + get => ReadUInt32LittleEndian(this._data.Span[16..]); + set => WriteUInt32LittleEndian(this._data.Span[16..], value); } /// /// Gets or sets the maximum shield. /// - public ushort MaximumShield + public uint MaximumShield { - get => ReadUInt16LittleEndian(this._data.Span[16..]); - set => WriteUInt16LittleEndian(this._data.Span[16..], value); + get => ReadUInt32LittleEndian(this._data.Span[20..]); + set => WriteUInt32LittleEndian(this._data.Span[20..], value); } /// /// Gets or sets the maximum ability. /// - public ushort MaximumAbility + public uint MaximumAbility { - get => ReadUInt16LittleEndian(this._data.Span[18..]); - set => WriteUInt16LittleEndian(this._data.Span[18..], value); + get => ReadUInt32LittleEndian(this._data.Span[24..]); + set => WriteUInt32LittleEndian(this._data.Span[24..], value); } /// - /// Performs an implicit conversion from a Memory of bytes to a . + /// Performs an implicit conversion from a Memory of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MasterCharacterLevelUpdate(Memory packet) => new (packet, false); + public static implicit operator MasterCharacterLevelUpdateExtended(Memory packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Memory of bytes. + /// Performs an implicit conversion from to a Memory of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Memory(MasterCharacterLevelUpdate packet) => packet._data; + public static implicit operator Memory(MasterCharacterLevelUpdateExtended packet) => packet._data; } @@ -26507,3 +28122,49 @@ public enum CharacterCreationUnlockFlags RageFighter = 8, } + /// + /// Defines the kind of the damage. + /// + public enum DamageKind + { + /// + /// Red color, used by normal damage. + /// + NormalRed = 0, + + /// + /// Cyan color, usually used by ignore defense damage. + /// + IgnoreDefenseCyan = 1, + + /// + /// Light green color, usually used by excellent damage. + /// + ExcellentLightGreen = 2, + + /// + /// Blue color, usually used by critical damage. + /// + CriticalBlue = 3, + + /// + /// Light pink color. + /// + LightPink = 4, + + /// + /// Dark green color, usually used by poison damage. + /// + PoisonDarkGreen = 5, + + /// + /// Dark pink color, usually used by reflected damage. + /// + ReflectedDarkPink = 6, + + /// + /// White color. + /// + White = 7, + } + diff --git a/src/Network/Packets/ServerToClient/ServerToClientPackets.xml b/src/Network/Packets/ServerToClient/ServerToClientPackets.xml index 47dde8f4a..c377f91e5 100644 --- a/src/Network/Packets/ServerToClient/ServerToClientPackets.xml +++ b/src/Network/Packets/ServerToClient/ServerToClientPackets.xml @@ -2164,54 +2164,53 @@ ShieldDamage - - - DamageKind - Defines the kind of the damage. - - - NormalRed - Red color, used by normal damage. - 0 - - - IgnoreDefenseCyan - Cyan color, usually used by ignore defense damage. - 1 - - - ExcellentLightGreen - Light green color, usually used by excellent damage. - 2 - - - CriticalBlue - Blue color, usually used by critical damage. - 3 - - - LightPink - Light pink color. - 4 - - - PoisonDarkGreen - Dark green color, usually used by poison damage. - 5 - - - ReflectedDarkPink - Dark pink color, usually used by reflected damage. - 6 - - - White - White color. - 7 - - - - + + + C1Header + 11 + ObjectHitExtended + 16 + ServerToClient + An object got hit in two cases: 1. When the own player is hit; 2. When the own player attacked some other object which got hit. + The damage is shown at the object which received the hit. + + + 3 + 0 + Enum + DamageKind + Kind + 4 + + + 3 + 6 + Boolean + IsDoubleDamage + + + 3 + 7 + Boolean + IsTripleDamage + + + 4 + ShortLittleEndian + ObjectId + + + 8 + IntegerLittleEndian + HealthDamage + + + + 12 + IntegerLittleEndian + ShieldDamage + + C1Header @@ -2352,6 +2351,76 @@ + + C3Header + 16 + ExperienceGainedExtended + 16 + ServerToClient + A player gained experience. + The experience is added to the experience counter and bar. + + + 3 + Enum + AddResult + Type + + + 4 + IntegerLittleEndian + AddedExperience + + + 8 + IntegerLittleEndian + DamageOfLastHit + + + 12 + ShortLittleEndian + KilledObjectId + + + 14 + ShortLittleEndian + KillerObjectId + + + + + AddResult + Defines the result and type of experience which is added. + + + Normal + The normal experience is added. + 1 + + + Master + The master experience is added. + 2 + + + MaxLevelReached + The maximum level has been reached, no experience is added. + 0x10 + + + MaxMasterLevelReached + The maximum master level has been reached, no master experience is added. + 0x20 + + + MonsterLevelTooLowForMasterExperience + The monster level is too low for master experience, no master experience is added. + 0x21 + + + + + C3HeaderWithSubCode 1C @@ -2820,6 +2889,28 @@ + + C1HeaderWithSubCode + 26 + FF + CurrentHealthAndShieldExtended + 12 + ServerToClient + Periodically, or if the current health or shield changed on the server side, e.g. by hits. + The health and shield bar is updated on the game client user interface. + + + 4 + IntegerLittleEndian + Health + + + 8 + IntegerLittleEndian + Shield + + + C1HeaderWithSubCode 26 @@ -2842,6 +2933,28 @@ + + C1HeaderWithSubCode + 26 + FE + MaximumHealthAndShieldExtended + 12 + ServerToClient + When the maximum health changed, e.g. by adding stat points or changed items. + The health and shield bar is updated on the game client user interface. + + + 4 + IntegerLittleEndian + Health + + + 8 + IntegerLittleEndian + Shield + + + C1HeaderWithSubCode 26 @@ -2864,6 +2977,28 @@ + + C1HeaderWithSubCode + 26 + FD + ItemConsumptionFailedExtended + 12 + ServerToClient + When the consumption of an item failed. + The game client gets a feedback about a failed consumption, and allows for do further consumption requests. + + + 4 + IntegerLittleEndian + Health + + + 8 + IntegerLittleEndian + Shield + + + C1HeaderWithSubCode 27 @@ -2886,6 +3021,28 @@ + + C1HeaderWithSubCode + 27 + FF + CurrentManaAndAbilityExtended + 12 + ServerToClient + The currently available mana or ability has changed, e.g. by using a skill. + The mana and ability bar is updated on the game client user interface. + + + 4 + IntegerLittleEndian + Mana + + + 8 + IntegerLittleEndian + Ability + + + C1HeaderWithSubCode 27 @@ -2908,6 +3065,28 @@ + + C1HeaderWithSubCode + 27 + FE + MaximumManaAndAbilityExtended + 12 + ServerToClient + The maximum available mana or ability has changed, e.g. by adding stat points. + The mana and ability bar is updated on the game client user interface. + + + 4 + IntegerLittleEndian + Mana + + + 8 + IntegerLittleEndian + Ability + + + C1Header 28 @@ -4917,69 +5096,323 @@ 4 - 6 + 6 + ShortLittleEndian + UpdatedDependentMaximumStat + + + 8 + ShortLittleEndian + UpdatedMaximumShield + + + 10 + ShortLittleEndian + UpdatedMaximumAbility + + + + + C1HeaderWithSubCode + F3 + 06 + CharacterStatIncreaseResponseExtended + 24 + ServerToClient + After the server processed a character stat increase request packet. + If it was successful, adds a point to the requested stat type. + + + 4 + Enum + CharacterStatAttribute + Attribute + + + 6 + ShortLittleEndian + AddedAmount + + + 8 + IntegerLittleEndian + UpdatedMaximumHealth + + + 12 + IntegerLittleEndian + UpdatedMaximumMana + + + 16 + IntegerLittleEndian + UpdatedMaximumShield + + + 20 + IntegerLittleEndian + UpdatedMaximumAbility + + + + + C1HeaderWithSubCode + F3 + 02 + CharacterDeleteResponse + 5 + ServerToClient + After the server processed a character delete response of the client. + If successful, the character is deleted from the character selection screen. Otherwise, a message is shown. + + + 4 + Enum + CharacterDeleteResult + Result + + + + + CharacterDeleteResult + Result of a character delete request. + + + Unsuccessful + Deleting was not successful + 0 + + + Successful + Deleting was successful + 1 + + + WrongSecurityCode + Deleting was not successful because a wrong security code was entered + 2 + + + + + + + C1HeaderWithSubCode + F3 + 05 + CharacterLevelUpdate + 24 + ServerToClient + After a character leveled up. + Updates the level (and other related stats) in the game client and shows an effect. + + + 4 + ShortLittleEndian + Level + + + 6 + ShortLittleEndian + LevelUpPoints + + + 8 + ShortLittleEndian + MaximumHealth + + + 10 + ShortLittleEndian + MaximumMana + + + 12 + ShortLittleEndian + MaximumShield + + + 14 + ShortLittleEndian + MaximumAbility + + + 16 + ShortLittleEndian + FruitPoints + + + 18 + ShortLittleEndian + MaximumFruitPoints + + + 20 + ShortLittleEndian + NegativeFruitPoints + + + 22 + ShortLittleEndian + MaximumNegativeFruitPoints + + + + + C3HeaderWithSubCode + F3 + 03 + CharacterInformation + 72 + ServerToClient + After the character was selected by the player and entered the game. + The characters enters the game world. + + + 4 + Byte + X + + + 5 + Byte + Y + + + 6 + ShortLittleEndian + MapId + + + 8 + LongBigEndian + CurrentExperience + + + 16 + LongBigEndian + ExperienceForNextLevel + + + 24 + ShortLittleEndian + LevelUpPoints + + + 26 + ShortLittleEndian + Strength + + + 28 + ShortLittleEndian + Agility + + + 30 + ShortLittleEndian + Vitality + + + 32 + ShortLittleEndian + Energy + + + 34 + ShortLittleEndian + CurrentHealth + + + 36 + ShortLittleEndian + MaximumHealth + + + 38 + ShortLittleEndian + CurrentMana + + + 40 + ShortLittleEndian + MaximumMana + + + 42 + ShortLittleEndian + CurrentShield + + + 44 + ShortLittleEndian + MaximumShield + + + 46 + ShortLittleEndian + CurrentAbility + + + 48 + ShortLittleEndian + MaximumAbility + + + 52 + IntegerLittleEndian + Money + + + 56 + Enum + CharacterHeroState + HeroState + + + 57 + Enum + CharacterStatus + Status + + + 58 + ShortLittleEndian + UsedFruitPoints + + + 60 + ShortLittleEndian + MaxFruitPoints + + + 62 ShortLittleEndian - UpdatedDependentMaximumStat + Leadership - 8 + 64 ShortLittleEndian - UpdatedMaximumShield + UsedNegativeFruitPoints - 10 + 66 ShortLittleEndian - UpdatedMaximumAbility + MaxNegativeFruitPoints - - - - C1HeaderWithSubCode - F3 - 02 - CharacterDeleteResponse - 5 - ServerToClient - After the server processed a character delete response of the client. - If successful, the character is deleted from the character selection screen. Otherwise, a message is shown. - - 4 - Enum - CharacterDeleteResult - Result + 68 + Byte + InventoryExtensions - - - CharacterDeleteResult - Result of a character delete request. - - - Unsuccessful - Deleting was not successful - 0 - - - Successful - Deleting was successful - 1 - - - WrongSecurityCode - Deleting was not successful because a wrong security code was entered - 2 - - - - C1HeaderWithSubCode F3 05 - CharacterLevelUpdate - 24 + CharacterLevelUpdateExtended + 32 ServerToClient After a character leveled up. Updates the level (and other related stats) in the game client and shows an effect. @@ -4996,41 +5429,41 @@ 8 - ShortLittleEndian + IntegerLittleEndian MaximumHealth - 10 - ShortLittleEndian + 12 + IntegerLittleEndian MaximumMana - 12 - ShortLittleEndian + 16 + IntegerLittleEndian MaximumShield - 14 - ShortLittleEndian + 20 + IntegerLittleEndian MaximumAbility - 16 + 24 ShortLittleEndian FruitPoints - 18 + 26 ShortLittleEndian MaximumFruitPoints - 20 + 28 ShortLittleEndian NegativeFruitPoints - 22 + 30 ShortLittleEndian MaximumNegativeFruitPoints @@ -5040,8 +5473,8 @@ C3HeaderWithSubCode F3 03 - CharacterInformation - 72 + CharacterInformationExtended + 84 ServerToClient After the character was selected by the player and entered the game. The characters enters the game world. @@ -5099,87 +5532,87 @@ 34 ShortLittleEndian - CurrentHealth + Leadership 36 - ShortLittleEndian + IntegerLittleEndian + CurrentHealth + + + 40 + IntegerLittleEndian MaximumHealth - 38 - ShortLittleEndian + 44 + IntegerLittleEndian CurrentMana - 40 - ShortLittleEndian + 48 + IntegerLittleEndian MaximumMana - 42 - ShortLittleEndian + 52 + IntegerLittleEndian CurrentShield - 44 - ShortLittleEndian + 56 + IntegerLittleEndian MaximumShield - 46 - ShortLittleEndian + 60 + IntegerLittleEndian CurrentAbility - 48 - ShortLittleEndian + 64 + IntegerLittleEndian MaximumAbility - 52 + 68 IntegerLittleEndian Money - 56 + 72 Enum CharacterHeroState HeroState - 57 + 73 Enum CharacterStatus Status - 58 + 74 ShortLittleEndian UsedFruitPoints - 60 + 76 ShortLittleEndian MaxFruitPoints - 62 - ShortLittleEndian - Leadership - - - 64 + 78 ShortLittleEndian UsedNegativeFruitPoints - 66 + 80 ShortLittleEndian MaxNegativeFruitPoints - 68 + 81 Byte InventoryExtensions @@ -5711,6 +6144,58 @@ + + C1HeaderWithSubCode + F3 + 50 + MasterStatsUpdateExtended + 40 + ServerToClient + After entering the game with a master class character. + The master related data is available. + + + 4 + ShortLittleEndian + MasterLevel + + + 6 + LongBigEndian + MasterExperience + + + 14 + LongBigEndian + MasterExperienceOfNextLevel + + + 22 + ShortLittleEndian + MasterLevelUpPoints + + + 24 + IntegerLittleEndian + MaximumHealth + + + 28 + IntegerLittleEndian + MaximumMana + + + 32 + IntegerLittleEndian + MaximumShield + + + 36 + IntegerLittleEndian + MaximumAbility + + + C1HeaderWithSubCode F3 @@ -5763,6 +6248,58 @@ + + C1HeaderWithSubCode + F3 + 51 + MasterCharacterLevelUpdateExtended + 28 + ServerToClient + After a master character leveled up. + Updates the master level (and other related stats) in the game client and shows an effect. + + + 4 + ShortLittleEndian + MasterLevel + + + 6 + ShortLittleEndian + GainedMasterPoints + + + 8 + ShortLittleEndian + CurrentMasterPoints + + + 10 + ShortLittleEndian + MaximumMasterPoints + + + 12 + IntegerLittleEndian + MaximumHealth + + + 16 + IntegerLittleEndian + MaximumMana + + + 20 + IntegerLittleEndian + MaximumShield + + + 24 + IntegerLittleEndian + MaximumAbility + + + C1HeaderWithSubCode F3 @@ -9573,5 +10110,51 @@ + + DamageKind + Defines the kind of the damage. + + + NormalRed + Red color, used by normal damage. + 0 + + + IgnoreDefenseCyan + Cyan color, usually used by ignore defense damage. + 1 + + + ExcellentLightGreen + Light green color, usually used by excellent damage. + 2 + + + CriticalBlue + Blue color, usually used by critical damage. + 3 + + + LightPink + Light pink color. + 4 + + + PoisonDarkGreen + Dark green color, usually used by poison damage. + 5 + + + ReflectedDarkPink + Dark pink color, usually used by reflected damage. + 6 + + + White + White color. + 7 + + + \ No newline at end of file diff --git a/src/Network/Packets/ServerToClient/ServerToClientPacketsRef.cs b/src/Network/Packets/ServerToClient/ServerToClientPacketsRef.cs index 0f0bdf34d..701c0d16b 100644 --- a/src/Network/Packets/ServerToClient/ServerToClientPacketsRef.cs +++ b/src/Network/Packets/ServerToClient/ServerToClientPacketsRef.cs @@ -5803,9 +5803,9 @@ public ushort HealthDamage /// /// Gets or sets the kind. /// - public ObjectHit.DamageKind Kind + public DamageKind Kind { - get => (ObjectHit.DamageKind)this._data[7..].GetByteValue(4, 0); + get => (DamageKind)this._data[7..].GetByteValue(4, 0); set => this._data[7..].SetByteValue((byte)value, 4, 0); } @@ -5852,6 +5852,130 @@ public ushort ShieldDamage } +/// +/// Is sent by the server when: An object got hit in two cases: 1. When the own player is hit; 2. When the own player attacked some other object which got hit. +/// Causes reaction on client side: The damage is shown at the object which received the hit. +/// +public readonly ref struct ObjectHitExtendedRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public ObjectHitExtendedRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ObjectHitExtendedRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x11; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 16; + + /// + /// Gets the header of this packet. + /// + public C1HeaderRef Header => new (this._data); + + /// + /// Gets or sets the kind. + /// + public DamageKind Kind + { + get => (DamageKind)this._data[3..].GetByteValue(4, 0); + set => this._data[3..].SetByteValue((byte)value, 4, 0); + } + + /// + /// Gets or sets the is double damage. + /// + public bool IsDoubleDamage + { + get => this._data[3..].GetBoolean(6); + set => this._data[3..].SetBoolean(value, 6); + } + + /// + /// Gets or sets the is triple damage. + /// + public bool IsTripleDamage + { + get => this._data[3..].GetBoolean(7); + set => this._data[3..].SetBoolean(value, 7); + } + + /// + /// Gets or sets the object id. + /// + public ushort ObjectId + { + get => ReadUInt16LittleEndian(this._data[4..]); + set => WriteUInt16LittleEndian(this._data[4..], value); + } + + /// + /// Gets or sets the health damage. + /// + public uint HealthDamage + { + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); + } + + /// + /// Gets or sets the shield damage. + /// + public uint ShieldDamage + { + get => ReadUInt32LittleEndian(this._data[12..]); + set => WriteUInt32LittleEndian(this._data[12..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ObjectHitExtendedRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(ObjectHitExtendedRef packet) => packet._data; +} + + /// /// Is sent by the server when: An object in the observed scope (including the own player) moved instantly. /// Causes reaction on client side: The position of the object is updated on client side. @@ -6295,6 +6419,121 @@ public ushort DamageOfLastHit } +/// +/// Is sent by the server when: A player gained experience. +/// Causes reaction on client side: The experience is added to the experience counter and bar. +/// +public readonly ref struct ExperienceGainedExtendedRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public ExperienceGainedExtendedRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ExperienceGainedExtendedRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC3; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x16; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 16; + + /// + /// Gets the header of this packet. + /// + public C3HeaderRef Header => new (this._data); + + /// + /// Gets or sets the type. + /// + public ExperienceGainedExtended.AddResult Type + { + get => (ExperienceGainedExtended.AddResult)this._data[3]; + set => this._data[3] = (byte)value; + } + + /// + /// Gets or sets the added experience. + /// + public uint AddedExperience + { + get => ReadUInt32LittleEndian(this._data[4..]); + set => WriteUInt32LittleEndian(this._data[4..], value); + } + + /// + /// Gets or sets the damage of last hit. + /// + public uint DamageOfLastHit + { + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); + } + + /// + /// Gets or sets the killed object id. + /// + public ushort KilledObjectId + { + get => ReadUInt16LittleEndian(this._data[12..]); + set => WriteUInt16LittleEndian(this._data[12..], value); + } + + /// + /// Gets or sets the killer object id. + /// + public ushort KillerObjectId + { + get => ReadUInt16LittleEndian(this._data[14..]); + set => WriteUInt16LittleEndian(this._data[14..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ExperienceGainedExtendedRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(ExperienceGainedExtendedRef packet) => packet._data; +} + + /// /// Is sent by the server when: The map was changed on the server side. /// Causes reaction on client side: The game client changes to the specified map and coordinates. @@ -7790,28 +8029,28 @@ public ushort Shield /// -/// Is sent by the server when: When the maximum health changed, e.g. by adding stat points or changed items. +/// Is sent by the server when: Periodically, or if the current health or shield changed on the server side, e.g. by hits. /// Causes reaction on client side: The health and shield bar is updated on the game client user interface. /// -public readonly ref struct MaximumHealthAndShieldRef +public readonly ref struct CurrentHealthAndShieldExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MaximumHealthAndShieldRef(Span data) + public CurrentHealthAndShieldExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MaximumHealthAndShieldRef(Span data, bool initialize) + private CurrentHealthAndShieldExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -7838,12 +8077,12 @@ private MaximumHealthAndShieldRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFE; + public static byte SubCode => 0xFF; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 9; + public static int Length => 12; /// /// Gets the header of this packet. @@ -7853,60 +8092,60 @@ private MaximumHealthAndShieldRef(Span data, bool initialize) /// /// Gets or sets the health. /// - public ushort Health + public uint Health { - get => ReadUInt16BigEndian(this._data[4..]); - set => WriteUInt16BigEndian(this._data[4..], value); + get => ReadUInt32LittleEndian(this._data[4..]); + set => WriteUInt32LittleEndian(this._data[4..], value); } /// /// Gets or sets the shield. /// - public ushort Shield + public uint Shield { - get => ReadUInt16BigEndian(this._data[7..]); - set => WriteUInt16BigEndian(this._data[7..], value); + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MaximumHealthAndShieldRef(Span packet) => new (packet, false); + public static implicit operator CurrentHealthAndShieldExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(MaximumHealthAndShieldRef packet) => packet._data; + public static implicit operator Span(CurrentHealthAndShieldExtendedRef packet) => packet._data; } /// -/// Is sent by the server when: When the consumption of an item failed. -/// Causes reaction on client side: The game client gets a feedback about a failed consumption, and allows for do further consumption requests. +/// Is sent by the server when: When the maximum health changed, e.g. by adding stat points or changed items. +/// Causes reaction on client side: The health and shield bar is updated on the game client user interface. /// -public readonly ref struct ItemConsumptionFailedRef +public readonly ref struct MaximumHealthAndShieldRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemConsumptionFailedRef(Span data) + public MaximumHealthAndShieldRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemConsumptionFailedRef(Span data, bool initialize) + private MaximumHealthAndShieldRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -7933,7 +8172,7 @@ private ItemConsumptionFailedRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFD; + public static byte SubCode => 0xFE; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. @@ -7964,44 +8203,44 @@ public ushort Shield } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemConsumptionFailedRef(Span packet) => new (packet, false); + public static implicit operator MaximumHealthAndShieldRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ItemConsumptionFailedRef packet) => packet._data; + public static implicit operator Span(MaximumHealthAndShieldRef packet) => packet._data; } /// -/// Is sent by the server when: The currently available mana or ability has changed, e.g. by using a skill. -/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. +/// Is sent by the server when: When the maximum health changed, e.g. by adding stat points or changed items. +/// Causes reaction on client side: The health and shield bar is updated on the game client user interface. /// -public readonly ref struct CurrentManaAndAbilityRef +public readonly ref struct MaximumHealthAndShieldExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CurrentManaAndAbilityRef(Span data) + public MaximumHealthAndShieldExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CurrentManaAndAbilityRef(Span data, bool initialize) + private MaximumHealthAndShieldExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8022,18 +8261,18 @@ private CurrentManaAndAbilityRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x27; + public static byte Code => 0x26; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFF; + public static byte SubCode => 0xFE; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 12; /// /// Gets the header of this packet. @@ -8041,62 +8280,62 @@ private CurrentManaAndAbilityRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the mana. + /// Gets or sets the health. /// - public ushort Mana + public uint Health { - get => ReadUInt16BigEndian(this._data[4..]); - set => WriteUInt16BigEndian(this._data[4..], value); + get => ReadUInt32LittleEndian(this._data[4..]); + set => WriteUInt32LittleEndian(this._data[4..], value); } /// - /// Gets or sets the ability. + /// Gets or sets the shield. /// - public ushort Ability + public uint Shield { - get => ReadUInt16BigEndian(this._data[6..]); - set => WriteUInt16BigEndian(this._data[6..], value); + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CurrentManaAndAbilityRef(Span packet) => new (packet, false); + public static implicit operator MaximumHealthAndShieldExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CurrentManaAndAbilityRef packet) => packet._data; + public static implicit operator Span(MaximumHealthAndShieldExtendedRef packet) => packet._data; } /// -/// Is sent by the server when: The maximum available mana or ability has changed, e.g. by adding stat points. -/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. +/// Is sent by the server when: When the consumption of an item failed. +/// Causes reaction on client side: The game client gets a feedback about a failed consumption, and allows for do further consumption requests. /// -public readonly ref struct MaximumManaAndAbilityRef +public readonly ref struct ItemConsumptionFailedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MaximumManaAndAbilityRef(Span data) + public ItemConsumptionFailedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MaximumManaAndAbilityRef(Span data, bool initialize) + private ItemConsumptionFailedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8117,18 +8356,18 @@ private MaximumManaAndAbilityRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x27; + public static byte Code => 0x26; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0xFE; + public static byte SubCode => 0xFD; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 9; /// /// Gets the header of this packet. @@ -8136,62 +8375,62 @@ private MaximumManaAndAbilityRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the mana. + /// Gets or sets the health. /// - public ushort Mana + public ushort Health { get => ReadUInt16BigEndian(this._data[4..]); set => WriteUInt16BigEndian(this._data[4..], value); } /// - /// Gets or sets the ability. + /// Gets or sets the shield. /// - public ushort Ability + public ushort Shield { - get => ReadUInt16BigEndian(this._data[6..]); - set => WriteUInt16BigEndian(this._data[6..], value); + get => ReadUInt16BigEndian(this._data[7..]); + set => WriteUInt16BigEndian(this._data[7..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MaximumManaAndAbilityRef(Span packet) => new (packet, false); + public static implicit operator ItemConsumptionFailedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(MaximumManaAndAbilityRef packet) => packet._data; + public static implicit operator Span(ItemConsumptionFailedRef packet) => packet._data; } /// -/// Is sent by the server when: The item has been removed from the inventory of the player. -/// Causes reaction on client side: The client removes the item in the inventory user interface. +/// Is sent by the server when: When the consumption of an item failed. +/// Causes reaction on client side: The game client gets a feedback about a failed consumption, and allows for do further consumption requests. /// -public readonly ref struct ItemRemovedRef +public readonly ref struct ItemConsumptionFailedExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemRemovedRef(Span data) + public ItemConsumptionFailedExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemRemovedRef(Span data, bool initialize) + private ItemConsumptionFailedExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8200,7 +8439,7 @@ private ItemRemovedRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); - this.TrueFlag = 1; + header.SubCode = SubCode; } } @@ -8212,75 +8451,81 @@ private ItemRemovedRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x28; + public static byte Code => 0x26; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0xFD; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 5; + public static int Length => 12; /// /// Gets the header of this packet. /// - public C1HeaderRef Header => new (this._data); + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the affected slot of the item in the inventory. + /// Gets or sets the health. /// - public byte InventorySlot + public uint Health { - get => this._data[3]; - set => this._data[3] = value; + get => ReadUInt32LittleEndian(this._data[4..]); + set => WriteUInt32LittleEndian(this._data[4..], value); } /// - /// Gets or sets the true flag. + /// Gets or sets the shield. /// - public byte TrueFlag + public uint Shield { - get => this._data[4]; - set => this._data[4] = value; + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemRemovedRef(Span packet) => new (packet, false); + public static implicit operator ItemConsumptionFailedExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ItemRemovedRef packet) => packet._data; + public static implicit operator Span(ItemConsumptionFailedExtendedRef packet) => packet._data; } /// -/// Is sent by the server when: The client requested to consume a special item, e.g. a bottle of Ale. -/// Causes reaction on client side: The player is shown in a red color and has increased attack speed. +/// Is sent by the server when: The currently available mana or ability has changed, e.g. by using a skill. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly ref struct ConsumeItemWithEffectRef +public readonly ref struct CurrentManaAndAbilityRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ConsumeItemWithEffectRef(Span data) + public CurrentManaAndAbilityRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ConsumeItemWithEffectRef(Span data, bool initialize) + private CurrentManaAndAbilityRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8289,86 +8534,93 @@ private ConsumeItemWithEffectRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC3; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x29; + public static byte Code => 0x27; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0xFF; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 6; + public static int Length => 8; /// /// Gets the header of this packet. /// - public C3HeaderRef Header => new (this._data); + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the item type. + /// Gets or sets the mana. /// - public ConsumeItemWithEffect.ConsumedItemType ItemType + public ushort Mana { - get => (ConsumeItemWithEffect.ConsumedItemType)this._data[3]; - set => this._data[3] = (byte)value; + get => ReadUInt16BigEndian(this._data[4..]); + set => WriteUInt16BigEndian(this._data[4..], value); } /// - /// Gets or sets the effect time in seconds. + /// Gets or sets the ability. /// - public ushort EffectTimeInSeconds + public ushort Ability { - get => ReadUInt16BigEndian(this._data[4..]); - set => WriteUInt16BigEndian(this._data[4..], value); + get => ReadUInt16BigEndian(this._data[6..]); + set => WriteUInt16BigEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ConsumeItemWithEffectRef(Span packet) => new (packet, false); + public static implicit operator CurrentManaAndAbilityRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ConsumeItemWithEffectRef packet) => packet._data; + public static implicit operator Span(CurrentManaAndAbilityRef packet) => packet._data; } /// -/// Is sent by the server when: The durability of an item in the inventory of the player has been changed. -/// Causes reaction on client side: The client updates the item in the inventory user interface. +/// Is sent by the server when: The currently available mana or ability has changed, e.g. by using a skill. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly ref struct ItemDurabilityChangedRef +public readonly ref struct CurrentManaAndAbilityExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemDurabilityChangedRef(Span data) + public CurrentManaAndAbilityExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemDurabilityChangedRef(Span data, bool initialize) + private CurrentManaAndAbilityExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8377,6 +8629,7 @@ private ItemDurabilityChangedRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } @@ -8388,84 +8641,81 @@ private ItemDurabilityChangedRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x2A; + public static byte Code => 0x27; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public static int Length => 6; + public static byte SubCode => 0xFF; /// - /// Gets the header of this packet. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public C1HeaderRef Header => new (this._data); + public static int Length => 12; /// - /// Gets or sets the inventory slot. + /// Gets the header of this packet. /// - public byte InventorySlot - { - get => this._data[3]; - set => this._data[3] = value; - } + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the durability. + /// Gets or sets the mana. /// - public byte Durability + public uint Mana { - get => this._data[4]; - set => this._data[4] = value; + get => ReadUInt32LittleEndian(this._data[4..]); + set => WriteUInt32LittleEndian(this._data[4..], value); } /// - /// Gets or sets true, if the change resulted from an item consumption; otherwise, false + /// Gets or sets the ability. /// - public bool ByConsumption + public uint Ability { - get => this._data[5..].GetBoolean(); - set => this._data[5..].SetBoolean(value); + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemDurabilityChangedRef(Span packet) => new (packet, false); + public static implicit operator CurrentManaAndAbilityExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ItemDurabilityChangedRef packet) => packet._data; + public static implicit operator Span(CurrentManaAndAbilityExtendedRef packet) => packet._data; } /// -/// Is sent by the server when: The player requested to consume a fruit. -/// Causes reaction on client side: The client updates the user interface, by changing the added stat points and used fruit points. +/// Is sent by the server when: The maximum available mana or ability has changed, e.g. by adding stat points. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly ref struct FruitConsumptionResponseRef +public readonly ref struct MaximumManaAndAbilityRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public FruitConsumptionResponseRef(Span data) + public MaximumManaAndAbilityRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private FruitConsumptionResponseRef(Span data, bool initialize) + private MaximumManaAndAbilityRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8474,6 +8724,7 @@ private FruitConsumptionResponseRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } @@ -8485,84 +8736,81 @@ private FruitConsumptionResponseRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x2C; + public static byte Code => 0x27; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0xFE; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 7; + public static int Length => 8; /// /// Gets the header of this packet. /// - public C1HeaderRef Header => new (this._data); + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the result. + /// Gets or sets the mana. /// - public FruitConsumptionResponse.FruitConsumptionResult Result + public ushort Mana { - get => (FruitConsumptionResponse.FruitConsumptionResult)this._data[3]; - set => this._data[3] = (byte)value; + get => ReadUInt16BigEndian(this._data[4..]); + set => WriteUInt16BigEndian(this._data[4..], value); } /// - /// Gets or sets the stat points. + /// Gets or sets the ability. /// - public ushort StatPoints + public ushort Ability { - get => ReadUInt16LittleEndian(this._data[4..]); - set => WriteUInt16LittleEndian(this._data[4..], value); - } - - /// - /// Gets or sets the stat type. - /// - public FruitConsumptionResponse.FruitStatType StatType - { - get => (FruitConsumptionResponse.FruitStatType)this._data[6]; - set => this._data[6] = (byte)value; + get => ReadUInt16BigEndian(this._data[6..]); + set => WriteUInt16BigEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator FruitConsumptionResponseRef(Span packet) => new (packet, false); + public static implicit operator MaximumManaAndAbilityRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(FruitConsumptionResponseRef packet) => packet._data; + public static implicit operator Span(MaximumManaAndAbilityRef packet) => packet._data; } /// -/// Is sent by the server when: The player requested to consume an item which gives a magic effect. -/// Causes reaction on client side: The client updates the user interface, it shows the remaining time at the effect icon. +/// Is sent by the server when: The maximum available mana or ability has changed, e.g. by adding stat points. +/// Causes reaction on client side: The mana and ability bar is updated on the game client user interface. /// -public readonly ref struct EffectItemConsumptionRef +public readonly ref struct MaximumManaAndAbilityExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public EffectItemConsumptionRef(Span data) + public MaximumManaAndAbilityExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private EffectItemConsumptionRef(Span data, bool initialize) + private MaximumManaAndAbilityExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8571,6 +8819,7 @@ private EffectItemConsumptionRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } @@ -8582,102 +8831,81 @@ private EffectItemConsumptionRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x2D; - - /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. - /// - public static int Length => 17; - - /// - /// Gets the header of this packet. - /// - public C1HeaderRef Header => new (this._data); + public static byte Code => 0x27; /// - /// Gets or sets the origin. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public EffectItemConsumption.EffectOrigin Origin - { - get => (EffectItemConsumption.EffectOrigin)this._data[4]; - set => this._data[4] = (byte)value; - } + public static byte SubCode => 0xFE; /// - /// Gets or sets the type. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public EffectItemConsumption.EffectType Type - { - get => (EffectItemConsumption.EffectType)this._data[6]; - set => this._data[6] = (byte)value; - } + public static int Length => 12; /// - /// Gets or sets the action. + /// Gets the header of this packet. /// - public EffectItemConsumption.EffectAction Action - { - get => (EffectItemConsumption.EffectAction)this._data[8]; - set => this._data[8] = (byte)value; - } + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the remaining seconds. + /// Gets or sets the mana. /// - public uint RemainingSeconds + public uint Mana { - get => ReadUInt32LittleEndian(this._data[12..]); - set => WriteUInt32LittleEndian(this._data[12..], value); + get => ReadUInt32LittleEndian(this._data[4..]); + set => WriteUInt32LittleEndian(this._data[4..], value); } /// - /// Gets or sets the magic effect number. + /// Gets or sets the ability. /// - public byte MagicEffectNumber + public uint Ability { - get => this._data[16]; - set => this._data[16] = value; + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator EffectItemConsumptionRef(Span packet) => new (packet, false); + public static implicit operator MaximumManaAndAbilityExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(EffectItemConsumptionRef packet) => packet._data; + public static implicit operator Span(MaximumManaAndAbilityExtendedRef packet) => packet._data; } /// -/// Is sent by the server when: After the client talked to an NPC which should cause a dialog to open on the client side. -/// Causes reaction on client side: The client opens the specified dialog. +/// Is sent by the server when: The item has been removed from the inventory of the player. +/// Causes reaction on client side: The client removes the item in the inventory user interface. /// -public readonly ref struct NpcWindowResponseRef +public readonly ref struct ItemRemovedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public NpcWindowResponseRef(Span data) + public ItemRemovedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private NpcWindowResponseRef(Span data, bool initialize) + private ItemRemovedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8686,77 +8914,87 @@ private NpcWindowResponseRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); + this.TrueFlag = 1; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC3; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x30; + public static byte Code => 0x28; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 11; + public static int Length => 5; /// /// Gets the header of this packet. /// - public C3HeaderRef Header => new (this._data); + public C1HeaderRef Header => new (this._data); /// - /// Gets or sets the window. + /// Gets or sets the affected slot of the item in the inventory. /// - public NpcWindowResponse.NpcWindow Window + public byte InventorySlot { - get => (NpcWindowResponse.NpcWindow)this._data[3]; - set => this._data[3] = (byte)value; + get => this._data[3]; + set => this._data[3] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the true flag. + /// + public byte TrueFlag + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator NpcWindowResponseRef(Span packet) => new (packet, false); + public static implicit operator ItemRemovedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(NpcWindowResponseRef packet) => packet._data; + public static implicit operator Span(ItemRemovedRef packet) => packet._data; } /// -/// Is sent by the server when: The player opens a merchant npc or the vault. It's sent after the dialog was opened by another message. -/// Causes reaction on client side: The client shows the items in the opened dialog. +/// Is sent by the server when: The client requested to consume a special item, e.g. a bottle of Ale. +/// Causes reaction on client side: The player is shown in a red color and has increased attack speed. /// -public readonly ref struct StoreItemListRef +public readonly ref struct ConsumeItemWithEffectRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public StoreItemListRef(Span data) + public ConsumeItemWithEffectRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private StoreItemListRef(Span data, bool initialize) + private ConsumeItemWithEffectRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8764,95 +9002,87 @@ private StoreItemListRef(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC3; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x31; + public static byte Code => 0x29; /// - /// Gets the header of this packet. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public C2HeaderRef Header => new (this._data); + public static int Length => 6; /// - /// Gets or sets the type. + /// Gets the header of this packet. /// - public StoreItemList.ItemWindow Type - { - get => (StoreItemList.ItemWindow)this._data[4]; - set => this._data[4] = (byte)value; - } + public C3HeaderRef Header => new (this._data); /// - /// Gets or sets the item count. + /// Gets or sets the item type. /// - public byte ItemCount + public ConsumeItemWithEffect.ConsumedItemType ItemType { - get => this._data[5]; - set => this._data[5] = value; + get => (ConsumeItemWithEffect.ConsumedItemType)this._data[3]; + set => this._data[3] = (byte)value; } /// - /// Gets the of the specified index. + /// Gets or sets the effect time in seconds. /// - public StoredItemRef this[int index, int storedItemLength] => new (this._data[(6 + index * storedItemLength)..]); + public ushort EffectTimeInSeconds + { + get => ReadUInt16BigEndian(this._data[4..]); + set => WriteUInt16BigEndian(this._data[4..], value); + } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator StoreItemListRef(Span packet) => new (packet, false); + public static implicit operator ConsumeItemWithEffectRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(StoreItemListRef packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified count of and it's size. - /// - /// The count of from which the size will be calculated. - /// The length of from which the size will be calculated. - - public static int GetRequiredSize(int itemsCount, int structLength) => itemsCount * structLength + 6; + public static implicit operator Span(ConsumeItemWithEffectRef packet) => packet._data; } /// -/// Is sent by the server when: The request of buying an item from a NPC failed. -/// Causes reaction on client side: The client is responsive again. Without this message, it may stuck. +/// Is sent by the server when: The durability of an item in the inventory of the player has been changed. +/// Causes reaction on client side: The client updates the item in the inventory user interface. /// -public readonly ref struct NpcItemBuyFailedRef +public readonly ref struct ItemDurabilityChangedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public NpcItemBuyFailedRef(Span data) + public ItemDurabilityChangedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private NpcItemBuyFailedRef(Span data, bool initialize) + private ItemDurabilityChangedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8861,7 +9091,6 @@ private NpcItemBuyFailedRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; } } @@ -8873,63 +9102,84 @@ private NpcItemBuyFailedRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x32; + public static byte Code => 0x2A; /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static byte SubCode => 0xFF; + public static int Length => 6; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the header of this packet. /// - public static int Length => 4; + public C1HeaderRef Header => new (this._data); /// - /// Gets the header of this packet. + /// Gets or sets the inventory slot. /// - public C1HeaderWithSubCodeRef Header => new (this._data); + public byte InventorySlot + { + get => this._data[3]; + set => this._data[3] = value; + } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the durability. + /// + public byte Durability + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Gets or sets true, if the change resulted from an item consumption; otherwise, false + /// + public bool ByConsumption + { + get => this._data[5..].GetBoolean(); + set => this._data[5..].SetBoolean(value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator NpcItemBuyFailedRef(Span packet) => new (packet, false); + public static implicit operator ItemDurabilityChangedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(NpcItemBuyFailedRef packet) => packet._data; + public static implicit operator Span(ItemDurabilityChangedRef packet) => packet._data; } /// -/// Is sent by the server when: The request of buying an item from a player or npc was successful. -/// Causes reaction on client side: The bought item is added to the inventory. +/// Is sent by the server when: The player requested to consume a fruit. +/// Causes reaction on client side: The client updates the user interface, by changing the added stat points and used fruit points. /// -public readonly ref struct ItemBoughtRef +public readonly ref struct FruitConsumptionResponseRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ItemBoughtRef(Span data) + public FruitConsumptionResponseRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ItemBoughtRef(Span data, bool initialize) + private FruitConsumptionResponseRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -8937,7 +9187,7 @@ private ItemBoughtRef(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); } } @@ -8949,7 +9199,12 @@ private ItemBoughtRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x32; + public static byte Code => 0x2C; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 7; /// /// Gets the header of this packet. @@ -8957,68 +9212,71 @@ private ItemBoughtRef(Span data, bool initialize) public C1HeaderRef Header => new (this._data); /// - /// Gets or sets the inventory slot. + /// Gets or sets the result. /// - public byte InventorySlot + public FruitConsumptionResponse.FruitConsumptionResult Result { - get => this._data[3]; - set => this._data[3] = value; + get => (FruitConsumptionResponse.FruitConsumptionResult)this._data[3]; + set => this._data[3] = (byte)value; } /// - /// Gets or sets the item data. + /// Gets or sets the stat points. /// - public Span ItemData + public ushort StatPoints { - get => this._data.Slice(4); + get => ReadUInt16LittleEndian(this._data[4..]); + set => WriteUInt16LittleEndian(this._data[4..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the stat type. + /// + public FruitConsumptionResponse.FruitStatType StatType + { + get => (FruitConsumptionResponse.FruitStatType)this._data[6]; + set => this._data[6] = (byte)value; + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ItemBoughtRef(Span packet) => new (packet, false); + public static implicit operator FruitConsumptionResponseRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ItemBoughtRef packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified length of . - /// - /// The length in bytes of on which the required size depends. - - public static int GetRequiredSize(int itemDataLength) => itemDataLength + 4; + public static implicit operator Span(FruitConsumptionResponseRef packet) => packet._data; } /// -/// Is sent by the server when: The result of a previous item sell request. -/// Causes reaction on client side: The amount of specified money is set at the players inventory. +/// Is sent by the server when: The player requested to consume an item which gives a magic effect. +/// Causes reaction on client side: The client updates the user interface, it shows the remaining time at the effect icon. /// -public readonly ref struct NpcItemSellResultRef +public readonly ref struct EffectItemConsumptionRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public NpcItemSellResultRef(Span data) + public EffectItemConsumptionRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private NpcItemSellResultRef(Span data, bool initialize) + private EffectItemConsumptionRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9033,80 +9291,107 @@ private NpcItemSellResultRef(Span data, bool initialize) /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC3; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x33; + public static byte Code => 0x2D; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 17; /// /// Gets the header of this packet. /// - public C3HeaderRef Header => new (this._data); + public C1HeaderRef Header => new (this._data); /// - /// Gets or sets the success. + /// Gets or sets the origin. /// - public bool Success + public EffectItemConsumption.EffectOrigin Origin { - get => this._data[3..].GetBoolean(); - set => this._data[3..].SetBoolean(value); + get => (EffectItemConsumption.EffectOrigin)this._data[4]; + set => this._data[4] = (byte)value; } /// - /// Gets or sets the money. + /// Gets or sets the type. /// - public uint Money + public EffectItemConsumption.EffectType Type { - get => ReadUInt32LittleEndian(this._data[4..]); - set => WriteUInt32LittleEndian(this._data[4..], value); + get => (EffectItemConsumption.EffectType)this._data[6]; + set => this._data[6] = (byte)value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the action. + /// + public EffectItemConsumption.EffectAction Action + { + get => (EffectItemConsumption.EffectAction)this._data[8]; + set => this._data[8] = (byte)value; + } + + /// + /// Gets or sets the remaining seconds. + /// + public uint RemainingSeconds + { + get => ReadUInt32LittleEndian(this._data[12..]); + set => WriteUInt32LittleEndian(this._data[12..], value); + } + + /// + /// Gets or sets the magic effect number. + /// + public byte MagicEffectNumber + { + get => this._data[16]; + set => this._data[16] = value; + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator NpcItemSellResultRef(Span packet) => new (packet, false); + public static implicit operator EffectItemConsumptionRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(NpcItemSellResultRef packet) => packet._data; + public static implicit operator Span(EffectItemConsumptionRef packet) => packet._data; } /// -/// Is sent by the server when: The player requested to set a price for an item of the players shop. -/// Causes reaction on client side: The item gets a price on the user interface. +/// Is sent by the server when: After the client talked to an NPC which should cause a dialog to open on the client side. +/// Causes reaction on client side: The client opens the specified dialog. /// -public readonly ref struct PlayerShopSetItemPriceResponseRef +public readonly ref struct NpcWindowResponseRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopSetItemPriceResponseRef(Span data) + public NpcWindowResponseRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopSetItemPriceResponseRef(Span data, bool initialize) + private NpcWindowResponseRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9115,7 +9400,6 @@ private PlayerShopSetItemPriceResponseRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; } } @@ -9127,81 +9411,66 @@ private PlayerShopSetItemPriceResponseRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x3F; - - /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. - /// - public static byte SubCode => 0x01; + public static byte Code => 0x30; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 6; + public static int Length => 11; /// /// Gets the header of this packet. /// - public C3HeaderWithSubCodeRef Header => new (this._data); - - /// - /// Gets or sets the inventory slot. - /// - public byte InventorySlot - { - get => this._data[5]; - set => this._data[5] = value; - } + public C3HeaderRef Header => new (this._data); /// - /// Gets or sets the result. + /// Gets or sets the window. /// - public PlayerShopSetItemPriceResponse.ItemPriceSetResult Result + public NpcWindowResponse.NpcWindow Window { - get => (PlayerShopSetItemPriceResponse.ItemPriceSetResult)this._data[4]; - set => this._data[4] = (byte)value; + get => (NpcWindowResponse.NpcWindow)this._data[3]; + set => this._data[3] = (byte)value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayerShopSetItemPriceResponseRef(Span packet) => new (packet, false); + public static implicit operator NpcWindowResponseRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(PlayerShopSetItemPriceResponseRef packet) => packet._data; + public static implicit operator Span(NpcWindowResponseRef packet) => packet._data; } /// -/// Is sent by the server when: After a player in scope requested to close his shop or after all items has been sold. -/// Causes reaction on client side: The player shop not shown as open anymore. +/// Is sent by the server when: The player opens a merchant npc or the vault. It's sent after the dialog was opened by another message. +/// Causes reaction on client side: The client shows the items in the opened dialog. /// -public readonly ref struct PlayerShopClosedRef +public readonly ref struct StoreItemListRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopClosedRef(Span data) + public StoreItemListRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopClosedRef(Span data, bool initialize) + private StoreItemListRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9209,95 +9478,95 @@ private PlayerShopClosedRef(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; - this.Success = true; + header.Length = (ushort)data.Length; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC1; + public static byte HeaderType => 0xC2; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x3F; - - /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. - /// - public static byte SubCode => 0x3; - - /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. - /// - public static int Length => 7; + public static byte Code => 0x31; /// /// Gets the header of this packet. /// - public C1HeaderWithSubCodeRef Header => new (this._data); + public C2HeaderRef Header => new (this._data); /// - /// Gets or sets the success. + /// Gets or sets the type. /// - public bool Success + public StoreItemList.ItemWindow Type { - get => this._data[4..].GetBoolean(); - set => this._data[4..].SetBoolean(value); + get => (StoreItemList.ItemWindow)this._data[4]; + set => this._data[4] = (byte)value; } /// - /// Gets or sets the player id. + /// Gets or sets the item count. /// - public ushort PlayerId + public byte ItemCount { - get => ReadUInt16BigEndian(this._data[5..]); - set => WriteUInt16BigEndian(this._data[5..], value); + get => this._data[5]; + set => this._data[5] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets the of the specified index. + /// + public StoredItemRef this[int index, int storedItemLength] => new (this._data[(6 + index * storedItemLength)..]); + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayerShopClosedRef(Span packet) => new (packet, false); + public static implicit operator StoreItemListRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(PlayerShopClosedRef packet) => packet._data; -} - + public static implicit operator Span(StoreItemListRef packet) => packet._data; -/// -/// Is sent by the server when: An item of the players shop was sold to another player. -/// Causes reaction on client side: The item is removed from the players inventory and a blue system message appears. + /// + /// Calculates the size of the packet for the specified count of and it's size. + /// + /// The count of from which the size will be calculated. + /// The length of from which the size will be calculated. + + public static int GetRequiredSize(int itemsCount, int structLength) => itemsCount * structLength + 6; +} + + +/// +/// Is sent by the server when: The request of buying an item from a NPC failed. +/// Causes reaction on client side: The client is responsive again. Without this message, it may stuck. /// -public readonly ref struct PlayerShopItemSoldToPlayerRef +public readonly ref struct NpcItemBuyFailedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopItemSoldToPlayerRef(Span data) + public NpcItemBuyFailedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopItemSoldToPlayerRef(Span data, bool initialize) + private NpcItemBuyFailedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9318,18 +9587,18 @@ private PlayerShopItemSoldToPlayerRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x3F; + public static byte Code => 0x32; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x08; + public static byte SubCode => 0xFF; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 15; + public static int Length => 4; /// /// Gets the header of this packet. @@ -9337,62 +9606,44 @@ private PlayerShopItemSoldToPlayerRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the inventory slot. - /// - public byte InventorySlot - { - get => this._data[4]; - set => this._data[4] = value; - } - - /// - /// Gets or sets the buyer name. - /// - public string BuyerName - { - get => this._data.ExtractString(5, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(5, 10).WriteString(value, System.Text.Encoding.UTF8); - } - - /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayerShopItemSoldToPlayerRef(Span packet) => new (packet, false); + public static implicit operator NpcItemBuyFailedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(PlayerShopItemSoldToPlayerRef packet) => packet._data; + public static implicit operator Span(NpcItemBuyFailedRef packet) => packet._data; } /// -/// Is sent by the server when: After the player requested to close his shop or after all items has been sold. -/// Causes reaction on client side: The player shop dialog is closed for the shop of the specified player. +/// Is sent by the server when: The request of buying an item from a player or npc was successful. +/// Causes reaction on client side: The bought item is added to the inventory. /// -public readonly ref struct ClosePlayerShopDialogRef +public readonly ref struct ItemBoughtRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ClosePlayerShopDialogRef(Span data) + public ItemBoughtRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ClosePlayerShopDialogRef(Span data, bool initialize) + private ItemBoughtRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9400,8 +9651,7 @@ private ClosePlayerShopDialogRef(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; + header.Length = (byte)data.Length; } } @@ -9413,72 +9663,76 @@ private ClosePlayerShopDialogRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x3F; - - /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. - /// - public static byte SubCode => 0x12; + public static byte Code => 0x32; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the header of this packet. /// - public static int Length => 6; + public C1HeaderRef Header => new (this._data); /// - /// Gets the header of this packet. + /// Gets or sets the inventory slot. /// - public C1HeaderWithSubCodeRef Header => new (this._data); + public byte InventorySlot + { + get => this._data[3]; + set => this._data[3] = value; + } /// - /// Gets or sets the player id. + /// Gets or sets the item data. /// - public ushort PlayerId + public Span ItemData { - get => ReadUInt16BigEndian(this._data[4..]); - set => WriteUInt16BigEndian(this._data[4..], value); + get => this._data.Slice(4); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ClosePlayerShopDialogRef(Span packet) => new (packet, false); + public static implicit operator ItemBoughtRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ClosePlayerShopDialogRef packet) => packet._data; + public static implicit operator Span(ItemBoughtRef packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified length of . + /// + /// The length in bytes of on which the required size depends. + + public static int GetRequiredSize(int itemDataLength) => itemDataLength + 4; } /// -/// Is sent by the server when: After the player requested to open a shop of another player. -/// Causes reaction on client side: The player shop dialog is shown with the provided item data. +/// Is sent by the server when: The result of a previous item sell request. +/// Causes reaction on client side: The amount of specified money is set at the players inventory. /// -public readonly ref struct PlayerShopItemListRef +public readonly ref struct NpcItemSellResultRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopItemListRef(Span data) + public NpcItemSellResultRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopItemListRef(Span data, bool initialize) + private NpcItemSellResultRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9486,138 +9740,87 @@ private PlayerShopItemListRef(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; - header.SubCode = SubCode; - this.Success = true; + header.Length = (byte)Math.Min(data.Length, Length); } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC3; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x3F; + public static byte Code => 0x33; /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static byte SubCode => 0x05; + public static int Length => 8; /// /// Gets the header of this packet. /// - public C2HeaderWithSubCodeRef Header => new (this._data); - - /// - /// Gets or sets the action. - /// - public PlayerShopItemList.ActionKind Action - { - get => (PlayerShopItemList.ActionKind)this._data[4]; - set => this._data[4] = (byte)value; - } + public C3HeaderRef Header => new (this._data); /// /// Gets or sets the success. /// public bool Success { - get => this._data[5..].GetBoolean(); - set => this._data[5..].SetBoolean(value); - } - - /// - /// Gets or sets the player id. - /// - public ushort PlayerId - { - get => ReadUInt16BigEndian(this._data[6..]); - set => WriteUInt16BigEndian(this._data[6..], value); - } - - /// - /// Gets or sets the player name. - /// - public string PlayerName - { - get => this._data.ExtractString(8, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(8, 10).WriteString(value, System.Text.Encoding.UTF8); - } - - /// - /// Gets or sets the shop name. - /// - public string ShopName - { - get => this._data.ExtractString(18, 36, System.Text.Encoding.UTF8); - set => this._data.Slice(18, 36).WriteString(value, System.Text.Encoding.UTF8); + get => this._data[3..].GetBoolean(); + set => this._data[3..].SetBoolean(value); } /// - /// Gets or sets the item count. + /// Gets or sets the money. /// - public byte ItemCount + public uint Money { - get => this._data[54]; - set => this._data[54] = value; + get => ReadUInt32LittleEndian(this._data[4..]); + set => WriteUInt32LittleEndian(this._data[4..], value); } /// - /// Gets the of the specified index. - /// - public PlayerShopItemRef this[int index] => new (this._data[(55 + index * PlayerShopItemRef.Length)..]); - - /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayerShopItemListRef(Span packet) => new (packet, false); + public static implicit operator NpcItemSellResultRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(PlayerShopItemListRef packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified count of . - /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int itemsCount) => itemsCount * PlayerShopItemRef.Length + 55; + public static implicit operator Span(NpcItemSellResultRef packet) => packet._data; } /// -/// Is sent by the server when: After the player gets into scope of a player with an opened shop. -/// Causes reaction on client side: The player shop title is shown at the specified players. +/// Is sent by the server when: The player requested to set a price for an item of the players shop. +/// Causes reaction on client side: The item gets a price on the user interface. /// -public readonly ref struct PlayerShopsRef +public readonly ref struct PlayerShopSetItemPriceResponseRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopsRef(Span data) + public PlayerShopSetItemPriceResponseRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PlayerShopsRef(Span data, bool initialize) + private PlayerShopSetItemPriceResponseRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9625,7 +9828,7 @@ private PlayerShopsRef(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; } } @@ -9633,7 +9836,7 @@ private PlayerShopsRef(Span data, bool initialize) /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC3; /// /// Gets the operation code of this data packet. @@ -9644,61 +9847,1049 @@ private PlayerShopsRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; + public static byte SubCode => 0x01; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 6; /// /// Gets the header of this packet. /// - public C2HeaderWithSubCodeRef Header => new (this._data); + public C3HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the shop count. + /// Gets or sets the inventory slot. /// - public byte ShopCount + public byte InventorySlot { get => this._data[5]; set => this._data[5] = value; } /// - /// Gets the of the specified index. + /// Gets or sets the result. /// - public PlayerShopRef this[int index] => new (this._data[(6 + index * PlayerShopRef.Length)..]); + public PlayerShopSetItemPriceResponse.ItemPriceSetResult Result + { + get => (PlayerShopSetItemPriceResponse.ItemPriceSetResult)this._data[4]; + set => this._data[4] = (byte)value; + } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayerShopsRef(Span packet) => new (packet, false); + public static implicit operator PlayerShopSetItemPriceResponseRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(PlayerShopSetItemPriceResponseRef packet) => packet._data; +} + + +/// +/// Is sent by the server when: After a player in scope requested to close his shop or after all items has been sold. +/// Causes reaction on client side: The player shop not shown as open anymore. +/// +public readonly ref struct PlayerShopClosedRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public PlayerShopClosedRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private PlayerShopClosedRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + this.Success = true; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x3F; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x3; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 7; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the success. + /// + public bool Success + { + get => this._data[4..].GetBoolean(); + set => this._data[4..].SetBoolean(value); + } + + /// + /// Gets or sets the player id. + /// + public ushort PlayerId + { + get => ReadUInt16BigEndian(this._data[5..]); + set => WriteUInt16BigEndian(this._data[5..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator PlayerShopClosedRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(PlayerShopClosedRef packet) => packet._data; +} + + +/// +/// Is sent by the server when: An item of the players shop was sold to another player. +/// Causes reaction on client side: The item is removed from the players inventory and a blue system message appears. +/// +public readonly ref struct PlayerShopItemSoldToPlayerRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public PlayerShopItemSoldToPlayerRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private PlayerShopItemSoldToPlayerRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x3F; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x08; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 15; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the inventory slot. + /// + public byte InventorySlot + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Gets or sets the buyer name. + /// + public string BuyerName + { + get => this._data.ExtractString(5, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(5, 10).WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator PlayerShopItemSoldToPlayerRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(PlayerShopItemSoldToPlayerRef packet) => packet._data; +} + + +/// +/// Is sent by the server when: After the player requested to close his shop or after all items has been sold. +/// Causes reaction on client side: The player shop dialog is closed for the shop of the specified player. +/// +public readonly ref struct ClosePlayerShopDialogRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public ClosePlayerShopDialogRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ClosePlayerShopDialogRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x3F; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x12; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 6; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the player id. + /// + public ushort PlayerId + { + get => ReadUInt16BigEndian(this._data[4..]); + set => WriteUInt16BigEndian(this._data[4..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ClosePlayerShopDialogRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(ClosePlayerShopDialogRef packet) => packet._data; +} + + +/// +/// Is sent by the server when: After the player requested to open a shop of another player. +/// Causes reaction on client side: The player shop dialog is shown with the provided item data. +/// +public readonly ref struct PlayerShopItemListRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public PlayerShopItemListRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private PlayerShopItemListRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (ushort)data.Length; + header.SubCode = SubCode; + this.Success = true; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC2; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x3F; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x05; + + /// + /// Gets the header of this packet. + /// + public C2HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the action. + /// + public PlayerShopItemList.ActionKind Action + { + get => (PlayerShopItemList.ActionKind)this._data[4]; + set => this._data[4] = (byte)value; + } + + /// + /// Gets or sets the success. + /// + public bool Success + { + get => this._data[5..].GetBoolean(); + set => this._data[5..].SetBoolean(value); + } + + /// + /// Gets or sets the player id. + /// + public ushort PlayerId + { + get => ReadUInt16BigEndian(this._data[6..]); + set => WriteUInt16BigEndian(this._data[6..], value); + } + + /// + /// Gets or sets the player name. + /// + public string PlayerName + { + get => this._data.ExtractString(8, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(8, 10).WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Gets or sets the shop name. + /// + public string ShopName + { + get => this._data.ExtractString(18, 36, System.Text.Encoding.UTF8); + set => this._data.Slice(18, 36).WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Gets or sets the item count. + /// + public byte ItemCount + { + get => this._data[54]; + set => this._data[54] = value; + } + + /// + /// Gets the of the specified index. + /// + public PlayerShopItemRef this[int index] => new (this._data[(55 + index * PlayerShopItemRef.Length)..]); + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator PlayerShopItemListRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(PlayerShopItemListRef packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of . + /// + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int itemsCount) => itemsCount * PlayerShopItemRef.Length + 55; +} + + +/// +/// Is sent by the server when: After the player gets into scope of a player with an opened shop. +/// Causes reaction on client side: The player shop title is shown at the specified players. +/// +public readonly ref struct PlayerShopsRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public PlayerShopsRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private PlayerShopsRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (ushort)data.Length; + header.SubCode = SubCode; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC2; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x3F; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x00; + + /// + /// Gets the header of this packet. + /// + public C2HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the shop count. + /// + public byte ShopCount + { + get => this._data[5]; + set => this._data[5] = value; + } + + /// + /// Gets the of the specified index. + /// + public PlayerShopRef this[int index] => new (this._data[(6 + index * PlayerShopRef.Length)..]); + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator PlayerShopsRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(PlayerShopsRef packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of . + /// + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int shopsCount) => shopsCount * PlayerShopRef.Length + 6; + + +/// +/// Data of the shop of a player.. +/// +public readonly ref struct PlayerShopRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public PlayerShopRef(Span data) + { + this._data = data; + } + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 38; + + /// + /// Gets or sets the player id. + /// + public ushort PlayerId + { + get => ReadUInt16BigEndian(this._data); + set => WriteUInt16BigEndian(this._data, value); + } + + /// + /// Gets or sets the store name. + /// + public string StoreName + { + get => this._data.ExtractString(2, 36, System.Text.Encoding.UTF8); + set => this._data.Slice(2, 36).WriteString(value, System.Text.Encoding.UTF8); + } +} +} + + +/// +/// Is sent by the server when: The player wears a monster transformation ring. +/// Causes reaction on client side: The character appears as monster, defined by the Skin property. +/// +public readonly ref struct AddTransformedCharactersToScope075Ref +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public AddTransformedCharactersToScope075Ref(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private AddTransformedCharactersToScope075Ref(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (ushort)data.Length; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC2; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x45; + + /// + /// Gets the header of this packet. + /// + public C2HeaderRef Header => new (this._data); + + /// + /// Gets or sets the character count. + /// + public byte CharacterCount + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Gets the of the specified index. + /// + public CharacterDataRef this[int index] => new (this._data[(5 + index * CharacterDataRef.Length)..]); + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator AddTransformedCharactersToScope075Ref(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(AddTransformedCharactersToScope075Ref packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of . + /// + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 5; + + +/// +/// Contains the data of an transformed character.. +/// +public readonly ref struct CharacterDataRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public CharacterDataRef(Span data) + { + this._data = data; + } + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 19; + + /// + /// Gets or sets the id. + /// + public ushort Id + { + get => ReadUInt16BigEndian(this._data); + set => WriteUInt16BigEndian(this._data, value); + } + + /// + /// Gets or sets the current position x. + /// + public byte CurrentPositionX + { + get => this._data[2]; + set => this._data[2] = value; + } + + /// + /// Gets or sets the current position y. + /// + public byte CurrentPositionY + { + get => this._data[3]; + set => this._data[3] = value; + } + + /// + /// Gets or sets the skin. + /// + public byte Skin + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Gets or sets the is poisoned. + /// + public bool IsPoisoned + { + get => this._data[5..].GetBoolean(0); + set => this._data[5..].SetBoolean(value, 0); + } + + /// + /// Gets or sets the is iced. + /// + public bool IsIced + { + get => this._data[5..].GetBoolean(1); + set => this._data[5..].SetBoolean(value, 1); + } + + /// + /// Gets or sets the is damage buffed. + /// + public bool IsDamageBuffed + { + get => this._data[5..].GetBoolean(2); + set => this._data[5..].SetBoolean(value, 2); + } + + /// + /// Gets or sets the is defense buffed. + /// + public bool IsDefenseBuffed + { + get => this._data[5..].GetBoolean(3); + set => this._data[5..].SetBoolean(value, 3); + } + + /// + /// Gets or sets the name. + /// + public string Name + { + get => this._data.ExtractString(6, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(6, 10).WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Gets or sets the target position x. + /// + public byte TargetPositionX + { + get => this._data[16]; + set => this._data[16] = value; + } + + /// + /// Gets or sets the target position y. + /// + public byte TargetPositionY + { + get => this._data[17]; + set => this._data[17] = value; + } + + /// + /// Gets or sets the rotation. + /// + public byte Rotation + { + get => this._data[18..].GetByteValue(4, 4); + set => this._data[18..].SetByteValue(value, 4, 4); + } + + /// + /// Gets or sets the hero state. + /// + public CharacterHeroState HeroState + { + get => (CharacterHeroState)this._data[18..].GetByteValue(4, 0); + set => this._data[18..].SetByteValue((byte)value, 4, 0); + } +} +} + + +/// +/// Is sent by the server when: The player wears a monster transformation ring. +/// Causes reaction on client side: The character appears as monster, defined by the Skin property. +/// +public readonly ref partial struct AddTransformedCharactersToScopeRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public AddTransformedCharactersToScopeRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private AddTransformedCharactersToScopeRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (ushort)data.Length; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC2; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0x45; + + /// + /// Gets the header of this packet. + /// + public C2HeaderRef Header => new (this._data); + + /// + /// Gets or sets the character count. + /// + public byte CharacterCount + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator AddTransformedCharactersToScopeRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(AddTransformedCharactersToScopeRef packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified count of and it's size. + /// + /// The count of from which the size will be calculated. + /// The length of from which the size will be calculated. + + public static int GetRequiredSize(int charactersCount, int structLength) => charactersCount * structLength + 5; + + +/// +/// Contains the data of an transformed character.. +/// +public readonly ref struct CharacterDataRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public CharacterDataRef(Span data) + { + this._data = data; + } + + /// + /// Gets or sets the id. + /// + public ushort Id + { + get => ReadUInt16BigEndian(this._data); + set => WriteUInt16BigEndian(this._data, value); + } + + /// + /// Gets or sets the current position x. + /// + public byte CurrentPositionX + { + get => this._data[2]; + set => this._data[2] = value; + } + + /// + /// Gets or sets the current position y. + /// + public byte CurrentPositionY + { + get => this._data[3]; + set => this._data[3] = value; + } + + /// + /// Gets or sets the skin. + /// + public ushort Skin + { + get => ReadUInt16BigEndian(this._data[4..]); + set => WriteUInt16BigEndian(this._data[4..], value); + } + + /// + /// Gets or sets the name. + /// + public string Name + { + get => this._data.ExtractString(6, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(6, 10).WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Gets or sets the target position x. + /// + public byte TargetPositionX + { + get => this._data[16]; + set => this._data[16] = value; + } + + /// + /// Gets or sets the target position y. + /// + public byte TargetPositionY + { + get => this._data[17]; + set => this._data[17] = value; + } + + /// + /// Gets or sets the rotation. + /// + public byte Rotation + { + get => this._data[18..].GetByteValue(4, 4); + set => this._data[18..].SetByteValue(value, 4, 4); + } + + /// + /// Gets or sets the hero state. + /// + public CharacterHeroState HeroState + { + get => (CharacterHeroState)this._data[18..].GetByteValue(4, 0); + set => this._data[18..].SetByteValue((byte)value, 4, 0); + } + + /// + /// Gets or sets the appearance. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Span(PlayerShopsRef packet) => packet._data; + public Span Appearance + { + get => this._data.Slice(19, 18); + } /// - /// Calculates the size of the packet for the specified count of . + /// Gets or sets defines the number of effects which would be sent after this field. /// - /// The count of from which the size will be calculated. + public byte EffectCount + { + get => this._data[37]; + set => this._data[37] = value; + } + + /// + /// Gets the of the specified index. + /// + public EffectIdRef this[int index] => new (this._data[(38 + index * EffectIdRef.Length)..]); + + /// + /// Calculates the size of the packet for the specified count of . + /// + /// The count of from which the size will be calculated. - public static int GetRequiredSize(int shopsCount) => shopsCount * PlayerShopRef.Length + 6; + public static int GetRequiredSize(int effectsCount) => effectsCount * EffectIdRef.Length + 38; +} /// -/// Data of the shop of a player.. +/// Contains the id of a magic effect.. /// -public readonly ref struct PlayerShopRef +public readonly ref struct EffectIdRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PlayerShopRef(Span data) + public EffectIdRef(Span data) { this._data = data; } @@ -9706,52 +10897,43 @@ public PlayerShopRef(Span data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 38; - - /// - /// Gets or sets the player id. - /// - public ushort PlayerId - { - get => ReadUInt16BigEndian(this._data); - set => WriteUInt16BigEndian(this._data, value); - } + public static int Length => 1; /// - /// Gets or sets the store name. + /// Gets or sets the id. /// - public string StoreName + public byte Id { - get => this._data.ExtractString(2, 36, System.Text.Encoding.UTF8); - set => this._data.Slice(2, 36).WriteString(value, System.Text.Encoding.UTF8); + get => this._data[0]; + set => this._data[0] = value; } } } /// -/// Is sent by the server when: The player wears a monster transformation ring. -/// Causes reaction on client side: The character appears as monster, defined by the Skin property. +/// Is sent by the server when: The server wants to alter the terrain attributes of a map at runtime. +/// Causes reaction on client side: The client updates the terrain attributes on its side. /// -public readonly ref struct AddTransformedCharactersToScope075Ref +public readonly ref struct ChangeTerrainAttributesRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public AddTransformedCharactersToScope075Ref(Span data) + public ChangeTerrainAttributesRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private AddTransformedCharactersToScope075Ref(Span data, bool initialize) + private ChangeTerrainAttributesRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9759,73 +10941,101 @@ private AddTransformedCharactersToScope075Ref(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; + header.Length = (byte)data.Length; + this.Type = false; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x45; + public static byte Code => 0x46; /// /// Gets the header of this packet. /// - public C2HeaderRef Header => new (this._data); + public C1HeaderRef Header => new (this._data); /// - /// Gets or sets the character count. + /// Gets or sets the type. /// - public byte CharacterCount + public bool Type { - get => this._data[4]; - set => this._data[4] = value; + get => this._data[3..].GetBoolean(); + set => this._data[3..].SetBoolean(value); } /// - /// Gets the of the specified index. + /// Gets or sets the attribute. /// - public CharacterDataRef this[int index] => new (this._data[(5 + index * CharacterDataRef.Length)..]); + public ChangeTerrainAttributes.TerrainAttributeType Attribute + { + get => (ChangeTerrainAttributes.TerrainAttributeType)this._data[4]; + set => this._data[4] = (byte)value; + } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets when this is true, the attribute is removed on the client side. If it's false, then the attribute is added. + /// + public bool RemoveAttribute + { + get => this._data[5..].GetBoolean(); + set => this._data[5..].SetBoolean(value); + } + + /// + /// Gets or sets the area count. + /// + public byte AreaCount + { + get => this._data[6]; + set => this._data[6] = value; + } + + /// + /// Gets the of the specified index. + /// + public TerrainAreaRef this[int index] => new (this._data[(7 + index * TerrainAreaRef.Length)..]); + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator AddTransformedCharactersToScope075Ref(Span packet) => new (packet, false); + public static implicit operator ChangeTerrainAttributesRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(AddTransformedCharactersToScope075Ref packet) => packet._data; + public static implicit operator Span(ChangeTerrainAttributesRef packet) => packet._data; /// - /// Calculates the size of the packet for the specified count of . + /// Calculates the size of the packet for the specified count of . /// - /// The count of from which the size will be calculated. + /// The count of from which the size will be calculated. - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 5; + public static int GetRequiredSize(int areasCount) => areasCount * TerrainAreaRef.Length + 7; /// -/// Contains the data of an transformed character.. +/// Defines the area which should be changed.. /// -public readonly ref struct CharacterDataRef +public readonly ref struct TerrainAreaRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterDataRef(Span data) + public TerrainAreaRef(Span data) { this._data = data; } @@ -9833,151 +11043,158 @@ public CharacterDataRef(Span data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 19; + public static int Length => 4; /// - /// Gets or sets the id. + /// Gets or sets the start x. /// - public ushort Id + public byte StartX { - get => ReadUInt16BigEndian(this._data); - set => WriteUInt16BigEndian(this._data, value); + get => this._data[0]; + set => this._data[0] = value; } /// - /// Gets or sets the current position x. + /// Gets or sets the start y. /// - public byte CurrentPositionX + public byte StartY { - get => this._data[2]; - set => this._data[2] = value; + get => this._data[1]; + set => this._data[1] = value; } /// - /// Gets or sets the current position y. + /// Gets or sets the end x. /// - public byte CurrentPositionY + public byte EndX { - get => this._data[3]; - set => this._data[3] = value; + get => this._data[2]; + set => this._data[2] = value; } /// - /// Gets or sets the skin. + /// Gets or sets the end y. /// - public byte Skin + public byte EndY { - get => this._data[4]; - set => this._data[4] = value; + get => this._data[3]; + set => this._data[3] = value; } +} +} + + +/// +/// Is sent by the server when: After a player achieved or lost something. +/// Causes reaction on client side: An effect is shown for the affected player. +/// +public readonly ref struct ShowEffectRef +{ + private readonly Span _data; /// - /// Gets or sets the is poisoned. + /// Initializes a new instance of the struct. /// - public bool IsPoisoned + /// The underlying data. + public ShowEffectRef(Span data) + : this(data, true) { - get => this._data[5..].GetBoolean(0); - set => this._data[5..].SetBoolean(value, 0); } /// - /// Gets or sets the is iced. + /// Initializes a new instance of the struct. /// - public bool IsIced + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ShowEffectRef(Span data, bool initialize) { - get => this._data[5..].GetBoolean(1); - set => this._data[5..].SetBoolean(value, 1); + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + } } /// - /// Gets or sets the is damage buffed. + /// Gets the header type of this data packet. /// - public bool IsDamageBuffed - { - get => this._data[5..].GetBoolean(2); - set => this._data[5..].SetBoolean(value, 2); - } + public static byte HeaderType => 0xC1; /// - /// Gets or sets the is defense buffed. + /// Gets the operation code of this data packet. /// - public bool IsDefenseBuffed - { - get => this._data[5..].GetBoolean(3); - set => this._data[5..].SetBoolean(value, 3); - } + public static byte Code => 0x48; /// - /// Gets or sets the name. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public string Name - { - get => this._data.ExtractString(6, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(6, 10).WriteString(value, System.Text.Encoding.UTF8); - } + public static int Length => 6; /// - /// Gets or sets the target position x. + /// Gets the header of this packet. /// - public byte TargetPositionX - { - get => this._data[16]; - set => this._data[16] = value; - } + public C1HeaderRef Header => new (this._data); /// - /// Gets or sets the target position y. + /// Gets or sets the player id. /// - public byte TargetPositionY + public ushort PlayerId { - get => this._data[17]; - set => this._data[17] = value; + get => ReadUInt16BigEndian(this._data[3..]); + set => WriteUInt16BigEndian(this._data[3..], value); } /// - /// Gets or sets the rotation. + /// Gets or sets the effect. /// - public byte Rotation + public ShowEffect.EffectType Effect { - get => this._data[18..].GetByteValue(4, 4); - set => this._data[18..].SetByteValue(value, 4, 4); + get => (ShowEffect.EffectType)this._data[5]; + set => this._data[5] = (byte)value; } /// - /// Gets or sets the hero state. + /// Performs an implicit conversion from a Span of bytes to a . /// - public CharacterHeroState HeroState - { - get => (CharacterHeroState)this._data[18..].GetByteValue(4, 0); - set => this._data[18..].SetByteValue((byte)value, 4, 0); - } -} + /// The packet as span. + /// The packet as struct. + public static implicit operator ShowEffectRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(ShowEffectRef packet) => packet._data; } /// -/// Is sent by the server when: The player wears a monster transformation ring. -/// Causes reaction on client side: The character appears as monster, defined by the Skin property. +/// Is sent by the server when: After the game client requested it, usually after a successful login. +/// Causes reaction on client side: The game client shows the available characters of the account. /// -public readonly ref partial struct AddTransformedCharactersToScopeRef +public readonly ref struct CharacterListRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public AddTransformedCharactersToScopeRef(Span data) + public CharacterListRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private AddTransformedCharactersToScopeRef(Span data, bool initialize) + private CharacterListRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -9985,59 +11202,97 @@ private AddTransformedCharactersToScopeRef(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (ushort)data.Length; + header.Length = (byte)data.Length; + header.SubCode = SubCode; } } /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC2; + public static byte HeaderType => 0xC1; /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x45; + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x00; /// /// Gets the header of this packet. /// - public C2HeaderRef Header => new (this._data); + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the unlock flags. + /// + public CharacterCreationUnlockFlags UnlockFlags + { + get => (CharacterCreationUnlockFlags)this._data[4]; + set => this._data[4] = (byte)value; + } + + /// + /// Gets or sets the move cnt. + /// + public byte MoveCnt + { + get => this._data[5]; + set => this._data[5] = value; + } /// /// Gets or sets the character count. /// public byte CharacterCount { - get => this._data[4]; - set => this._data[4] = value; + get => this._data[6]; + set => this._data[6] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the is vault extended. + /// + public bool IsVaultExtended + { + get => this._data[7..].GetBoolean(); + set => this._data[7..].SetBoolean(value); + } + + /// + /// Gets the of the specified index. + /// + public CharacterDataRef this[int index] => new (this._data[(8 + index * CharacterDataRef.Length)..]); + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator AddTransformedCharactersToScopeRef(Span packet) => new (packet, false); + public static implicit operator CharacterListRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(AddTransformedCharactersToScopeRef packet) => packet._data; + public static implicit operator Span(CharacterListRef packet) => packet._data; /// - /// Calculates the size of the packet for the specified count of and it's size. + /// Calculates the size of the packet for the specified count of . /// /// The count of from which the size will be calculated. - /// The length of from which the size will be calculated. - - public static int GetRequiredSize(int charactersCount, int structLength) => charactersCount * structLength + 5; + + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 8; /// -/// Contains the data of an transformed character.. +/// Data of one character in the list.. /// public readonly ref struct CharacterDataRef { @@ -10053,173 +11308,184 @@ public CharacterDataRef(Span data) } /// - /// Gets or sets the id. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public ushort Id - { - get => ReadUInt16BigEndian(this._data); - set => WriteUInt16BigEndian(this._data, value); - } + public static int Length => 34; /// - /// Gets or sets the current position x. + /// Gets or sets the slot index. /// - public byte CurrentPositionX + public byte SlotIndex { - get => this._data[2]; - set => this._data[2] = value; + get => this._data[0]; + set => this._data[0] = value; } /// - /// Gets or sets the current position y. + /// Gets or sets the name. /// - public byte CurrentPositionY + public string Name { - get => this._data[3]; - set => this._data[3] = value; + get => this._data.ExtractString(1, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(1, 10).WriteString(value, System.Text.Encoding.UTF8); } /// - /// Gets or sets the skin. + /// Gets or sets the level. /// - public ushort Skin + public ushort Level { - get => ReadUInt16BigEndian(this._data[4..]); - set => WriteUInt16BigEndian(this._data[4..], value); + get => ReadUInt16LittleEndian(this._data[12..]); + set => WriteUInt16LittleEndian(this._data[12..], value); } /// - /// Gets or sets the name. + /// Gets or sets the status. /// - public string Name + public CharacterStatus Status { - get => this._data.ExtractString(6, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(6, 10).WriteString(value, System.Text.Encoding.UTF8); + get => (CharacterStatus)this._data[14..].GetByteValue(4, 0); + set => this._data[14..].SetByteValue((byte)value, 4, 0); } /// - /// Gets or sets the target position x. + /// Gets or sets the is item block active. /// - public byte TargetPositionX + public bool IsItemBlockActive { - get => this._data[16]; - set => this._data[16] = value; + get => this._data[14..].GetBoolean(4); + set => this._data[14..].SetBoolean(value, 4); } /// - /// Gets or sets the target position y. + /// Gets or sets the appearance. /// - public byte TargetPositionY + public Span Appearance { - get => this._data[17]; - set => this._data[17] = value; + get => this._data.Slice(15, 18); } /// - /// Gets or sets the rotation. + /// Gets or sets the guild position. /// - public byte Rotation + public GuildMemberRole GuildPosition { - get => this._data[18..].GetByteValue(4, 4); - set => this._data[18..].SetByteValue(value, 4, 4); + get => (GuildMemberRole)this._data[33]; + set => this._data[33] = (byte)value; } +} +} + + +/// +/// Is sent by the server when: It's send right after the CharacterList, in the character selection screen, if the account has any unlocked character classes. +/// Causes reaction on client side: The client unlocks the specified character classes, so they can be created. +/// +public readonly ref struct CharacterClassCreationUnlockRef +{ + private readonly Span _data; /// - /// Gets or sets the hero state. + /// Initializes a new instance of the struct. /// - public CharacterHeroState HeroState + /// The underlying data. + public CharacterClassCreationUnlockRef(Span data) + : this(data, true) { - get => (CharacterHeroState)this._data[18..].GetByteValue(4, 0); - set => this._data[18..].SetByteValue((byte)value, 4, 0); } /// - /// Gets or sets the appearance. + /// Initializes a new instance of the struct. /// - public Span Appearance + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private CharacterClassCreationUnlockRef(Span data, bool initialize) { - get => this._data.Slice(19, 18); + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } } /// - /// Gets or sets defines the number of effects which would be sent after this field. + /// Gets the header type of this data packet. /// - public byte EffectCount - { - get => this._data[37]; - set => this._data[37] = value; - } + public static byte HeaderType => 0xC1; /// - /// Gets the of the specified index. + /// Gets the operation code of this data packet. /// - public EffectIdRef this[int index] => new (this._data[(38 + index * EffectIdRef.Length)..]); + public static byte Code => 0xDE; /// - /// Calculates the size of the packet for the specified count of . + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int effectsCount) => effectsCount * EffectIdRef.Length + 38; -} - - -/// -/// Contains the id of a magic effect.. -/// -public readonly ref struct EffectIdRef -{ - private readonly Span _data; + public static byte SubCode => 0x00; /// - /// Initializes a new instance of the struct. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - /// The underlying data. - public EffectIdRef(Span data) - { - this._data = data; - } + public static int Length => 5; /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets the header of this packet. /// - public static int Length => 1; + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the id. + /// Gets or sets the unlock flags. /// - public byte Id + public CharacterCreationUnlockFlags UnlockFlags { - get => this._data[0]; - set => this._data[0] = value; + get => (CharacterCreationUnlockFlags)this._data[4]; + set => this._data[4] = (byte)value; } -} + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator CharacterClassCreationUnlockRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(CharacterClassCreationUnlockRef packet) => packet._data; } /// -/// Is sent by the server when: The server wants to alter the terrain attributes of a map at runtime. -/// Causes reaction on client side: The client updates the terrain attributes on its side. +/// Is sent by the server when: After the game client requested it, usually after a successful login. +/// Causes reaction on client side: The game client shows the available characters of the account. /// -public readonly ref struct ChangeTerrainAttributesRef +public readonly ref struct CharacterList075Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ChangeTerrainAttributesRef(Span data) + public CharacterList075Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ChangeTerrainAttributesRef(Span data, bool initialize) + private CharacterList075Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -10228,7 +11494,7 @@ private ChangeTerrainAttributesRef(Span data, bool initialize) header.Type = HeaderType; header.Code = Code; header.Length = (byte)data.Length; - this.Type = false; + header.SubCode = SubCode; } } @@ -10240,88 +11506,67 @@ private ChangeTerrainAttributesRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0x46; - - /// - /// Gets the header of this packet. - /// - public C1HeaderRef Header => new (this._data); - - /// - /// Gets or sets the type. - /// - public bool Type - { - get => this._data[3..].GetBoolean(); - set => this._data[3..].SetBoolean(value); - } + public static byte Code => 0xF3; /// - /// Gets or sets the attribute. + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. /// - public ChangeTerrainAttributes.TerrainAttributeType Attribute - { - get => (ChangeTerrainAttributes.TerrainAttributeType)this._data[4]; - set => this._data[4] = (byte)value; - } + public static byte SubCode => 0x00; /// - /// Gets or sets when this is true, the attribute is removed on the client side. If it's false, then the attribute is added. + /// Gets the header of this packet. /// - public bool RemoveAttribute - { - get => this._data[5..].GetBoolean(); - set => this._data[5..].SetBoolean(value); - } + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the area count. + /// Gets or sets the character count. /// - public byte AreaCount + public byte CharacterCount { - get => this._data[6]; - set => this._data[6] = value; + get => this._data[4]; + set => this._data[4] = value; } /// - /// Gets the of the specified index. + /// Gets the of the specified index. /// - public TerrainAreaRef this[int index] => new (this._data[(7 + index * TerrainAreaRef.Length)..]); + public CharacterDataRef this[int index] => new (this._data[(5 + index * CharacterDataRef.Length)..]); /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ChangeTerrainAttributesRef(Span packet) => new (packet, false); + public static implicit operator CharacterList075Ref(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ChangeTerrainAttributesRef packet) => packet._data; + public static implicit operator Span(CharacterList075Ref packet) => packet._data; /// - /// Calculates the size of the packet for the specified count of . + /// Calculates the size of the packet for the specified count of . /// - /// The count of from which the size will be calculated. + /// The count of from which the size will be calculated. - public static int GetRequiredSize(int areasCount) => areasCount * TerrainAreaRef.Length + 7; + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 5; /// -/// Defines the area which should be changed.. +/// Data of one character in the list.. /// -public readonly ref struct TerrainAreaRef +public readonly ref struct CharacterDataRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public TerrainAreaRef(Span data) + public CharacterDataRef(Span data) { this._data = data; } @@ -10329,132 +11574,61 @@ public TerrainAreaRef(Span data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 4; + public static int Length => 24; /// - /// Gets or sets the start x. + /// Gets or sets the slot index. /// - public byte StartX + public byte SlotIndex { get => this._data[0]; set => this._data[0] = value; } /// - /// Gets or sets the start y. - /// - public byte StartY - { - get => this._data[1]; - set => this._data[1] = value; - } - - /// - /// Gets or sets the end x. - /// - public byte EndX - { - get => this._data[2]; - set => this._data[2] = value; - } - - /// - /// Gets or sets the end y. + /// Gets or sets the name. /// - public byte EndY + public string Name { - get => this._data[3]; - set => this._data[3] = value; + get => this._data.ExtractString(1, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(1, 10).WriteString(value, System.Text.Encoding.UTF8); } -} -} - - -/// -/// Is sent by the server when: After a player achieved or lost something. -/// Causes reaction on client side: An effect is shown for the affected player. -/// -public readonly ref struct ShowEffectRef -{ - private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Gets or sets the level. /// - /// The underlying data. - public ShowEffectRef(Span data) - : this(data, true) + public ushort Level { + get => ReadUInt16BigEndian(this._data[11..]); + set => WriteUInt16BigEndian(this._data[11..], value); } /// - /// Initializes a new instance of the struct. + /// Gets or sets the status. /// - /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private ShowEffectRef(Span data, bool initialize) + public CharacterStatus Status { - this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - } + get => (CharacterStatus)this._data[13..].GetByteValue(4, 0); + set => this._data[13..].SetByteValue((byte)value, 4, 0); } /// - /// Gets the header type of this data packet. - /// - public static byte HeaderType => 0xC1; - - /// - /// Gets the operation code of this data packet. - /// - public static byte Code => 0x48; - - /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. - /// - public static int Length => 6; - - /// - /// Gets the header of this packet. - /// - public C1HeaderRef Header => new (this._data); - - /// - /// Gets or sets the player id. + /// Gets or sets the is item block active. /// - public ushort PlayerId + public bool IsItemBlockActive { - get => ReadUInt16BigEndian(this._data[3..]); - set => WriteUInt16BigEndian(this._data[3..], value); + get => this._data[13..].GetBoolean(4); + set => this._data[13..].SetBoolean(value, 4); } /// - /// Gets or sets the effect. + /// Gets or sets the appearance. /// - public ShowEffect.EffectType Effect + public Span Appearance { - get => (ShowEffect.EffectType)this._data[5]; - set => this._data[5] = (byte)value; + get => this._data.Slice(14, 9); } - - /// - /// Performs an implicit conversion from a Span of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator ShowEffectRef(Span packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Span of bytes. - /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Span(ShowEffectRef packet) => packet._data; +} } @@ -10462,25 +11636,25 @@ public ShowEffect.EffectType Effect /// Is sent by the server when: After the game client requested it, usually after a successful login. /// Causes reaction on client side: The game client shows the available characters of the account. /// -public readonly ref struct CharacterListRef +public readonly ref struct CharacterList095Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterListRef(Span data) + public CharacterList095Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterListRef(Span data, bool initialize) + private CharacterList095Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -10514,67 +11688,40 @@ private CharacterListRef(Span data, bool initialize) /// public C1HeaderWithSubCodeRef Header => new (this._data); - /// - /// Gets or sets the unlock flags. - /// - public CharacterCreationUnlockFlags UnlockFlags - { - get => (CharacterCreationUnlockFlags)this._data[4]; - set => this._data[4] = (byte)value; - } - - /// - /// Gets or sets the move cnt. - /// - public byte MoveCnt - { - get => this._data[5]; - set => this._data[5] = value; - } - /// /// Gets or sets the character count. /// public byte CharacterCount { - get => this._data[6]; - set => this._data[6] = value; - } - - /// - /// Gets or sets the is vault extended. - /// - public bool IsVaultExtended - { - get => this._data[7..].GetBoolean(); - set => this._data[7..].SetBoolean(value); + get => this._data[4]; + set => this._data[4] = value; } /// /// Gets the of the specified index. /// - public CharacterDataRef this[int index] => new (this._data[(8 + index * CharacterDataRef.Length)..]); + public CharacterDataRef this[int index] => new (this._data[(5 + index * CharacterDataRef.Length)..]); /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterListRef(Span packet) => new (packet, false); + public static implicit operator CharacterList095Ref(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterListRef packet) => packet._data; + public static implicit operator Span(CharacterList095Ref packet) => packet._data; /// /// Calculates the size of the packet for the specified count of . /// /// The count of from which the size will be calculated. - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 8; + public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 5; /// @@ -10596,7 +11743,7 @@ public CharacterDataRef(Span data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 34; + public static int Length => 26; /// /// Gets or sets the slot index. @@ -10648,44 +11795,35 @@ public bool IsItemBlockActive /// public Span Appearance { - get => this._data.Slice(15, 18); - } - - /// - /// Gets or sets the guild position. - /// - public GuildMemberRole GuildPosition - { - get => (GuildMemberRole)this._data[33]; - set => this._data[33] = (byte)value; + get => this._data.Slice(15, 11); } } } /// -/// Is sent by the server when: It's send right after the CharacterList, in the character selection screen, if the account has any unlocked character classes. -/// Causes reaction on client side: The client unlocks the specified character classes, so they can be created. +/// Is sent by the server when: After the server successfully processed a character creation request. +/// Causes reaction on client side: The new character is shown in the character list /// -public readonly ref struct CharacterClassCreationUnlockRef +public readonly ref struct CharacterCreationSuccessfulRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterClassCreationUnlockRef(Span data) + public CharacterCreationSuccessfulRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterClassCreationUnlockRef(Span data, bool initialize) + private CharacterCreationSuccessfulRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -10695,6 +11833,7 @@ private CharacterClassCreationUnlockRef(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Success = true; } } @@ -10706,18 +11845,18 @@ private CharacterClassCreationUnlockRef(Span data, bool initialize) /// /// Gets the operation code of this data packet. /// - public static byte Code => 0xDE; + public static byte Code => 0xF3; /// /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; + public static byte SubCode => 0x01; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 5; + public static int Length => 42; /// /// Gets the header of this packet. @@ -10725,53 +11864,113 @@ private CharacterClassCreationUnlockRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the unlock flags. + /// Gets or sets the success. /// - public CharacterCreationUnlockFlags UnlockFlags + public bool Success { - get => (CharacterCreationUnlockFlags)this._data[4]; - set => this._data[4] = (byte)value; + get => this._data[4..].GetBoolean(); + set => this._data[4..].SetBoolean(value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the character name. + /// + public string CharacterName + { + get => this._data.ExtractString(5, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(5, 10).WriteString(value, System.Text.Encoding.UTF8); + } + + /// + /// Gets or sets the character slot. + /// + public byte CharacterSlot + { + get => this._data[15]; + set => this._data[15] = value; + } + + /// + /// Gets or sets the level. + /// + public ushort Level + { + get => ReadUInt16LittleEndian(this._data[16..]); + set => WriteUInt16LittleEndian(this._data[16..], value); + } + + /// + /// Gets or sets the class. + /// + public CharacterClassNumber Class + { + get => (CharacterClassNumber)this._data[18..].GetByteValue(8, 3); + set => this._data[18..].SetByteValue((byte)value, 8, 3); + } + + /// + /// Gets or sets the character status. + /// + public byte CharacterStatus + { + get => this._data[19]; + set => this._data[19] = value; + } + + /// + /// Gets or sets the preview data. + /// + public Span PreviewData + { + get => this._data.Slice(20); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterClassCreationUnlockRef(Span packet) => new (packet, false); + public static implicit operator CharacterCreationSuccessfulRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterClassCreationUnlockRef packet) => packet._data; + public static implicit operator Span(CharacterCreationSuccessfulRef packet) => packet._data; + + /// + /// Calculates the size of the packet for the specified length of . + /// + /// The length in bytes of on which the required size depends. + + public static int GetRequiredSize(int previewDataLength) => previewDataLength + 20; } /// -/// Is sent by the server when: After the game client requested it, usually after a successful login. -/// Causes reaction on client side: The game client shows the available characters of the account. +/// Is sent by the server when: After the server processed a character creation request without success. +/// Causes reaction on client side: A message is shown that it failed. /// -public readonly ref struct CharacterList075Ref +public readonly ref struct CharacterCreationFailedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterList075Ref(Span data) + public CharacterCreationFailedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterList075Ref(Span data, bool initialize) + private CharacterCreationFailedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -10779,7 +11978,7 @@ private CharacterList075Ref(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; } } @@ -10798,149 +11997,206 @@ private CharacterList075Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; - - /// - /// Gets the header of this packet. - /// - public C1HeaderWithSubCodeRef Header => new (this._data); + public static byte SubCode => 0x01; /// - /// Gets or sets the character count. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public byte CharacterCount - { - get => this._data[4]; - set => this._data[4] = value; - } + public static int Length => 5; /// - /// Gets the of the specified index. + /// Gets the header of this packet. /// - public CharacterDataRef this[int index] => new (this._data[(5 + index * CharacterDataRef.Length)..]); + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterList075Ref(Span packet) => new (packet, false); + public static implicit operator CharacterCreationFailedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterList075Ref packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified count of . - /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 5; + public static implicit operator Span(CharacterCreationFailedRef packet) => packet._data; +} /// -/// Data of one character in the list.. +/// Is sent by the server when: The character respawned after death. +/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. /// -public readonly ref struct CharacterDataRef +public readonly ref struct RespawnAfterDeath075Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterDataRef(Span data) + public RespawnAfterDeath075Ref(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private RespawnAfterDeath075Ref(Span data, bool initialize) { this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + } } + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x04; + /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 24; + public static int Length => 20; /// - /// Gets or sets the slot index. + /// Gets the header of this packet. /// - public byte SlotIndex + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the position x. + /// + public byte PositionX { - get => this._data[0]; - set => this._data[0] = value; + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Gets or sets the position y. + /// + public byte PositionY + { + get => this._data[5]; + set => this._data[5] = value; + } + + /// + /// Gets or sets the map number. + /// + public byte MapNumber + { + get => this._data[6]; + set => this._data[6] = value; + } + + /// + /// Gets or sets the direction. + /// + public byte Direction + { + get => this._data[7]; + set => this._data[7] = value; + } + + /// + /// Gets or sets the current health. + /// + public ushort CurrentHealth + { + get => ReadUInt16LittleEndian(this._data[8..]); + set => WriteUInt16LittleEndian(this._data[8..], value); } /// - /// Gets or sets the name. + /// Gets or sets the current mana. /// - public string Name + public ushort CurrentMana { - get => this._data.ExtractString(1, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(1, 10).WriteString(value, System.Text.Encoding.UTF8); + get => ReadUInt16LittleEndian(this._data[10..]); + set => WriteUInt16LittleEndian(this._data[10..], value); } /// - /// Gets or sets the level. + /// Gets or sets the experience. /// - public ushort Level + public uint Experience { - get => ReadUInt16BigEndian(this._data[11..]); - set => WriteUInt16BigEndian(this._data[11..], value); + get => ReadUInt32LittleEndian(this._data[12..]); + set => WriteUInt32LittleEndian(this._data[12..], value); } /// - /// Gets or sets the status. + /// Gets or sets the money. /// - public CharacterStatus Status + public uint Money { - get => (CharacterStatus)this._data[13..].GetByteValue(4, 0); - set => this._data[13..].SetByteValue((byte)value, 4, 0); + get => ReadUInt32LittleEndian(this._data[16..]); + set => WriteUInt32LittleEndian(this._data[16..], value); } /// - /// Gets or sets the is item block active. + /// Performs an implicit conversion from a Span of bytes to a . /// - public bool IsItemBlockActive - { - get => this._data[13..].GetBoolean(4); - set => this._data[13..].SetBoolean(value, 4); - } + /// The packet as span. + /// The packet as struct. + public static implicit operator RespawnAfterDeath075Ref(Span packet) => new (packet, false); /// - /// Gets or sets the appearance. + /// Performs an implicit conversion from to a Span of bytes. /// - public Span Appearance - { - get => this._data.Slice(14, 9); - } -} + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(RespawnAfterDeath075Ref packet) => packet._data; } /// -/// Is sent by the server when: After the game client requested it, usually after a successful login. -/// Causes reaction on client side: The game client shows the available characters of the account. +/// Is sent by the server when: The character respawned after death. +/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. /// -public readonly ref struct CharacterList095Ref +public readonly ref struct RespawnAfterDeath095Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterList095Ref(Span data) + public RespawnAfterDeath095Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterList095Ref(Span data, bool initialize) + private RespawnAfterDeath095Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -10948,7 +12204,7 @@ private CharacterList095Ref(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; } } @@ -10967,7 +12223,12 @@ private CharacterList095Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x00; + public static byte SubCode => 0x04; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 22; /// /// Gets the header of this packet. @@ -10975,141 +12236,125 @@ private CharacterList095Ref(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the character count. + /// Gets or sets the position x. /// - public byte CharacterCount + public byte PositionX { get => this._data[4]; set => this._data[4] = value; } /// - /// Gets the of the specified index. - /// - public CharacterDataRef this[int index] => new (this._data[(5 + index * CharacterDataRef.Length)..]); - - /// - /// Performs an implicit conversion from a Span of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator CharacterList095Ref(Span packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Span of bytes. - /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Span(CharacterList095Ref packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified count of . + /// Gets or sets the position y. /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int charactersCount) => charactersCount * CharacterDataRef.Length + 5; - - -/// -/// Data of one character in the list.. -/// -public readonly ref struct CharacterDataRef -{ - private readonly Span _data; + public byte PositionY + { + get => this._data[5]; + set => this._data[5] = value; + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the map number. /// - /// The underlying data. - public CharacterDataRef(Span data) + public byte MapNumber { - this._data = data; + get => this._data[6]; + set => this._data[6] = value; } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the direction. /// - public static int Length => 26; + public byte Direction + { + get => this._data[7]; + set => this._data[7] = value; + } /// - /// Gets or sets the slot index. + /// Gets or sets the current health. /// - public byte SlotIndex + public ushort CurrentHealth { - get => this._data[0]; - set => this._data[0] = value; + get => ReadUInt16LittleEndian(this._data[8..]); + set => WriteUInt16LittleEndian(this._data[8..], value); } /// - /// Gets or sets the name. + /// Gets or sets the current mana. /// - public string Name + public ushort CurrentMana { - get => this._data.ExtractString(1, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(1, 10).WriteString(value, System.Text.Encoding.UTF8); + get => ReadUInt16LittleEndian(this._data[10..]); + set => WriteUInt16LittleEndian(this._data[10..], value); } /// - /// Gets or sets the level. + /// Gets or sets the current ability. /// - public ushort Level + public ushort CurrentAbility { get => ReadUInt16LittleEndian(this._data[12..]); set => WriteUInt16LittleEndian(this._data[12..], value); } /// - /// Gets or sets the status. + /// Gets or sets the experience. /// - public CharacterStatus Status + public uint Experience { - get => (CharacterStatus)this._data[14..].GetByteValue(4, 0); - set => this._data[14..].SetByteValue((byte)value, 4, 0); + get => ReadUInt32LittleEndian(this._data[14..]); + set => WriteUInt32LittleEndian(this._data[14..], value); } /// - /// Gets or sets the is item block active. + /// Gets or sets the money. /// - public bool IsItemBlockActive + public uint Money { - get => this._data[14..].GetBoolean(4); - set => this._data[14..].SetBoolean(value, 4); + get => ReadUInt32LittleEndian(this._data[18..]); + set => WriteUInt32LittleEndian(this._data[18..], value); } /// - /// Gets or sets the appearance. + /// Performs an implicit conversion from a Span of bytes to a . /// - public Span Appearance - { - get => this._data.Slice(15, 11); - } -} + /// The packet as span. + /// The packet as struct. + public static implicit operator RespawnAfterDeath095Ref(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(RespawnAfterDeath095Ref packet) => packet._data; } /// -/// Is sent by the server when: After the server successfully processed a character creation request. -/// Causes reaction on client side: The new character is shown in the character list +/// Is sent by the server when: The character got damaged by being poisoned on old client versions. +/// Causes reaction on client side: Removes the damage from the health without showing a damage number. /// -public readonly ref struct CharacterCreationSuccessfulRef +public readonly ref struct PoisonDamageRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterCreationSuccessfulRef(Span data) + public PoisonDamageRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterCreationSuccessfulRef(Span data, bool initialize) + private PoisonDamageRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -11119,7 +12364,6 @@ private CharacterCreationSuccessfulRef(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Success = true; } } @@ -11137,12 +12381,12 @@ private CharacterCreationSuccessfulRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x01; + public static byte SubCode => 0x07; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 42; + public static int Length => 8; /// /// Gets the header of this packet. @@ -11150,113 +12394,62 @@ private CharacterCreationSuccessfulRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the success. - /// - public bool Success - { - get => this._data[4..].GetBoolean(); - set => this._data[4..].SetBoolean(value); - } - - /// - /// Gets or sets the character name. - /// - public string CharacterName - { - get => this._data.ExtractString(5, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(5, 10).WriteString(value, System.Text.Encoding.UTF8); - } - - /// - /// Gets or sets the character slot. - /// - public byte CharacterSlot - { - get => this._data[15]; - set => this._data[15] = value; - } - - /// - /// Gets or sets the level. - /// - public ushort Level - { - get => ReadUInt16LittleEndian(this._data[16..]); - set => WriteUInt16LittleEndian(this._data[16..], value); - } - - /// - /// Gets or sets the class. - /// - public CharacterClassNumber Class - { - get => (CharacterClassNumber)this._data[18..].GetByteValue(8, 3); - set => this._data[18..].SetByteValue((byte)value, 8, 3); - } - - /// - /// Gets or sets the character status. + /// Gets or sets the health damage. /// - public byte CharacterStatus + public ushort HealthDamage { - get => this._data[19]; - set => this._data[19] = value; + get => ReadUInt16BigEndian(this._data[4..]); + set => WriteUInt16BigEndian(this._data[4..], value); } /// - /// Gets or sets the preview data. + /// Gets or sets the current shield. /// - public Span PreviewData + public ushort CurrentShield { - get => this._data.Slice(20); + get => ReadUInt16BigEndian(this._data[6..]); + set => WriteUInt16BigEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterCreationSuccessfulRef(Span packet) => new (packet, false); + public static implicit operator PoisonDamageRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterCreationSuccessfulRef packet) => packet._data; - - /// - /// Calculates the size of the packet for the specified length of . - /// - /// The length in bytes of on which the required size depends. - - public static int GetRequiredSize(int previewDataLength) => previewDataLength + 20; + public static implicit operator Span(PoisonDamageRef packet) => packet._data; } /// -/// Is sent by the server when: After the server processed a character creation request without success. -/// Causes reaction on client side: A message is shown that it failed. +/// Is sent by the server when: After a the hero state of an observed character changed. +/// Causes reaction on client side: The color of the name of the character is changed accordingly and a message is shown. /// -public readonly ref struct CharacterCreationFailedRef +public readonly ref struct HeroStateChangedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterCreationFailedRef(Span data) + public HeroStateChangedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterCreationFailedRef(Span data, bool initialize) + private HeroStateChangedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -11283,12 +12476,12 @@ private CharacterCreationFailedRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x01; + public static byte SubCode => 0x08; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 5; + public static int Length => 7; /// /// Gets the header of this packet. @@ -11296,44 +12489,62 @@ private CharacterCreationFailedRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the player id. + /// + public ushort PlayerId + { + get => ReadUInt16BigEndian(this._data[4..]); + set => WriteUInt16BigEndian(this._data[4..], value); + } + + /// + /// Gets or sets the new state. + /// + public CharacterHeroState NewState + { + get => (CharacterHeroState)this._data[6]; + set => this._data[6] = (byte)value; + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterCreationFailedRef(Span packet) => new (packet, false); + public static implicit operator HeroStateChangedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterCreationFailedRef packet) => packet._data; + public static implicit operator Span(HeroStateChangedRef packet) => packet._data; } /// -/// Is sent by the server when: The character respawned after death. -/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. +/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. +/// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly ref struct RespawnAfterDeath075Ref +public readonly ref struct SkillAddedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public RespawnAfterDeath075Ref(Span data) + public SkillAddedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private RespawnAfterDeath075Ref(Span data, bool initialize) + private SkillAddedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -11343,6 +12554,7 @@ private RespawnAfterDeath075Ref(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Flag = 0xFE; } } @@ -11360,12 +12572,12 @@ private RespawnAfterDeath075Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x04; + public static byte SubCode => 0x11; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 20; + public static int Length => 10; /// /// Gets the header of this packet. @@ -11373,116 +12585,185 @@ private RespawnAfterDeath075Ref(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the position x. + /// Gets or sets the flag. /// - public byte PositionX + public byte Flag { get => this._data[4]; set => this._data[4] = value; } /// - /// Gets or sets the position y. + /// Gets or sets the skill index. /// - public byte PositionY + public byte SkillIndex { - get => this._data[5]; - set => this._data[5] = value; + get => this._data[6]; + set => this._data[6] = value; } /// - /// Gets or sets the map number. + /// Gets or sets the skill number. /// - public byte MapNumber + public ushort SkillNumber { - get => this._data[6]; - set => this._data[6] = value; + get => ReadUInt16LittleEndian(this._data[7..]); + set => WriteUInt16LittleEndian(this._data[7..], value); } /// - /// Gets or sets the direction. + /// Gets or sets the skill level. /// - public byte Direction + public byte SkillLevel { - get => this._data[7]; - set => this._data[7] = value; + get => this._data[9]; + set => this._data[9] = value; } /// - /// Gets or sets the current health. + /// Performs an implicit conversion from a Span of bytes to a . /// - public ushort CurrentHealth + /// The packet as span. + /// The packet as struct. + public static implicit operator SkillAddedRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(SkillAddedRef packet) => packet._data; +} + + +/// +/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. +/// Causes reaction on client side: The skill is added to the skill list on client side. +/// +public readonly ref struct SkillRemovedRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public SkillRemovedRef(Span data) + : this(data, true) { - get => ReadUInt16LittleEndian(this._data[8..]); - set => WriteUInt16LittleEndian(this._data[8..], value); } /// - /// Gets or sets the current mana. + /// Initializes a new instance of the struct. /// - public ushort CurrentMana + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private SkillRemovedRef(Span data, bool initialize) { - get => ReadUInt16LittleEndian(this._data[10..]); - set => WriteUInt16LittleEndian(this._data[10..], value); + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + this.Flag = 0xFF; + } } /// - /// Gets or sets the experience. + /// Gets the header type of this data packet. /// - public uint Experience + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x11; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 10; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the flag. + /// + public byte Flag { - get => ReadUInt32LittleEndian(this._data[12..]); - set => WriteUInt32LittleEndian(this._data[12..], value); + get => this._data[4]; + set => this._data[4] = value; } /// - /// Gets or sets the money. + /// Gets or sets the skill index. /// - public uint Money + public byte SkillIndex { - get => ReadUInt32LittleEndian(this._data[16..]); - set => WriteUInt32LittleEndian(this._data[16..], value); + get => this._data[6]; + set => this._data[6] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the skill number. + /// + public ushort SkillNumber + { + get => ReadUInt16LittleEndian(this._data[7..]); + set => WriteUInt16LittleEndian(this._data[7..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator RespawnAfterDeath075Ref(Span packet) => new (packet, false); + public static implicit operator SkillRemovedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(RespawnAfterDeath075Ref packet) => packet._data; + public static implicit operator Span(SkillRemovedRef packet) => packet._data; } /// -/// Is sent by the server when: The character respawned after death. -/// Causes reaction on client side: The character respawns with the specified attributes at the specified map. +/// Is sent by the server when: Usually, when the player entered the game with a character. When skills get added or removed, this message is sent as well, but with a misleading count. +/// Causes reaction on client side: The skill list gets initialized. /// -public readonly ref struct RespawnAfterDeath095Ref +public readonly ref struct SkillListUpdateRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public RespawnAfterDeath095Ref(Span data) + public SkillListUpdateRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private RespawnAfterDeath095Ref(Span data, bool initialize) + private SkillListUpdateRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -11490,7 +12771,7 @@ private RespawnAfterDeath095Ref(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); + header.Length = (byte)data.Length; header.SubCode = SubCode; } } @@ -11509,12 +12790,7 @@ private RespawnAfterDeath095Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x04; - - /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. - /// - public static int Length => 22; + public static byte SubCode => 0x11; /// /// Gets the header of this packet. @@ -11522,125 +12798,115 @@ private RespawnAfterDeath095Ref(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the position x. + /// Gets or sets mixed usage: Skill list count (when list). 0xFE when adding a skill, 0xFF when removing a Skill. /// - public byte PositionX + public byte Count { get => this._data[4]; set => this._data[4] = value; } /// - /// Gets or sets the position y. + /// Gets the of the specified index. /// - public byte PositionY - { - get => this._data[5]; - set => this._data[5] = value; - } + public SkillEntryRef this[int index] => new (this._data[(6 + index * SkillEntryRef.Length)..]); + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator SkillListUpdateRef(Span packet) => new (packet, false); /// - /// Gets or sets the map number. + /// Performs an implicit conversion from to a Span of bytes. /// - public byte MapNumber - { - get => this._data[6]; - set => this._data[6] = value; - } + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(SkillListUpdateRef packet) => packet._data; /// - /// Gets or sets the direction. + /// Calculates the size of the packet for the specified count of . /// - public byte Direction - { - get => this._data[7]; - set => this._data[7] = value; - } + /// The count of from which the size will be calculated. + + public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntryRef.Length + 6; + + +/// +/// Structure for a skill entry of the skill list.. +/// +public readonly ref struct SkillEntryRef +{ + private readonly Span _data; /// - /// Gets or sets the current health. + /// Initializes a new instance of the struct. /// - public ushort CurrentHealth + /// The underlying data. + public SkillEntryRef(Span data) { - get => ReadUInt16LittleEndian(this._data[8..]); - set => WriteUInt16LittleEndian(this._data[8..], value); + this._data = data; } /// - /// Gets or sets the current mana. + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public ushort CurrentMana - { - get => ReadUInt16LittleEndian(this._data[10..]); - set => WriteUInt16LittleEndian(this._data[10..], value); - } + public static int Length => 4; /// - /// Gets or sets the current ability. + /// Gets or sets the skill index. /// - public ushort CurrentAbility + public byte SkillIndex { - get => ReadUInt16LittleEndian(this._data[12..]); - set => WriteUInt16LittleEndian(this._data[12..], value); + get => this._data[0]; + set => this._data[0] = value; } /// - /// Gets or sets the experience. + /// Gets or sets the skill number. /// - public uint Experience + public ushort SkillNumber { - get => ReadUInt32LittleEndian(this._data[14..]); - set => WriteUInt32LittleEndian(this._data[14..], value); + get => ReadUInt16LittleEndian(this._data[1..]); + set => WriteUInt16LittleEndian(this._data[1..], value); } /// - /// Gets or sets the money. + /// Gets or sets the skill level. /// - public uint Money + public byte SkillLevel { - get => ReadUInt32LittleEndian(this._data[18..]); - set => WriteUInt32LittleEndian(this._data[18..], value); + get => this._data[3]; + set => this._data[3] = value; } - - /// - /// Performs an implicit conversion from a Span of bytes to a . - /// - /// The packet as span. - /// The packet as struct. - public static implicit operator RespawnAfterDeath095Ref(Span packet) => new (packet, false); - - /// - /// Performs an implicit conversion from to a Span of bytes. - /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Span(RespawnAfterDeath095Ref packet) => packet._data; +} } /// -/// Is sent by the server when: The character got damaged by being poisoned on old client versions. -/// Causes reaction on client side: Removes the damage from the health without showing a damage number. +/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. +/// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly ref struct PoisonDamageRef +public readonly ref struct SkillAdded075Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public PoisonDamageRef(Span data) + public SkillAdded075Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private PoisonDamageRef(Span data, bool initialize) + private SkillAdded075Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -11650,6 +12916,7 @@ private PoisonDamageRef(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Flag = 1; } } @@ -11667,7 +12934,7 @@ private PoisonDamageRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x07; + public static byte SubCode => 0x11; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. @@ -11680,62 +12947,71 @@ private PoisonDamageRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the health damage. + /// Gets or sets the flag. /// - public ushort HealthDamage + public byte Flag { - get => ReadUInt16BigEndian(this._data[4..]); - set => WriteUInt16BigEndian(this._data[4..], value); + get => this._data[4]; + set => this._data[4] = value; } /// - /// Gets or sets the current shield. + /// Gets or sets the skill index. /// - public ushort CurrentShield + public byte SkillIndex + { + get => this._data[5]; + set => this._data[5] = value; + } + + /// + /// Gets or sets the skill number and level. + /// + public ushort SkillNumberAndLevel { get => ReadUInt16BigEndian(this._data[6..]); set => WriteUInt16BigEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PoisonDamageRef(Span packet) => new (packet, false); + public static implicit operator SkillAdded075Ref(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(PoisonDamageRef packet) => packet._data; + public static implicit operator Span(SkillAdded075Ref packet) => packet._data; } /// -/// Is sent by the server when: After a the hero state of an observed character changed. -/// Causes reaction on client side: The color of the name of the character is changed accordingly and a message is shown. +/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. +/// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly ref struct HeroStateChangedRef +public readonly ref struct SkillRemoved075Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public HeroStateChangedRef(Span data) + public SkillRemoved075Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private HeroStateChangedRef(Span data, bool initialize) + private SkillRemoved075Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -11745,6 +13021,7 @@ private HeroStateChangedRef(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; + this.Flag = 0; } } @@ -11762,12 +13039,12 @@ private HeroStateChangedRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x08; + public static byte SubCode => 0x11; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 7; + public static int Length => 10; /// /// Gets the header of this packet. @@ -11775,36 +13052,45 @@ private HeroStateChangedRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the player id. + /// Gets or sets the flag. /// - public ushort PlayerId + public byte Flag { - get => ReadUInt16BigEndian(this._data[4..]); - set => WriteUInt16BigEndian(this._data[4..], value); + get => this._data[4]; + set => this._data[4] = value; } /// - /// Gets or sets the new state. + /// Gets or sets the skill index. /// - public CharacterHeroState NewState + public byte SkillIndex { - get => (CharacterHeroState)this._data[6]; - set => this._data[6] = (byte)value; + get => this._data[5]; + set => this._data[5] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the skill number and level. + /// + public ushort SkillNumberAndLevel + { + get => ReadUInt16BigEndian(this._data[6..]); + set => WriteUInt16BigEndian(this._data[6..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator HeroStateChangedRef(Span packet) => new (packet, false); + public static implicit operator SkillRemoved075Ref(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(HeroStateChangedRef packet) => packet._data; + public static implicit operator Span(SkillRemoved075Ref packet) => packet._data; } @@ -11812,25 +13098,25 @@ public CharacterHeroState NewState /// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. /// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly ref struct SkillAddedRef +public readonly ref struct SkillAdded095Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillAddedRef(Span data) + public SkillAdded095Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillAddedRef(Span data, bool initialize) + private SkillAdded095Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -11863,7 +13149,7 @@ private SkillAddedRef(Span data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 10; + public static int Length => 8; /// /// Gets the header of this packet. @@ -11884,41 +13170,32 @@ public byte Flag /// public byte SkillIndex { - get => this._data[6]; - set => this._data[6] = value; - } - - /// - /// Gets or sets the skill number. - /// - public ushort SkillNumber - { - get => ReadUInt16LittleEndian(this._data[7..]); - set => WriteUInt16LittleEndian(this._data[7..], value); + get => this._data[5]; + set => this._data[5] = value; } /// - /// Gets or sets the skill level. + /// Gets or sets the skill number and level. /// - public byte SkillLevel + public ushort SkillNumberAndLevel { - get => this._data[9]; - set => this._data[9] = value; + get => ReadUInt16BigEndian(this._data[6..]); + set => WriteUInt16BigEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillAddedRef(Span packet) => new (packet, false); + public static implicit operator SkillAdded095Ref(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(SkillAddedRef packet) => packet._data; + public static implicit operator Span(SkillAdded095Ref packet) => packet._data; } @@ -11926,25 +13203,25 @@ public byte SkillLevel /// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. /// Causes reaction on client side: The skill is added to the skill list on client side. /// -public readonly ref struct SkillRemovedRef +public readonly ref struct SkillRemoved095Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillRemovedRef(Span data) + public SkillRemoved095Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillRemovedRef(Span data, bool initialize) + private SkillRemoved095Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -11998,32 +13275,32 @@ public byte Flag /// public byte SkillIndex { - get => this._data[6]; - set => this._data[6] = value; + get => this._data[5]; + set => this._data[5] = value; } /// - /// Gets or sets the skill number. + /// Gets or sets the skill number and level. /// - public ushort SkillNumber + public ushort SkillNumberAndLevel { - get => ReadUInt16LittleEndian(this._data[7..]); - set => WriteUInt16LittleEndian(this._data[7..], value); + get => ReadUInt16BigEndian(this._data[6..]); + set => WriteUInt16BigEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillRemovedRef(Span packet) => new (packet, false); + public static implicit operator SkillRemoved095Ref(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(SkillRemovedRef packet) => packet._data; + public static implicit operator Span(SkillRemoved095Ref packet) => packet._data; } @@ -12031,25 +13308,25 @@ public ushort SkillNumber /// Is sent by the server when: Usually, when the player entered the game with a character. When skills get added or removed, this message is sent as well, but with a misleading count. /// Causes reaction on client side: The skill list gets initialized. /// -public readonly ref struct SkillListUpdateRef +public readonly ref struct SkillListUpdate075Ref { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillListUpdateRef(Span data) + public SkillListUpdate075Ref(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillListUpdateRef(Span data, bool initialize) + private SkillListUpdate075Ref(Span data, bool initialize) { this._data = data; if (initialize) @@ -12095,28 +13372,28 @@ public byte Count /// /// Gets the of the specified index. /// - public SkillEntryRef this[int index] => new (this._data[(6 + index * SkillEntryRef.Length)..]); + public SkillEntryRef this[int index] => new (this._data[(5 + index * SkillEntryRef.Length)..]); /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillListUpdateRef(Span packet) => new (packet, false); + public static implicit operator SkillListUpdate075Ref(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(SkillListUpdateRef packet) => packet._data; + public static implicit operator Span(SkillListUpdate075Ref packet) => packet._data; /// /// Calculates the size of the packet for the specified count of . /// /// The count of from which the size will be calculated. - public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntryRef.Length + 6; + public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntryRef.Length + 5; /// @@ -12138,7 +13415,7 @@ public SkillEntryRef(Span data) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 4; + public static int Length => 3; /// /// Gets or sets the skill index. @@ -12150,49 +13427,40 @@ public byte SkillIndex } /// - /// Gets or sets the skill number. - /// - public ushort SkillNumber - { - get => ReadUInt16LittleEndian(this._data[1..]); - set => WriteUInt16LittleEndian(this._data[1..], value); - } - - /// - /// Gets or sets the skill level. + /// Gets or sets the skill number and level. /// - public byte SkillLevel + public ushort SkillNumberAndLevel { - get => this._data[3]; - set => this._data[3] = value; + get => ReadUInt16BigEndian(this._data[1..]); + set => WriteUInt16BigEndian(this._data[1..], value); } } } /// -/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the client focused the character successfully on the server side. +/// Causes reaction on client side: The client highlights the focused character. /// -public readonly ref struct SkillAdded075Ref +public readonly ref struct CharacterFocusedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillAdded075Ref(Span data) + public CharacterFocusedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillAdded075Ref(Span data, bool initialize) + private CharacterFocusedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -12202,7 +13470,6 @@ private SkillAdded075Ref(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 1; } } @@ -12220,12 +13487,12 @@ private SkillAdded075Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x15; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 15; /// /// Gets the header of this packet. @@ -12233,71 +13500,53 @@ private SkillAdded075Ref(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the flag. - /// - public byte Flag - { - get => this._data[4]; - set => this._data[4] = value; - } - - /// - /// Gets or sets the skill index. - /// - public byte SkillIndex - { - get => this._data[5]; - set => this._data[5] = value; - } - - /// - /// Gets or sets the skill number and level. + /// Gets or sets the character name. /// - public ushort SkillNumberAndLevel + public string CharacterName { - get => ReadUInt16BigEndian(this._data[6..]); - set => WriteUInt16BigEndian(this._data[6..], value); + get => this._data.ExtractString(4, 10, System.Text.Encoding.UTF8); + set => this._data.Slice(4, 10).WriteString(value, System.Text.Encoding.UTF8); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillAdded075Ref(Span packet) => new (packet, false); + public static implicit operator CharacterFocusedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(SkillAdded075Ref packet) => packet._data; + public static implicit operator Span(CharacterFocusedRef packet) => packet._data; } /// -/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the server processed a character stat increase request packet. +/// Causes reaction on client side: If it was successful, adds a point to the requested stat type. /// -public readonly ref struct SkillRemoved075Ref +public readonly ref struct CharacterStatIncreaseResponseRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillRemoved075Ref(Span data) + public CharacterStatIncreaseResponseRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillRemoved075Ref(Span data, bool initialize) + private CharacterStatIncreaseResponseRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -12307,7 +13556,6 @@ private SkillRemoved075Ref(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 0; } } @@ -12325,12 +13573,12 @@ private SkillRemoved075Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x06; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 10; + public static int Length => 12; /// /// Gets the header of this packet. @@ -12338,71 +13586,89 @@ private SkillRemoved075Ref(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the flag. + /// Gets or sets the success. /// - public byte Flag + public bool Success { - get => this._data[4]; - set => this._data[4] = value; + get => this._data[4..].GetBoolean(4); + set => this._data[4..].SetBoolean(value, 4); } /// - /// Gets or sets the skill index. + /// Gets or sets the attribute. /// - public byte SkillIndex + public CharacterStatAttribute Attribute { - get => this._data[5]; - set => this._data[5] = value; + get => (CharacterStatAttribute)this._data[4..].GetByteValue(4, 0); + set => this._data[4..].SetByteValue((byte)value, 4, 0); } /// - /// Gets or sets the skill number and level. + /// Gets or sets the updated dependent maximum stat. /// - public ushort SkillNumberAndLevel + public ushort UpdatedDependentMaximumStat { - get => ReadUInt16BigEndian(this._data[6..]); - set => WriteUInt16BigEndian(this._data[6..], value); + get => ReadUInt16LittleEndian(this._data[6..]); + set => WriteUInt16LittleEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the updated maximum shield. + /// + public ushort UpdatedMaximumShield + { + get => ReadUInt16LittleEndian(this._data[8..]); + set => WriteUInt16LittleEndian(this._data[8..], value); + } + + /// + /// Gets or sets the updated maximum ability. + /// + public ushort UpdatedMaximumAbility + { + get => ReadUInt16LittleEndian(this._data[10..]); + set => WriteUInt16LittleEndian(this._data[10..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillRemoved075Ref(Span packet) => new (packet, false); + public static implicit operator CharacterStatIncreaseResponseRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(SkillRemoved075Ref packet) => packet._data; + public static implicit operator Span(CharacterStatIncreaseResponseRef packet) => packet._data; } /// -/// Is sent by the server when: After a skill got added to the skill list, e.g. by equipping an item or learning a skill. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the server processed a character stat increase request packet. +/// Causes reaction on client side: If it was successful, adds a point to the requested stat type. /// -public readonly ref struct SkillAdded095Ref +public readonly ref struct CharacterStatIncreaseResponseExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillAdded095Ref(Span data) + public CharacterStatIncreaseResponseExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillAdded095Ref(Span data, bool initialize) + private CharacterStatIncreaseResponseExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -12412,7 +13678,6 @@ private SkillAdded095Ref(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 0xFE; } } @@ -12430,12 +13695,12 @@ private SkillAdded095Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x06; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 8; + public static int Length => 24; /// /// Gets the header of this packet. @@ -12443,71 +13708,98 @@ private SkillAdded095Ref(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the flag. + /// Gets or sets the attribute. /// - public byte Flag + public CharacterStatAttribute Attribute { - get => this._data[4]; - set => this._data[4] = value; + get => (CharacterStatAttribute)this._data[4]; + set => this._data[4] = (byte)value; } /// - /// Gets or sets the skill index. + /// Gets or sets the added amount. /// - public byte SkillIndex + public ushort AddedAmount { - get => this._data[5]; - set => this._data[5] = value; + get => ReadUInt16LittleEndian(this._data[6..]); + set => WriteUInt16LittleEndian(this._data[6..], value); } /// - /// Gets or sets the skill number and level. + /// Gets or sets the updated maximum health. /// - public ushort SkillNumberAndLevel + public uint UpdatedMaximumHealth { - get => ReadUInt16BigEndian(this._data[6..]); - set => WriteUInt16BigEndian(this._data[6..], value); + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the updated maximum mana. + /// + public uint UpdatedMaximumMana + { + get => ReadUInt32LittleEndian(this._data[12..]); + set => WriteUInt32LittleEndian(this._data[12..], value); + } + + /// + /// Gets or sets the updated maximum shield. + /// + public uint UpdatedMaximumShield + { + get => ReadUInt32LittleEndian(this._data[16..]); + set => WriteUInt32LittleEndian(this._data[16..], value); + } + + /// + /// Gets or sets the updated maximum ability. + /// + public uint UpdatedMaximumAbility + { + get => ReadUInt32LittleEndian(this._data[20..]); + set => WriteUInt32LittleEndian(this._data[20..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillAdded095Ref(Span packet) => new (packet, false); + public static implicit operator CharacterStatIncreaseResponseExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(SkillAdded095Ref packet) => packet._data; + public static implicit operator Span(CharacterStatIncreaseResponseExtendedRef packet) => packet._data; } /// -/// Is sent by the server when: After a skill got removed from the skill list, e.g. by removing an equipped item. -/// Causes reaction on client side: The skill is added to the skill list on client side. +/// Is sent by the server when: After the server processed a character delete response of the client. +/// Causes reaction on client side: If successful, the character is deleted from the character selection screen. Otherwise, a message is shown. /// -public readonly ref struct SkillRemoved095Ref +public readonly ref struct CharacterDeleteResponseRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillRemoved095Ref(Span data) + public CharacterDeleteResponseRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillRemoved095Ref(Span data, bool initialize) + private CharacterDeleteResponseRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -12517,7 +13809,6 @@ private SkillRemoved095Ref(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.Flag = 0xFF; } } @@ -12535,84 +13826,66 @@ private SkillRemoved095Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x02; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 10; + public static int Length => 5; /// /// Gets the header of this packet. /// - public C1HeaderWithSubCodeRef Header => new (this._data); - - /// - /// Gets or sets the flag. - /// - public byte Flag - { - get => this._data[4]; - set => this._data[4] = value; - } - - /// - /// Gets or sets the skill index. - /// - public byte SkillIndex - { - get => this._data[5]; - set => this._data[5] = value; - } + public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the skill number and level. + /// Gets or sets the result. /// - public ushort SkillNumberAndLevel + public CharacterDeleteResponse.CharacterDeleteResult Result { - get => ReadUInt16BigEndian(this._data[6..]); - set => WriteUInt16BigEndian(this._data[6..], value); + get => (CharacterDeleteResponse.CharacterDeleteResult)this._data[4]; + set => this._data[4] = (byte)value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator SkillRemoved095Ref(Span packet) => new (packet, false); + public static implicit operator CharacterDeleteResponseRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(SkillRemoved095Ref packet) => packet._data; + public static implicit operator Span(CharacterDeleteResponseRef packet) => packet._data; } /// -/// Is sent by the server when: Usually, when the player entered the game with a character. When skills get added or removed, this message is sent as well, but with a misleading count. -/// Causes reaction on client side: The skill list gets initialized. +/// Is sent by the server when: After a character leveled up. +/// Causes reaction on client side: Updates the level (and other related stats) in the game client and shows an effect. /// -public readonly ref struct SkillListUpdate075Ref +public readonly ref struct CharacterLevelUpdateRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public SkillListUpdate075Ref(Span data) + public CharacterLevelUpdateRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private SkillListUpdate075Ref(Span data, bool initialize) + private CharacterLevelUpdateRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -12620,7 +13893,7 @@ private SkillListUpdate075Ref(Span data, bool initialize) var header = this.Header; header.Type = HeaderType; header.Code = Code; - header.Length = (byte)data.Length; + header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; } } @@ -12639,7 +13912,12 @@ private SkillListUpdate075Ref(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x11; + public static byte SubCode => 0x05; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 24; /// /// Gets the header of this packet. @@ -12647,106 +13925,134 @@ private SkillListUpdate075Ref(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets mixed usage: Skill list count (when list). 0xFE when adding a skill, 0xFF when removing a Skill. + /// Gets or sets the level. /// - public byte Count + public ushort Level { - get => this._data[4]; - set => this._data[4] = value; + get => ReadUInt16LittleEndian(this._data[4..]); + set => WriteUInt16LittleEndian(this._data[4..], value); } /// - /// Gets the of the specified index. + /// Gets or sets the level up points. /// - public SkillEntryRef this[int index] => new (this._data[(5 + index * SkillEntryRef.Length)..]); + public ushort LevelUpPoints + { + get => ReadUInt16LittleEndian(this._data[6..]); + set => WriteUInt16LittleEndian(this._data[6..], value); + } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the maximum health. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator SkillListUpdate075Ref(Span packet) => new (packet, false); + public ushort MaximumHealth + { + get => ReadUInt16LittleEndian(this._data[8..]); + set => WriteUInt16LittleEndian(this._data[8..], value); + } /// - /// Performs an implicit conversion from to a Span of bytes. + /// Gets or sets the maximum mana. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Span(SkillListUpdate075Ref packet) => packet._data; + public ushort MaximumMana + { + get => ReadUInt16LittleEndian(this._data[10..]); + set => WriteUInt16LittleEndian(this._data[10..], value); + } /// - /// Calculates the size of the packet for the specified count of . + /// Gets or sets the maximum shield. /// - /// The count of from which the size will be calculated. - - public static int GetRequiredSize(int skillsCount) => skillsCount * SkillEntryRef.Length + 5; - + public ushort MaximumShield + { + get => ReadUInt16LittleEndian(this._data[12..]); + set => WriteUInt16LittleEndian(this._data[12..], value); + } -/// -/// Structure for a skill entry of the skill list.. -/// -public readonly ref struct SkillEntryRef -{ - private readonly Span _data; + /// + /// Gets or sets the maximum ability. + /// + public ushort MaximumAbility + { + get => ReadUInt16LittleEndian(this._data[14..]); + set => WriteUInt16LittleEndian(this._data[14..], value); + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the fruit points. /// - /// The underlying data. - public SkillEntryRef(Span data) + public ushort FruitPoints { - this._data = data; + get => ReadUInt16LittleEndian(this._data[16..]); + set => WriteUInt16LittleEndian(this._data[16..], value); } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the maximum fruit points. /// - public static int Length => 3; + public ushort MaximumFruitPoints + { + get => ReadUInt16LittleEndian(this._data[18..]); + set => WriteUInt16LittleEndian(this._data[18..], value); + } /// - /// Gets or sets the skill index. + /// Gets or sets the negative fruit points. /// - public byte SkillIndex + public ushort NegativeFruitPoints { - get => this._data[0]; - set => this._data[0] = value; + get => ReadUInt16LittleEndian(this._data[20..]); + set => WriteUInt16LittleEndian(this._data[20..], value); } /// - /// Gets or sets the skill number and level. + /// Gets or sets the maximum negative fruit points. /// - public ushort SkillNumberAndLevel + public ushort MaximumNegativeFruitPoints { - get => ReadUInt16BigEndian(this._data[1..]); - set => WriteUInt16BigEndian(this._data[1..], value); + get => ReadUInt16LittleEndian(this._data[22..]); + set => WriteUInt16LittleEndian(this._data[22..], value); } -} + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator CharacterLevelUpdateRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(CharacterLevelUpdateRef packet) => packet._data; } /// -/// Is sent by the server when: After the client focused the character successfully on the server side. -/// Causes reaction on client side: The client highlights the focused character. +/// Is sent by the server when: After the character was selected by the player and entered the game. +/// Causes reaction on client side: The characters enters the game world. /// -public readonly ref struct CharacterFocusedRef +public readonly ref struct CharacterInformationRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterFocusedRef(Span data) + public CharacterInformationRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterFocusedRef(Span data, bool initialize) + private CharacterInformationRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -12762,7 +14068,7 @@ private CharacterFocusedRef(Span data, bool initialize) /// /// Gets the header type of this data packet. /// - public static byte HeaderType => 0xC1; + public static byte HeaderType => 0xC3; /// /// Gets the operation code of this data packet. @@ -12773,248 +14079,274 @@ private CharacterFocusedRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x15; + public static byte SubCode => 0x03; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 15; + public static int Length => 72; /// /// Gets the header of this packet. /// - public C1HeaderWithSubCodeRef Header => new (this._data); + public C3HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the character name. + /// Gets or sets the x. /// - public string CharacterName + public byte X { - get => this._data.ExtractString(4, 10, System.Text.Encoding.UTF8); - set => this._data.Slice(4, 10).WriteString(value, System.Text.Encoding.UTF8); + get => this._data[4]; + set => this._data[4] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the y. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator CharacterFocusedRef(Span packet) => new (packet, false); + public byte Y + { + get => this._data[5]; + set => this._data[5] = value; + } /// - /// Performs an implicit conversion from to a Span of bytes. + /// Gets or sets the map id. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Span(CharacterFocusedRef packet) => packet._data; -} + public ushort MapId + { + get => ReadUInt16LittleEndian(this._data[6..]); + set => WriteUInt16LittleEndian(this._data[6..], value); + } + /// + /// Gets or sets the current experience. + /// + public ulong CurrentExperience + { + get => ReadUInt64BigEndian(this._data[8..]); + set => WriteUInt64BigEndian(this._data[8..], value); + } -/// -/// Is sent by the server when: After the server processed a character stat increase request packet. -/// Causes reaction on client side: If it was successful, adds a point to the requested stat type. -/// -public readonly ref struct CharacterStatIncreaseResponseRef -{ - private readonly Span _data; + /// + /// Gets or sets the experience for next level. + /// + public ulong ExperienceForNextLevel + { + get => ReadUInt64BigEndian(this._data[16..]); + set => WriteUInt64BigEndian(this._data[16..], value); + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the level up points. /// - /// The underlying data. - public CharacterStatIncreaseResponseRef(Span data) - : this(data, true) + public ushort LevelUpPoints { + get => ReadUInt16LittleEndian(this._data[24..]); + set => WriteUInt16LittleEndian(this._data[24..], value); } /// - /// Initializes a new instance of the struct. + /// Gets or sets the strength. /// - /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterStatIncreaseResponseRef(Span data, bool initialize) + public ushort Strength { - this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; - } + get => ReadUInt16LittleEndian(this._data[26..]); + set => WriteUInt16LittleEndian(this._data[26..], value); } /// - /// Gets the header type of this data packet. + /// Gets or sets the agility. /// - public static byte HeaderType => 0xC1; + public ushort Agility + { + get => ReadUInt16LittleEndian(this._data[28..]); + set => WriteUInt16LittleEndian(this._data[28..], value); + } /// - /// Gets the operation code of this data packet. + /// Gets or sets the vitality. /// - public static byte Code => 0xF3; + public ushort Vitality + { + get => ReadUInt16LittleEndian(this._data[30..]); + set => WriteUInt16LittleEndian(this._data[30..], value); + } /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets or sets the energy. /// - public static byte SubCode => 0x06; + public ushort Energy + { + get => ReadUInt16LittleEndian(this._data[32..]); + set => WriteUInt16LittleEndian(this._data[32..], value); + } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the current health. /// - public static int Length => 12; + public ushort CurrentHealth + { + get => ReadUInt16LittleEndian(this._data[34..]); + set => WriteUInt16LittleEndian(this._data[34..], value); + } /// - /// Gets the header of this packet. + /// Gets or sets the maximum health. /// - public C1HeaderWithSubCodeRef Header => new (this._data); + public ushort MaximumHealth + { + get => ReadUInt16LittleEndian(this._data[36..]); + set => WriteUInt16LittleEndian(this._data[36..], value); + } /// - /// Gets or sets the success. + /// Gets or sets the current mana. /// - public bool Success + public ushort CurrentMana { - get => this._data[4..].GetBoolean(4); - set => this._data[4..].SetBoolean(value, 4); + get => ReadUInt16LittleEndian(this._data[38..]); + set => WriteUInt16LittleEndian(this._data[38..], value); } /// - /// Gets or sets the attribute. + /// Gets or sets the maximum mana. /// - public CharacterStatAttribute Attribute + public ushort MaximumMana { - get => (CharacterStatAttribute)this._data[4..].GetByteValue(4, 0); - set => this._data[4..].SetByteValue((byte)value, 4, 0); + get => ReadUInt16LittleEndian(this._data[40..]); + set => WriteUInt16LittleEndian(this._data[40..], value); } /// - /// Gets or sets the updated dependent maximum stat. + /// Gets or sets the current shield. /// - public ushort UpdatedDependentMaximumStat + public ushort CurrentShield { - get => ReadUInt16LittleEndian(this._data[6..]); - set => WriteUInt16LittleEndian(this._data[6..], value); + get => ReadUInt16LittleEndian(this._data[42..]); + set => WriteUInt16LittleEndian(this._data[42..], value); } /// - /// Gets or sets the updated maximum shield. + /// Gets or sets the maximum shield. /// - public ushort UpdatedMaximumShield + public ushort MaximumShield { - get => ReadUInt16LittleEndian(this._data[8..]); - set => WriteUInt16LittleEndian(this._data[8..], value); + get => ReadUInt16LittleEndian(this._data[44..]); + set => WriteUInt16LittleEndian(this._data[44..], value); } /// - /// Gets or sets the updated maximum ability. + /// Gets or sets the current ability. /// - public ushort UpdatedMaximumAbility + public ushort CurrentAbility { - get => ReadUInt16LittleEndian(this._data[10..]); - set => WriteUInt16LittleEndian(this._data[10..], value); + get => ReadUInt16LittleEndian(this._data[46..]); + set => WriteUInt16LittleEndian(this._data[46..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the maximum ability. /// - /// The packet as span. - /// The packet as struct. - public static implicit operator CharacterStatIncreaseResponseRef(Span packet) => new (packet, false); + public ushort MaximumAbility + { + get => ReadUInt16LittleEndian(this._data[48..]); + set => WriteUInt16LittleEndian(this._data[48..], value); + } /// - /// Performs an implicit conversion from to a Span of bytes. + /// Gets or sets the money. /// - /// The packet as struct. - /// The packet as byte span. - public static implicit operator Span(CharacterStatIncreaseResponseRef packet) => packet._data; -} - - -/// -/// Is sent by the server when: After the server processed a character delete response of the client. -/// Causes reaction on client side: If successful, the character is deleted from the character selection screen. Otherwise, a message is shown. -/// -public readonly ref struct CharacterDeleteResponseRef -{ - private readonly Span _data; + public uint Money + { + get => ReadUInt32LittleEndian(this._data[52..]); + set => WriteUInt32LittleEndian(this._data[52..], value); + } /// - /// Initializes a new instance of the struct. + /// Gets or sets the hero state. /// - /// The underlying data. - public CharacterDeleteResponseRef(Span data) - : this(data, true) + public CharacterHeroState HeroState { + get => (CharacterHeroState)this._data[56]; + set => this._data[56] = (byte)value; } /// - /// Initializes a new instance of the struct. + /// Gets or sets the status. /// - /// The underlying data. - /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterDeleteResponseRef(Span data, bool initialize) + public CharacterStatus Status { - this._data = data; - if (initialize) - { - var header = this.Header; - header.Type = HeaderType; - header.Code = Code; - header.Length = (byte)Math.Min(data.Length, Length); - header.SubCode = SubCode; - } + get => (CharacterStatus)this._data[57]; + set => this._data[57] = (byte)value; } /// - /// Gets the header type of this data packet. + /// Gets or sets the used fruit points. /// - public static byte HeaderType => 0xC1; + public ushort UsedFruitPoints + { + get => ReadUInt16LittleEndian(this._data[58..]); + set => WriteUInt16LittleEndian(this._data[58..], value); + } /// - /// Gets the operation code of this data packet. + /// Gets or sets the max fruit points. /// - public static byte Code => 0xF3; + public ushort MaxFruitPoints + { + get => ReadUInt16LittleEndian(this._data[60..]); + set => WriteUInt16LittleEndian(this._data[60..], value); + } /// - /// Gets the operation sub-code of this data packet. - /// The is used as a grouping key. + /// Gets or sets the leadership. /// - public static byte SubCode => 0x02; + public ushort Leadership + { + get => ReadUInt16LittleEndian(this._data[62..]); + set => WriteUInt16LittleEndian(this._data[62..], value); + } /// - /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// Gets or sets the used negative fruit points. /// - public static int Length => 5; + public ushort UsedNegativeFruitPoints + { + get => ReadUInt16LittleEndian(this._data[64..]); + set => WriteUInt16LittleEndian(this._data[64..], value); + } /// - /// Gets the header of this packet. + /// Gets or sets the max negative fruit points. /// - public C1HeaderWithSubCodeRef Header => new (this._data); + public ushort MaxNegativeFruitPoints + { + get => ReadUInt16LittleEndian(this._data[66..]); + set => WriteUInt16LittleEndian(this._data[66..], value); + } /// - /// Gets or sets the result. + /// Gets or sets the inventory extensions. /// - public CharacterDeleteResponse.CharacterDeleteResult Result + public byte InventoryExtensions { - get => (CharacterDeleteResponse.CharacterDeleteResult)this._data[4]; - set => this._data[4] = (byte)value; + get => this._data[68]; + set => this._data[68] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterDeleteResponseRef(Span packet) => new (packet, false); + public static implicit operator CharacterInformationRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterDeleteResponseRef packet) => packet._data; + public static implicit operator Span(CharacterInformationRef packet) => packet._data; } @@ -13022,25 +14354,25 @@ public CharacterDeleteResponse.CharacterDeleteResult Result /// Is sent by the server when: After a character leveled up. /// Causes reaction on client side: Updates the level (and other related stats) in the game client and shows an effect. /// -public readonly ref struct CharacterLevelUpdateRef +public readonly ref struct CharacterLevelUpdateExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterLevelUpdateRef(Span data) + public CharacterLevelUpdateExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterLevelUpdateRef(Span data, bool initialize) + private CharacterLevelUpdateExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -13072,7 +14404,7 @@ private CharacterLevelUpdateRef(Span data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 24; + public static int Length => 32; /// /// Gets the header of this packet. @@ -13100,37 +14432,37 @@ public ushort LevelUpPoints /// /// Gets or sets the maximum health. /// - public ushort MaximumHealth + public uint MaximumHealth { - get => ReadUInt16LittleEndian(this._data[8..]); - set => WriteUInt16LittleEndian(this._data[8..], value); + get => ReadUInt32LittleEndian(this._data[8..]); + set => WriteUInt32LittleEndian(this._data[8..], value); } /// /// Gets or sets the maximum mana. /// - public ushort MaximumMana + public uint MaximumMana { - get => ReadUInt16LittleEndian(this._data[10..]); - set => WriteUInt16LittleEndian(this._data[10..], value); + get => ReadUInt32LittleEndian(this._data[12..]); + set => WriteUInt32LittleEndian(this._data[12..], value); } /// /// Gets or sets the maximum shield. /// - public ushort MaximumShield + public uint MaximumShield { - get => ReadUInt16LittleEndian(this._data[12..]); - set => WriteUInt16LittleEndian(this._data[12..], value); + get => ReadUInt32LittleEndian(this._data[16..]); + set => WriteUInt32LittleEndian(this._data[16..], value); } /// /// Gets or sets the maximum ability. /// - public ushort MaximumAbility + public uint MaximumAbility { - get => ReadUInt16LittleEndian(this._data[14..]); - set => WriteUInt16LittleEndian(this._data[14..], value); + get => ReadUInt32LittleEndian(this._data[20..]); + set => WriteUInt32LittleEndian(this._data[20..], value); } /// @@ -13138,8 +14470,8 @@ public ushort MaximumAbility /// public ushort FruitPoints { - get => ReadUInt16LittleEndian(this._data[16..]); - set => WriteUInt16LittleEndian(this._data[16..], value); + get => ReadUInt16LittleEndian(this._data[24..]); + set => WriteUInt16LittleEndian(this._data[24..], value); } /// @@ -13147,8 +14479,8 @@ public ushort FruitPoints /// public ushort MaximumFruitPoints { - get => ReadUInt16LittleEndian(this._data[18..]); - set => WriteUInt16LittleEndian(this._data[18..], value); + get => ReadUInt16LittleEndian(this._data[26..]); + set => WriteUInt16LittleEndian(this._data[26..], value); } /// @@ -13156,8 +14488,8 @@ public ushort MaximumFruitPoints /// public ushort NegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data[20..]); - set => WriteUInt16LittleEndian(this._data[20..], value); + get => ReadUInt16LittleEndian(this._data[28..]); + set => WriteUInt16LittleEndian(this._data[28..], value); } /// @@ -13165,23 +14497,23 @@ public ushort NegativeFruitPoints /// public ushort MaximumNegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data[22..]); - set => WriteUInt16LittleEndian(this._data[22..], value); + get => ReadUInt16LittleEndian(this._data[30..]); + set => WriteUInt16LittleEndian(this._data[30..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterLevelUpdateRef(Span packet) => new (packet, false); + public static implicit operator CharacterLevelUpdateExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterLevelUpdateRef packet) => packet._data; + public static implicit operator Span(CharacterLevelUpdateExtendedRef packet) => packet._data; } @@ -13189,25 +14521,25 @@ public ushort MaximumNegativeFruitPoints /// Is sent by the server when: After the character was selected by the player and entered the game. /// Causes reaction on client side: The characters enters the game world. /// -public readonly ref struct CharacterInformationRef +public readonly ref struct CharacterInformationExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public CharacterInformationRef(Span data) + public CharacterInformationExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private CharacterInformationRef(Span data, bool initialize) + private CharacterInformationExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -13239,7 +14571,7 @@ private CharacterInformationRef(Span data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 72; + public static int Length => 84; /// /// Gets the header of this packet. @@ -13337,75 +14669,84 @@ public ushort Energy } /// - /// Gets or sets the current health. + /// Gets or sets the leadership. /// - public ushort CurrentHealth + public ushort Leadership { get => ReadUInt16LittleEndian(this._data[34..]); set => WriteUInt16LittleEndian(this._data[34..], value); } + /// + /// Gets or sets the current health. + /// + public uint CurrentHealth + { + get => ReadUInt32LittleEndian(this._data[36..]); + set => WriteUInt32LittleEndian(this._data[36..], value); + } + /// /// Gets or sets the maximum health. /// - public ushort MaximumHealth + public uint MaximumHealth { - get => ReadUInt16LittleEndian(this._data[36..]); - set => WriteUInt16LittleEndian(this._data[36..], value); + get => ReadUInt32LittleEndian(this._data[40..]); + set => WriteUInt32LittleEndian(this._data[40..], value); } /// /// Gets or sets the current mana. /// - public ushort CurrentMana + public uint CurrentMana { - get => ReadUInt16LittleEndian(this._data[38..]); - set => WriteUInt16LittleEndian(this._data[38..], value); + get => ReadUInt32LittleEndian(this._data[44..]); + set => WriteUInt32LittleEndian(this._data[44..], value); } /// /// Gets or sets the maximum mana. /// - public ushort MaximumMana + public uint MaximumMana { - get => ReadUInt16LittleEndian(this._data[40..]); - set => WriteUInt16LittleEndian(this._data[40..], value); + get => ReadUInt32LittleEndian(this._data[48..]); + set => WriteUInt32LittleEndian(this._data[48..], value); } /// /// Gets or sets the current shield. /// - public ushort CurrentShield + public uint CurrentShield { - get => ReadUInt16LittleEndian(this._data[42..]); - set => WriteUInt16LittleEndian(this._data[42..], value); + get => ReadUInt32LittleEndian(this._data[52..]); + set => WriteUInt32LittleEndian(this._data[52..], value); } /// /// Gets or sets the maximum shield. /// - public ushort MaximumShield + public uint MaximumShield { - get => ReadUInt16LittleEndian(this._data[44..]); - set => WriteUInt16LittleEndian(this._data[44..], value); + get => ReadUInt32LittleEndian(this._data[56..]); + set => WriteUInt32LittleEndian(this._data[56..], value); } /// /// Gets or sets the current ability. /// - public ushort CurrentAbility + public uint CurrentAbility { - get => ReadUInt16LittleEndian(this._data[46..]); - set => WriteUInt16LittleEndian(this._data[46..], value); + get => ReadUInt32LittleEndian(this._data[60..]); + set => WriteUInt32LittleEndian(this._data[60..], value); } /// /// Gets or sets the maximum ability. /// - public ushort MaximumAbility + public uint MaximumAbility { - get => ReadUInt16LittleEndian(this._data[48..]); - set => WriteUInt16LittleEndian(this._data[48..], value); + get => ReadUInt32LittleEndian(this._data[64..]); + set => WriteUInt32LittleEndian(this._data[64..], value); } /// @@ -13413,8 +14754,8 @@ public ushort MaximumAbility /// public uint Money { - get => ReadUInt32LittleEndian(this._data[52..]); - set => WriteUInt32LittleEndian(this._data[52..], value); + get => ReadUInt32LittleEndian(this._data[68..]); + set => WriteUInt32LittleEndian(this._data[68..], value); } /// @@ -13422,8 +14763,8 @@ public uint Money /// public CharacterHeroState HeroState { - get => (CharacterHeroState)this._data[56]; - set => this._data[56] = (byte)value; + get => (CharacterHeroState)this._data[72]; + set => this._data[72] = (byte)value; } /// @@ -13431,8 +14772,8 @@ public CharacterHeroState HeroState /// public CharacterStatus Status { - get => (CharacterStatus)this._data[57]; - set => this._data[57] = (byte)value; + get => (CharacterStatus)this._data[73]; + set => this._data[73] = (byte)value; } /// @@ -13440,8 +14781,8 @@ public CharacterStatus Status /// public ushort UsedFruitPoints { - get => ReadUInt16LittleEndian(this._data[58..]); - set => WriteUInt16LittleEndian(this._data[58..], value); + get => ReadUInt16LittleEndian(this._data[74..]); + set => WriteUInt16LittleEndian(this._data[74..], value); } /// @@ -13449,17 +14790,8 @@ public ushort UsedFruitPoints /// public ushort MaxFruitPoints { - get => ReadUInt16LittleEndian(this._data[60..]); - set => WriteUInt16LittleEndian(this._data[60..], value); - } - - /// - /// Gets or sets the leadership. - /// - public ushort Leadership - { - get => ReadUInt16LittleEndian(this._data[62..]); - set => WriteUInt16LittleEndian(this._data[62..], value); + get => ReadUInt16LittleEndian(this._data[76..]); + set => WriteUInt16LittleEndian(this._data[76..], value); } /// @@ -13467,8 +14799,8 @@ public ushort Leadership /// public ushort UsedNegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data[64..]); - set => WriteUInt16LittleEndian(this._data[64..], value); + get => ReadUInt16LittleEndian(this._data[78..]); + set => WriteUInt16LittleEndian(this._data[78..], value); } /// @@ -13476,8 +14808,8 @@ public ushort UsedNegativeFruitPoints /// public ushort MaxNegativeFruitPoints { - get => ReadUInt16LittleEndian(this._data[66..]); - set => WriteUInt16LittleEndian(this._data[66..], value); + get => ReadUInt16LittleEndian(this._data[80..]); + set => WriteUInt16LittleEndian(this._data[80..], value); } /// @@ -13485,23 +14817,23 @@ public ushort MaxNegativeFruitPoints /// public byte InventoryExtensions { - get => this._data[68]; - set => this._data[68] = value; + get => this._data[81]; + set => this._data[81] = value; } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator CharacterInformationRef(Span packet) => new (packet, false); + public static implicit operator CharacterInformationExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(CharacterInformationRef packet) => packet._data; + public static implicit operator Span(CharacterInformationExtendedRef packet) => packet._data; } @@ -14840,7 +16172,207 @@ private PlayFanfareSoundRef(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.EffectType = 2; + this.EffectType = 2; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x40; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 7; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the effect type. + /// + public byte EffectType + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Gets or sets the x. + /// + public byte X + { + get => this._data[5]; + set => this._data[5] = value; + } + + /// + /// Gets or sets the y. + /// + public byte Y + { + get => this._data[6]; + set => this._data[6] = value; + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator PlayFanfareSoundRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(PlayFanfareSoundRef packet) => packet._data; +} + + +/// +/// Is sent by the server when: E.g. when event items are dropped to the floor. +/// Causes reaction on client side: The client shows a swirl effect at the specified object. +/// +public readonly ref struct ShowSwirlRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public ShowSwirlRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private ShowSwirlRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; + this.EffectType = 58; + } + } + + /// + /// Gets the header type of this data packet. + /// + public static byte HeaderType => 0xC1; + + /// + /// Gets the operation code of this data packet. + /// + public static byte Code => 0xF3; + + /// + /// Gets the operation sub-code of this data packet. + /// The is used as a grouping key. + /// + public static byte SubCode => 0x40; + + /// + /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. + /// + public static int Length => 7; + + /// + /// Gets the header of this packet. + /// + public C1HeaderWithSubCodeRef Header => new (this._data); + + /// + /// Gets or sets the effect type. + /// + public byte EffectType + { + get => this._data[4]; + set => this._data[4] = value; + } + + /// + /// Gets or sets the target object id. + /// + public ushort TargetObjectId + { + get => ReadUInt16BigEndian(this._data[5..]); + set => WriteUInt16BigEndian(this._data[5..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . + /// + /// The packet as span. + /// The packet as struct. + public static implicit operator ShowSwirlRef(Span packet) => new (packet, false); + + /// + /// Performs an implicit conversion from to a Span of bytes. + /// + /// The packet as struct. + /// The packet as byte span. + public static implicit operator Span(ShowSwirlRef packet) => packet._data; +} + + +/// +/// Is sent by the server when: After entering the game with a master class character. +/// Causes reaction on client side: The master related data is available. +/// +public readonly ref struct MasterStatsUpdateRef +{ + private readonly Span _data; + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + public MasterStatsUpdateRef(Span data) + : this(data, true) + { + } + + /// + /// Initializes a new instance of the struct. + /// + /// The underlying data. + /// If set to true, the header data is automatically initialized and written to the underlying span. + private MasterStatsUpdateRef(Span data, bool initialize) + { + this._data = data; + if (initialize) + { + var header = this.Header; + header.Type = HeaderType; + header.Code = Code; + header.Length = (byte)Math.Min(data.Length, Length); + header.SubCode = SubCode; } } @@ -14858,12 +16390,12 @@ private PlayFanfareSoundRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x40; + public static byte SubCode => 0x50; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 7; + public static int Length => 32; /// /// Gets the header of this packet. @@ -14871,71 +16403,116 @@ private PlayFanfareSoundRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the effect type. + /// Gets or sets the master level. /// - public byte EffectType + public ushort MasterLevel { - get => this._data[4]; - set => this._data[4] = value; + get => ReadUInt16LittleEndian(this._data[4..]); + set => WriteUInt16LittleEndian(this._data[4..], value); } /// - /// Gets or sets the x. + /// Gets or sets the master experience. /// - public byte X + public ulong MasterExperience { - get => this._data[5]; - set => this._data[5] = value; + get => ReadUInt64BigEndian(this._data[6..]); + set => WriteUInt64BigEndian(this._data[6..], value); } /// - /// Gets or sets the y. + /// Gets or sets the master experience of next level. /// - public byte Y + public ulong MasterExperienceOfNextLevel { - get => this._data[6]; - set => this._data[6] = value; + get => ReadUInt64BigEndian(this._data[14..]); + set => WriteUInt64BigEndian(this._data[14..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the master level up points. + /// + public ushort MasterLevelUpPoints + { + get => ReadUInt16LittleEndian(this._data[22..]); + set => WriteUInt16LittleEndian(this._data[22..], value); + } + + /// + /// Gets or sets the maximum health. + /// + public ushort MaximumHealth + { + get => ReadUInt16LittleEndian(this._data[24..]); + set => WriteUInt16LittleEndian(this._data[24..], value); + } + + /// + /// Gets or sets the maximum mana. + /// + public ushort MaximumMana + { + get => ReadUInt16LittleEndian(this._data[26..]); + set => WriteUInt16LittleEndian(this._data[26..], value); + } + + /// + /// Gets or sets the maximum shield. + /// + public ushort MaximumShield + { + get => ReadUInt16LittleEndian(this._data[28..]); + set => WriteUInt16LittleEndian(this._data[28..], value); + } + + /// + /// Gets or sets the maximum ability. + /// + public ushort MaximumAbility + { + get => ReadUInt16LittleEndian(this._data[30..]); + set => WriteUInt16LittleEndian(this._data[30..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator PlayFanfareSoundRef(Span packet) => new (packet, false); + public static implicit operator MasterStatsUpdateRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(PlayFanfareSoundRef packet) => packet._data; + public static implicit operator Span(MasterStatsUpdateRef packet) => packet._data; } /// -/// Is sent by the server when: E.g. when event items are dropped to the floor. -/// Causes reaction on client side: The client shows a swirl effect at the specified object. +/// Is sent by the server when: After entering the game with a master class character. +/// Causes reaction on client side: The master related data is available. /// -public readonly ref struct ShowSwirlRef +public readonly ref struct MasterStatsUpdateExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public ShowSwirlRef(Span data) + public MasterStatsUpdateExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private ShowSwirlRef(Span data, bool initialize) + private MasterStatsUpdateExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -14945,7 +16522,6 @@ private ShowSwirlRef(Span data, bool initialize) header.Code = Code; header.Length = (byte)Math.Min(data.Length, Length); header.SubCode = SubCode; - this.EffectType = 58; } } @@ -14963,12 +16539,12 @@ private ShowSwirlRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x40; + public static byte SubCode => 0x50; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 7; + public static int Length => 40; /// /// Gets the header of this packet. @@ -14976,62 +16552,116 @@ private ShowSwirlRef(Span data, bool initialize) public C1HeaderWithSubCodeRef Header => new (this._data); /// - /// Gets or sets the effect type. + /// Gets or sets the master level. /// - public byte EffectType + public ushort MasterLevel { - get => this._data[4]; - set => this._data[4] = value; + get => ReadUInt16LittleEndian(this._data[4..]); + set => WriteUInt16LittleEndian(this._data[4..], value); } /// - /// Gets or sets the target object id. + /// Gets or sets the master experience. /// - public ushort TargetObjectId + public ulong MasterExperience { - get => ReadUInt16BigEndian(this._data[5..]); - set => WriteUInt16BigEndian(this._data[5..], value); + get => ReadUInt64BigEndian(this._data[6..]); + set => WriteUInt64BigEndian(this._data[6..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Gets or sets the master experience of next level. + /// + public ulong MasterExperienceOfNextLevel + { + get => ReadUInt64BigEndian(this._data[14..]); + set => WriteUInt64BigEndian(this._data[14..], value); + } + + /// + /// Gets or sets the master level up points. + /// + public ushort MasterLevelUpPoints + { + get => ReadUInt16LittleEndian(this._data[22..]); + set => WriteUInt16LittleEndian(this._data[22..], value); + } + + /// + /// Gets or sets the maximum health. + /// + public uint MaximumHealth + { + get => ReadUInt32LittleEndian(this._data[24..]); + set => WriteUInt32LittleEndian(this._data[24..], value); + } + + /// + /// Gets or sets the maximum mana. + /// + public uint MaximumMana + { + get => ReadUInt32LittleEndian(this._data[28..]); + set => WriteUInt32LittleEndian(this._data[28..], value); + } + + /// + /// Gets or sets the maximum shield. + /// + public uint MaximumShield + { + get => ReadUInt32LittleEndian(this._data[32..]); + set => WriteUInt32LittleEndian(this._data[32..], value); + } + + /// + /// Gets or sets the maximum ability. + /// + public uint MaximumAbility + { + get => ReadUInt32LittleEndian(this._data[36..]); + set => WriteUInt32LittleEndian(this._data[36..], value); + } + + /// + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator ShowSwirlRef(Span packet) => new (packet, false); + public static implicit operator MasterStatsUpdateExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(ShowSwirlRef packet) => packet._data; + public static implicit operator Span(MasterStatsUpdateExtendedRef packet) => packet._data; } /// -/// Is sent by the server when: After entering the game with a master class character. -/// Causes reaction on client side: The master related data is available. +/// Is sent by the server when: After a master character leveled up. +/// Causes reaction on client side: Updates the master level (and other related stats) in the game client and shows an effect. /// -public readonly ref struct MasterStatsUpdateRef +public readonly ref struct MasterCharacterLevelUpdateRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MasterStatsUpdateRef(Span data) + public MasterCharacterLevelUpdateRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MasterStatsUpdateRef(Span data, bool initialize) + private MasterCharacterLevelUpdateRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -15058,12 +16688,12 @@ private MasterStatsUpdateRef(Span data, bool initialize) /// Gets the operation sub-code of this data packet. /// The is used as a grouping key. /// - public static byte SubCode => 0x50; + public static byte SubCode => 0x51; /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 32; + public static int Length => 20; /// /// Gets the header of this packet. @@ -15080,30 +16710,30 @@ public ushort MasterLevel } /// - /// Gets or sets the master experience. + /// Gets or sets the gained master points. /// - public ulong MasterExperience + public ushort GainedMasterPoints { - get => ReadUInt64BigEndian(this._data[6..]); - set => WriteUInt64BigEndian(this._data[6..], value); + get => ReadUInt16LittleEndian(this._data[6..]); + set => WriteUInt16LittleEndian(this._data[6..], value); } /// - /// Gets or sets the master experience of next level. + /// Gets or sets the current master points. /// - public ulong MasterExperienceOfNextLevel + public ushort CurrentMasterPoints { - get => ReadUInt64BigEndian(this._data[14..]); - set => WriteUInt64BigEndian(this._data[14..], value); + get => ReadUInt16LittleEndian(this._data[8..]); + set => WriteUInt16LittleEndian(this._data[8..], value); } /// - /// Gets or sets the master level up points. + /// Gets or sets the maximum master points. /// - public ushort MasterLevelUpPoints + public ushort MaximumMasterPoints { - get => ReadUInt16LittleEndian(this._data[22..]); - set => WriteUInt16LittleEndian(this._data[22..], value); + get => ReadUInt16LittleEndian(this._data[10..]); + set => WriteUInt16LittleEndian(this._data[10..], value); } /// @@ -15111,8 +16741,8 @@ public ushort MasterLevelUpPoints /// public ushort MaximumHealth { - get => ReadUInt16LittleEndian(this._data[24..]); - set => WriteUInt16LittleEndian(this._data[24..], value); + get => ReadUInt16LittleEndian(this._data[12..]); + set => WriteUInt16LittleEndian(this._data[12..], value); } /// @@ -15120,8 +16750,8 @@ public ushort MaximumHealth /// public ushort MaximumMana { - get => ReadUInt16LittleEndian(this._data[26..]); - set => WriteUInt16LittleEndian(this._data[26..], value); + get => ReadUInt16LittleEndian(this._data[14..]); + set => WriteUInt16LittleEndian(this._data[14..], value); } /// @@ -15129,8 +16759,8 @@ public ushort MaximumMana /// public ushort MaximumShield { - get => ReadUInt16LittleEndian(this._data[28..]); - set => WriteUInt16LittleEndian(this._data[28..], value); + get => ReadUInt16LittleEndian(this._data[16..]); + set => WriteUInt16LittleEndian(this._data[16..], value); } /// @@ -15138,23 +16768,23 @@ public ushort MaximumShield /// public ushort MaximumAbility { - get => ReadUInt16LittleEndian(this._data[30..]); - set => WriteUInt16LittleEndian(this._data[30..], value); + get => ReadUInt16LittleEndian(this._data[18..]); + set => WriteUInt16LittleEndian(this._data[18..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MasterStatsUpdateRef(Span packet) => new (packet, false); + public static implicit operator MasterCharacterLevelUpdateRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(MasterStatsUpdateRef packet) => packet._data; + public static implicit operator Span(MasterCharacterLevelUpdateRef packet) => packet._data; } @@ -15162,25 +16792,25 @@ public ushort MaximumAbility /// Is sent by the server when: After a master character leveled up. /// Causes reaction on client side: Updates the master level (and other related stats) in the game client and shows an effect. /// -public readonly ref struct MasterCharacterLevelUpdateRef +public readonly ref struct MasterCharacterLevelUpdateExtendedRef { private readonly Span _data; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. - public MasterCharacterLevelUpdateRef(Span data) + public MasterCharacterLevelUpdateExtendedRef(Span data) : this(data, true) { } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// The underlying data. /// If set to true, the header data is automatically initialized and written to the underlying span. - private MasterCharacterLevelUpdateRef(Span data, bool initialize) + private MasterCharacterLevelUpdateExtendedRef(Span data, bool initialize) { this._data = data; if (initialize) @@ -15212,7 +16842,7 @@ private MasterCharacterLevelUpdateRef(Span data, bool initialize) /// /// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed. /// - public static int Length => 20; + public static int Length => 28; /// /// Gets the header of this packet. @@ -15258,52 +16888,52 @@ public ushort MaximumMasterPoints /// /// Gets or sets the maximum health. /// - public ushort MaximumHealth + public uint MaximumHealth { - get => ReadUInt16LittleEndian(this._data[12..]); - set => WriteUInt16LittleEndian(this._data[12..], value); + get => ReadUInt32LittleEndian(this._data[12..]); + set => WriteUInt32LittleEndian(this._data[12..], value); } /// /// Gets or sets the maximum mana. /// - public ushort MaximumMana + public uint MaximumMana { - get => ReadUInt16LittleEndian(this._data[14..]); - set => WriteUInt16LittleEndian(this._data[14..], value); + get => ReadUInt32LittleEndian(this._data[16..]); + set => WriteUInt32LittleEndian(this._data[16..], value); } /// /// Gets or sets the maximum shield. /// - public ushort MaximumShield + public uint MaximumShield { - get => ReadUInt16LittleEndian(this._data[16..]); - set => WriteUInt16LittleEndian(this._data[16..], value); + get => ReadUInt32LittleEndian(this._data[20..]); + set => WriteUInt32LittleEndian(this._data[20..], value); } /// /// Gets or sets the maximum ability. /// - public ushort MaximumAbility + public uint MaximumAbility { - get => ReadUInt16LittleEndian(this._data[18..]); - set => WriteUInt16LittleEndian(this._data[18..], value); + get => ReadUInt32LittleEndian(this._data[24..]); + set => WriteUInt32LittleEndian(this._data[24..], value); } /// - /// Performs an implicit conversion from a Span of bytes to a . + /// Performs an implicit conversion from a Span of bytes to a . /// /// The packet as span. /// The packet as struct. - public static implicit operator MasterCharacterLevelUpdateRef(Span packet) => new (packet, false); + public static implicit operator MasterCharacterLevelUpdateExtendedRef(Span packet) => new (packet, false); /// - /// Performs an implicit conversion from to a Span of bytes. + /// Performs an implicit conversion from to a Span of bytes. /// /// The packet as struct. /// The packet as byte span. - public static implicit operator Span(MasterCharacterLevelUpdateRef packet) => packet._data; + public static implicit operator Span(MasterCharacterLevelUpdateExtendedRef packet) => packet._data; } diff --git a/src/Network/PlugIns/OpenSourceClientNetworkEncryptionFactoryPlugIn.cs b/src/Network/PlugIns/OpenSourceClientNetworkEncryptionFactoryPlugIn.cs new file mode 100644 index 000000000..37194b8cb --- /dev/null +++ b/src/Network/PlugIns/OpenSourceClientNetworkEncryptionFactoryPlugIn.cs @@ -0,0 +1,45 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Network.PlugIns; + +using System.IO.Pipelines; +using System.Runtime.InteropServices; +using MUnique.OpenMU.Network; +using MUnique.OpenMU.Network.SimpleModulus; +using MUnique.OpenMU.Network.Xor; +using MUnique.OpenMU.PlugIns; + +/// +/// A plugin which provides network encryptors and decryptors for the english open source game clients of season 6 episode 3, version 2.04d +/// +[PlugIn("Network Encryption - Season 6 Episode 3, Open Source Client", "A plugin which provides network encryptors and decryptors for the english open source game clients of season 6 episode 3, version 2.04d")] +[Guid("AB9EBD28-7A45-4FBA-A282-E2120E70FF17")] +public class OpenSourceClientNetworkEncryptionFactoryPlugIn : INetworkEncryptionFactoryPlugIn +{ + /// + public ClientVersion Key { get; } = new (106, 3, ClientLanguage.English); + + /// + public IPipelinedEncryptor CreateEncryptor(PipeWriter target, DataDirection direction) + { + if (direction == DataDirection.ServerToClient) + { + return new PipelinedEncryptor(target); + } + + return new PipelinedXor32Encryptor(new PipelinedSimpleModulusEncryptor(target, PipelinedSimpleModulusEncryptor.DefaultClientKey).Writer); + } + + /// + public IPipelinedDecryptor CreateDecryptor(PipeReader source, DataDirection direction) + { + if (direction == DataDirection.ClientToServer) + { + return new PipelinedDecryptor(source); + } + + return new PipelinedSimpleModulusDecryptor(source, PipelinedSimpleModulusDecryptor.DefaultClientKey); + } +} \ No newline at end of file