Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ The kind of result.
| 6 | NameMismatchOrPriceMissing | The requested player with the specified id has a different name or price is missing. |
| 7 | LackOfMoney | The player has not enough money to buy the item from the seller. |
| 8 | MoneyOverflowOrNotEnoughSpace | The selling player cannot sell the item, because the sale would overflow his money amount in the inventory. Another possibility is that the inventory of the buyer cannot take the item. |
| 9 | ItemBlock | The requested player has item block active. |
| 9 | ItemBlock | The requested player has item block active. |
| 10 | LackOfPriceCurrency | The player has not enough of the currency (jewels or account coins) in which the price of the item is defined. |
30 changes: 30 additions & 0 deletions docs/Packets/C1-3F-0A-PlayerShopPriceTypesExtended_by-server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# C1 3F 0A - PlayerShopPriceTypesExtended (by server)

## Is sent when

After entering the game world, and before the player shop of another player is shown, when the server allows prices in player shops which are not paid in zen.

## Causes the following actions on the client side

The client offers the allowed price types, in addition to zen, when the player sets an item price in his player shop. Without this message, only zen prices are possible.

## Structure

| Index | Length | Data Type | Value | Description |
|-------|--------|-----------|-------|-------------|
| 0 | 1 | Byte | 0xC1 | [Packet type](PacketTypes.md) |
| 1 | 1 | Byte | | Packet header - length of the packet |
| 2 | 1 | Byte | 0x3F | Packet header - packet type identifier |
| 3 | 1 | Byte | 0x0A | Packet header - sub packet type identifier |
| 4 | 1 | Byte | | Count |
| 5 | PlayerShopPriceType.Length * Count | Array of PlayerShopPriceType | | PriceTypes |

### PlayerShopPriceType Structure

A price type which is allowed for prices in player shops, in addition to zen.

Length: 2 Bytes

| Index | Length | Data Type | Value | Description |
|-------|--------|-----------|-------|-------------|
| 0 | 2 | ShortLittleEndian | | PriceItemType; The value of PriceItemType of a price of this type, like in PlayerShopItemExtended: the item (group in the highest 4 bits, number in the remaining ones) with which the price is paid, or 0xFFF0 = WCoin (C), 0xFFF1 = WCoin (P), 0xFFF2 = Goblin Points. |
6 changes: 3 additions & 3 deletions docs/Packets/C2-3F-05-PlayerShopItemListExtended_by-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ Data of an item in a player shop, which allows for dynamic item sizes and trades

| Index | Length | Data Type | Value | Description |
|-------|--------|-----------|-------|-------------|
| 0 | 4 | IntegerLittleEndian | | MoneyPrice |
| 4 | 2 | ShortLittleEndian | | PriceItemType; Contains the item group in the highest 4 bits, and the item number in the remaining ones. |
| 6 | 2 | ShortLittleEndian | | RequiredItemAmount |
| 0 | 4 | IntegerLittleEndian | | MoneyPrice; The price in zen, or in account coins when PriceItemType is one of the account coin values (see there). It's 0 when the price is defined in items. |
| 4 | 2 | ShortLittleEndian | | PriceItemType; When RequiredItemAmount is greater than 0, it contains the item group in the highest 4 bits, and the item number in the remaining ones, of the item (e.g. a jewel) which is required to buy the item. When RequiredItemAmount is 0, the following reserved values define an account coin as currency, with the amount in MoneyPrice: 0xFFF0 = WCoin (C), 0xFFF1 = WCoin (P), 0xFFF2 = Goblin Points. Any other value means that MoneyPrice is the price in zen. |
| 6 | 2 | ShortLittleEndian | | RequiredItemAmount; The number of pieces of the item which is defined by PriceItemType, which is required to buy the item. 0, if the price is not defined in items. |
| 8 | 1 | Byte | | ItemSlot |
| 9 | | Binary | | ItemData |

Expand Down
22 changes: 22 additions & 0 deletions docs/Packets/C3-3F-09-PlayerShopSetItemPriceExtended_by-client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# C3 3F 09 - PlayerShopSetItemPriceExtended (by client)

## Is sent when

The player wants to set a price of an item which is inside his personal item shop, in zen or in one of the price types which are allowed by the server (see PlayerShopPriceTypesExtended).

## Causes the following actions on the server side

The price is set for the specified item, if its price type is allowed and the amount is within the configured limits. Works only if the shop is currently closed. The server responds with a PlayerShopSetItemPriceResponse.

## Structure

| Index | Length | Data Type | Value | Description |
|-------|--------|-----------|-------|-------------|
| 0 | 1 | Byte | 0xC3 | [Packet type](PacketTypes.md) |
| 1 | 1 | Byte | 13 | Packet header - length of the packet |
| 2 | 1 | Byte | 0x3F | Packet header - packet type identifier |
| 3 | 1 | Byte | 0x09 | Packet header - sub packet type identifier |
| 4 | 4 | IntegerLittleEndian | | MoneyPrice; The price in zen, or in account coins when PriceItemType is one of the account coin values. Encoded like the price of PlayerShopItemExtended. |
| 8 | 2 | ShortLittleEndian | | PriceItemType; The item (group in the highest 4 bits, number in the remaining ones) with which the price is paid, when RequiredItemAmount is greater than 0. Otherwise, 0xFFF0 = WCoin (C), 0xFFF1 = WCoin (P) and 0xFFF2 = Goblin Points define an account coin price; any other value a zen price. Encoded like the price of PlayerShopItemExtended. |
| 10 | 2 | ShortLittleEndian | | RequiredItemAmount; The number of pieces of the item which is defined by PriceItemType; 0, if the price is not paid with items. Encoded like the price of PlayerShopItemExtended. |
| 12 | 1 | Byte | | ItemSlot |
1 change: 1 addition & 0 deletions docs/Packets/ClientToServer.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* [C3 3F 05 - PlayerShopItemListRequest (by client)](C3-3F-05-PlayerShopItemListRequest_by-client.md)
* [C3 3F 06 - PlayerShopItemBuyRequest (by client)](C3-3F-06-PlayerShopItemBuyRequest_by-client.md)
* [C3 3F 07 - PlayerShopCloseOther (by client)](C3-3F-07-PlayerShopCloseOther_by-client.md)
* [C3 3F 09 - PlayerShopSetItemPriceExtended (by client)](C3-3F-09-PlayerShopSetItemPriceExtended_by-client.md)
* [C1 40 - PartyInviteRequest (by client)](C1-40-PartyInviteRequest_by-client.md)
* [C1 41 - PartyInviteResponse (by client)](C1-41-PartyInviteResponse_by-client.md)
* [C1 42 - PartyListRequest (by client)](C1-42-PartyListRequest_by-client.md)
Expand Down
1 change: 1 addition & 0 deletions docs/Packets/ServerToClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
* [C1 3F 06 - PlayerShopBuyResult (by server)](C1-3F-06-PlayerShopBuyResult_by-server.md)
* [C1 3F 06 - PlayerShopBuyResultExtended (by server)](C1-3F-06-PlayerShopBuyResultExtended_by-server.md)
* [C1 3F 08 - PlayerShopItemSoldToPlayer (by server)](C1-3F-08-PlayerShopItemSoldToPlayer_by-server.md)
* [C1 3F 0A - PlayerShopPriceTypesExtended (by server)](C1-3F-0A-PlayerShopPriceTypesExtended_by-server.md)
* [C1 3F 12 - ClosePlayerShopDialog (by server)](C1-3F-12-ClosePlayerShopDialog_by-server.md)
* [C1 3F 2 - PlayerShopOpenSuccessful (by server)](C1-3F-2-PlayerShopOpenSuccessful_by-server.md)
* [C1 3F 3 - PlayerShopClosed (by server)](C1-3F-3-PlayerShopClosed_by-server.md)
Expand Down
113 changes: 113 additions & 0 deletions src/Network/Packets/ClientToServer/ClientToServerPackets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,119 @@ public string PlayerName
}


/// <summary>
/// Is sent by the client when: The player wants to set a price of an item which is inside his personal item shop, in zen or in one of the price types which are allowed by the server (see PlayerShopPriceTypesExtended).
/// Causes reaction on server side: The price is set for the specified item, if its price type is allowed and the amount is within the configured limits. Works only if the shop is currently closed. The server responds with a PlayerShopSetItemPriceResponse.
/// </summary>
public readonly struct PlayerShopSetItemPriceExtended
{
private readonly Memory<byte> _data;

/// <summary>
/// Initializes a new instance of the <see cref="PlayerShopSetItemPriceExtended"/> struct.
/// </summary>
/// <param name="data">The underlying data.</param>
public PlayerShopSetItemPriceExtended(Memory<byte> data)
: this(data, true)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="PlayerShopSetItemPriceExtended"/> struct.
/// </summary>
/// <param name="data">The underlying data.</param>
/// <param name="initialize">If set to <c>true</c>, the header data is automatically initialized and written to the underlying span.</param>
private PlayerShopSetItemPriceExtended(Memory<byte> 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;
}
}

/// <summary>
/// Gets the header type of this data packet.
/// </summary>
public static byte HeaderType => 0xC3;

/// <summary>
/// Gets the operation code of this data packet.
/// </summary>
public static byte Code => 0x3F;

/// <summary>
/// Gets the operation sub-code of this data packet.
/// The <see cref="Code" /> is used as a grouping key.
/// </summary>
public static byte SubCode => 0x09;

/// <summary>
/// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed.
/// </summary>
public static int Length => 13;

/// <summary>
/// Gets the header of this packet.
/// </summary>
public C3HeaderWithSubCode Header => new (this._data);

/// <summary>
/// Gets or sets the price in zen, or in account coins when PriceItemType is one of the account coin values. Encoded like the price of PlayerShopItemExtended.
/// </summary>
public uint MoneyPrice
{
get => ReadUInt32LittleEndian(this._data.Span[4..]);
set => WriteUInt32LittleEndian(this._data.Span[4..], value);
}

/// <summary>
/// Gets or sets the item (group in the highest 4 bits, number in the remaining ones) with which the price is paid, when RequiredItemAmount is greater than 0. Otherwise, 0xFFF0 = WCoin (C), 0xFFF1 = WCoin (P) and 0xFFF2 = Goblin Points define an account coin price; any other value a zen price. Encoded like the price of PlayerShopItemExtended.
/// </summary>
public ushort PriceItemType
{
get => ReadUInt16LittleEndian(this._data.Span[8..]);
set => WriteUInt16LittleEndian(this._data.Span[8..], value);
}

/// <summary>
/// Gets or sets the number of pieces of the item which is defined by PriceItemType; 0, if the price is not paid with items. Encoded like the price of PlayerShopItemExtended.
/// </summary>
public ushort RequiredItemAmount
{
get => ReadUInt16LittleEndian(this._data.Span[10..]);
set => WriteUInt16LittleEndian(this._data.Span[10..], value);
}

/// <summary>
/// Gets or sets the item slot.
/// </summary>
public byte ItemSlot
{
get => this._data.Span[12];
set => this._data.Span[12] = value;
}

/// <summary>
/// Performs an implicit conversion from a Memory of bytes to a <see cref="PlayerShopSetItemPriceExtended"/>.
/// </summary>
/// <param name="packet">The packet as span.</param>
/// <returns>The packet as struct.</returns>
public static implicit operator PlayerShopSetItemPriceExtended(Memory<byte> packet) => new (packet, false);

/// <summary>
/// Performs an implicit conversion from <see cref="PlayerShopSetItemPriceExtended"/> to a Memory of bytes.
/// </summary>
/// <param name="packet">The packet as struct.</param>
/// <returns>The packet as byte span.</returns>
public static implicit operator Memory<byte>(PlayerShopSetItemPriceExtended packet) => packet._data;
}


/// <summary>
/// Is sent by the client when: A player requests to pick up an item which is laying on the ground in the near of the players character.
/// Causes reaction on server side: If the player is allowed to pick the item up, and is the first player which tried that, it tries to add the item to the inventory. The server sends a response about the result of the request.
Expand Down
36 changes: 36 additions & 0 deletions src/Network/Packets/ClientToServer/ClientToServerPackets.xml
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,42 @@
</Field>
</Fields>
</Packet>
<Packet>
<HeaderType>C3HeaderWithSubCode</HeaderType>
<Code>3F</Code>
<SubCode>09</SubCode>
<Name>PlayerShopSetItemPriceExtended</Name>
<Caption>Player Shop - Set Item Price (extended)</Caption>
<Length>13</Length>
<Direction>ClientToServer</Direction>
<SentWhen>The player wants to set a price of an item which is inside his personal item shop, in zen or in one of the price types which are allowed by the server (see PlayerShopPriceTypesExtended).</SentWhen>
<CausedReaction>The price is set for the specified item, if its price type is allowed and the amount is within the configured limits. Works only if the shop is currently closed. The server responds with a PlayerShopSetItemPriceResponse.</CausedReaction>
<Fields>
<Field>
<Index>4</Index>
<Type>IntegerLittleEndian</Type>
<Name>MoneyPrice</Name>
<Description>The price in zen, or in account coins when PriceItemType is one of the account coin values. Encoded like the price of PlayerShopItemExtended.</Description>
</Field>
<Field>
<Index>8</Index>
<Type>ShortLittleEndian</Type>
<Name>PriceItemType</Name>
<Description>The item (group in the highest 4 bits, number in the remaining ones) with which the price is paid, when RequiredItemAmount is greater than 0. Otherwise, 0xFFF0 = WCoin (C), 0xFFF1 = WCoin (P) and 0xFFF2 = Goblin Points define an account coin price; any other value a zen price. Encoded like the price of PlayerShopItemExtended.</Description>
</Field>
<Field>
<Index>10</Index>
<Type>ShortLittleEndian</Type>
<Name>RequiredItemAmount</Name>
<Description>The number of pieces of the item which is defined by PriceItemType; 0, if the price is not paid with items. Encoded like the price of PlayerShopItemExtended.</Description>
</Field>
<Field>
<Index>12</Index>
<Type>Byte</Type>
<Name>ItemSlot</Name>
</Field>
</Fields>
</Packet>
<Packet>
<HeaderType>C3Header</HeaderType>
<Code>22</Code>
Expand Down
113 changes: 113 additions & 0 deletions src/Network/Packets/ClientToServer/ClientToServerPacketsRef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,6 +1544,119 @@ public string PlayerName
}


/// <summary>
/// Is sent by the client when: The player wants to set a price of an item which is inside his personal item shop, in zen or in one of the price types which are allowed by the server (see PlayerShopPriceTypesExtended).
/// Causes reaction on server side: The price is set for the specified item, if its price type is allowed and the amount is within the configured limits. Works only if the shop is currently closed. The server responds with a PlayerShopSetItemPriceResponse.
/// </summary>
public readonly ref struct PlayerShopSetItemPriceExtendedRef
{
private readonly Span<byte> _data;

/// <summary>
/// Initializes a new instance of the <see cref="PlayerShopSetItemPriceExtendedRef"/> struct.
/// </summary>
/// <param name="data">The underlying data.</param>
public PlayerShopSetItemPriceExtendedRef(Span<byte> data)
: this(data, true)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="PlayerShopSetItemPriceExtendedRef"/> struct.
/// </summary>
/// <param name="data">The underlying data.</param>
/// <param name="initialize">If set to <c>true</c>, the header data is automatically initialized and written to the underlying span.</param>
private PlayerShopSetItemPriceExtendedRef(Span<byte> 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;
}
}

/// <summary>
/// Gets the header type of this data packet.
/// </summary>
public static byte HeaderType => 0xC3;

/// <summary>
/// Gets the operation code of this data packet.
/// </summary>
public static byte Code => 0x3F;

/// <summary>
/// Gets the operation sub-code of this data packet.
/// The <see cref="Code" /> is used as a grouping key.
/// </summary>
public static byte SubCode => 0x09;

/// <summary>
/// Gets the initial length of this data packet. When the size is dynamic, this value may be bigger than actually needed.
/// </summary>
public static int Length => 13;

/// <summary>
/// Gets the header of this packet.
/// </summary>
public C3HeaderWithSubCodeRef Header => new (this._data);

/// <summary>
/// Gets or sets the price in zen, or in account coins when PriceItemType is one of the account coin values. Encoded like the price of PlayerShopItemExtended.
/// </summary>
public uint MoneyPrice
{
get => ReadUInt32LittleEndian(this._data[4..]);
set => WriteUInt32LittleEndian(this._data[4..], value);
}

/// <summary>
/// Gets or sets the item (group in the highest 4 bits, number in the remaining ones) with which the price is paid, when RequiredItemAmount is greater than 0. Otherwise, 0xFFF0 = WCoin (C), 0xFFF1 = WCoin (P) and 0xFFF2 = Goblin Points define an account coin price; any other value a zen price. Encoded like the price of PlayerShopItemExtended.
/// </summary>
public ushort PriceItemType
{
get => ReadUInt16LittleEndian(this._data[8..]);
set => WriteUInt16LittleEndian(this._data[8..], value);
}

/// <summary>
/// Gets or sets the number of pieces of the item which is defined by PriceItemType; 0, if the price is not paid with items. Encoded like the price of PlayerShopItemExtended.
/// </summary>
public ushort RequiredItemAmount
{
get => ReadUInt16LittleEndian(this._data[10..]);
set => WriteUInt16LittleEndian(this._data[10..], value);
}

/// <summary>
/// Gets or sets the item slot.
/// </summary>
public byte ItemSlot
{
get => this._data[12];
set => this._data[12] = value;
}

/// <summary>
/// Performs an implicit conversion from a Span of bytes to a <see cref="PlayerShopSetItemPriceExtended"/>.
/// </summary>
/// <param name="packet">The packet as span.</param>
/// <returns>The packet as struct.</returns>
public static implicit operator PlayerShopSetItemPriceExtendedRef(Span<byte> packet) => new (packet, false);

/// <summary>
/// Performs an implicit conversion from <see cref="PlayerShopSetItemPriceExtended"/> to a Span of bytes.
/// </summary>
/// <param name="packet">The packet as struct.</param>
/// <returns>The packet as byte span.</returns>
public static implicit operator Span<byte>(PlayerShopSetItemPriceExtendedRef packet) => packet._data;
}


/// <summary>
/// Is sent by the client when: A player requests to pick up an item which is laying on the ground in the near of the players character.
/// Causes reaction on server side: If the player is allowed to pick the item up, and is the first player which tried that, it tries to add the item to the inventory. The server sends a response about the result of the request.
Expand Down
Loading
Loading