diff --git a/common/base_packet.h b/common/base_packet.h index 027b8d2fb..16a527ade 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -67,6 +67,8 @@ public: uint8 ReadUInt8() { uint8 value = *(uint8 *)(pBuffer + _rpos); _rpos += sizeof(uint8); return value; } uint8 ReadUInt8(uint32 Offset) const { uint8 value = *(uint8 *)(pBuffer + Offset); return value; } + uint16 ReadUInt16() { uint16 value = *(uint16 *)(pBuffer + _rpos); _rpos += sizeof(uint16); return value; } + uint16 ReadUInt16(uint32 Offset) const { uint16 value = *(uint16 *)(pBuffer + Offset); return value; } uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; } uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; } void ReadString(char *str) { uint32 len = static_cast(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; } diff --git a/common/emu_oplist.h b/common/emu_oplist.h index 28ec9af0f..223491ecd 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -215,6 +215,7 @@ N(OP_GroupUpdate), N(OP_GroupUpdateB), N(OP_GroupUpdateLeaderAA), N(OP_GuildBank), +N(OP_GuildBankItemList), N(OP_GuildCreate), N(OP_GuildDelete), N(OP_GuildDemote), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 3f6476ba9..74eb9536e 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4724,6 +4724,22 @@ struct GuildBankItemUpdate_Struct /*226*/ uint16 Unknown226; }; +// newer clients (RoF+) send a list that contains 240 entries +// The packets don't actually use all 64 chars in the strings, but we'll just overallocate for these +struct GuildBankItemListEntry_Struct +{ + uint8 vaild; + uint32 permissions; + char whofor[64]; + char donator[64]; + uint32 item_id; + uint32 item_icon; + uint32 quantity; + uint8 allow_merge; // 1 here for non-full stacks + uint8 usable; + char item_name[64]; +}; + struct GuildBankClear_Struct { /*00*/ uint32 Action; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 4ee6d4ec0..79c7271fd 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1179,6 +1179,54 @@ namespace RoF dest->FastQueuePacket(&outapp); } + ENCODE(OP_GuildBank) + { + auto in = *p; + *p = nullptr; + auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger + + // The first action in the enum was removed, everything 1 less + // Normally we cast them to their structs, but there are so many here! will only do when it's easier + switch (in->ReadUInt32()) { + case 10: // GuildBankAcknowledge + outapp->WriteUInt32(9); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + break; + case 5: // GuildBankDeposit (ack) + outapp->WriteUInt32(4); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + outapp->WriteUInt32(in->ReadUInt32()); + break; + case 1: { // GuildBankItemUpdate + auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer; + auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer; + eq->Action = 0; + OUT(Unknown004); + eq->Unknown08 = 0; + OUT(SlotID); + OUT(Area); + OUT(Unknown012); + OUT(ItemID); + OUT(Icon); + OUT(Quantity); + OUT(Permissions); + OUT(AllowMerge); + OUT(Useable); + OUT_str(ItemName); + OUT_str(Donator); + OUT_str(WhoFor); + OUT(Unknown226); + break; + } + default: + break; + } + delete in; + dest->FastQueuePacket(&outapp); + } + ENCODE(OP_GuildMemberList) { //consume the packet @@ -4590,6 +4638,92 @@ namespace RoF DECODE_FORWARD(OP_GroupInvite); } + DECODE(OP_GuildBank) + { + // all actions are 1 off due to the removal of one of enums + switch (__packet->ReadUInt32()) { + case 2: {// GuildBankPromote + DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct); + SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct); + emu->Action = 3; + IN(Unknown04); + IN(Slot); + IN(Slot2); + FINISH_DIRECT_DECODE(); + return; + } + case 3: { // GuildBankViewItem + DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct); + SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct); + emu->Action = 4; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Unknown16); + FINISH_DIRECT_DECODE(); + return; + } + case 4: { // GuildBankDeposit + __packet->WriteUInt32(5); + return; + } + case 5: { // GuildBankPermissions + DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct); + SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct); + emu->Action = 6; + IN(Unknown04); + IN(SlotID); + IN(Unknown10); + IN(ItemID); + IN(Permissions); + strn0cpy(emu->MemberName, eq->MemberName, 64); + FINISH_DIRECT_DECODE(); + return; + } + case 6: { // GuildBankWithdraw + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 7; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 7: { // GuildBankSplitStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 8; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 8: { // GuildBankMergeStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 9; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + default: + Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action"); + __packet->SetOpcode(OP_Unknown); /* invalidate the packet */ + return; + } + } + DECODE(OP_GuildDemote) { DECODE_LENGTH_EXACT(structs::GuildDemoteStruct); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 7319dc98b..e5cc77791 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1250,6 +1250,54 @@ namespace RoF2 dest->FastQueuePacket(&outapp); } + ENCODE(OP_GuildBank) + { + auto in = *p; + *p = nullptr; + auto outapp = new EQApplicationPacket(OP_GuildBank, in->size + 4); // all of them are 4 bytes bigger + + // The first action in the enum was removed, everything 1 less + // Normally we cast them to their structs, but there are so many here! will only do when it's easier + switch (in->ReadUInt32()) { + case 10: // GuildBankAcknowledge + outapp->WriteUInt32(9); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + break; + case 5: // GuildBankDeposit (ack) + outapp->WriteUInt32(4); + outapp->WriteUInt32(in->ReadUInt32()); + outapp->WriteUInt32(0); + outapp->WriteUInt32(in->ReadUInt32()); + break; + case 1: { // GuildBankItemUpdate + auto emu = (GuildBankItemUpdate_Struct *)in->pBuffer; + auto eq = (structs::GuildBankItemUpdate_Struct *)outapp->pBuffer; + eq->Action = 0; + OUT(Unknown004); + eq->Unknown08 = 0; + OUT(SlotID); + OUT(Area); + OUT(Unknown012); + OUT(ItemID); + OUT(Icon); + OUT(Quantity); + OUT(Permissions); + OUT(AllowMerge); + OUT(Useable); + OUT_str(ItemName); + OUT_str(Donator); + OUT_str(WhoFor); + OUT(Unknown226); + break; + } + default: + break; + } + delete in; + dest->FastQueuePacket(&outapp); + } + ENCODE(OP_GuildMemberList) { //consume the packet @@ -4739,6 +4787,92 @@ namespace RoF2 DECODE_FORWARD(OP_GroupInvite); } + DECODE(OP_GuildBank) + { + // all actions are 1 off due to the removal of one of enums + switch (__packet->ReadUInt32()) { + case 2: {// GuildBankPromote + DECODE_LENGTH_EXACT(structs::GuildBankPromote_Struct); + SETUP_DIRECT_DECODE(GuildBankPromote_Struct, structs::GuildBankPromote_Struct); + emu->Action = 3; + IN(Unknown04); + IN(Slot); + IN(Slot2); + FINISH_DIRECT_DECODE(); + return; + } + case 3: { // GuildBankViewItem + DECODE_LENGTH_EXACT(structs::GuildBankViewItem_Struct); + SETUP_DIRECT_DECODE(GuildBankViewItem_Struct, structs::GuildBankViewItem_Struct); + emu->Action = 4; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Unknown16); + FINISH_DIRECT_DECODE(); + return; + } + case 4: { // GuildBankDeposit + __packet->WriteUInt32(5); + return; + } + case 5: { // GuildBankPermissions + DECODE_LENGTH_EXACT(structs::GuildBankPermissions_Struct); + SETUP_DIRECT_DECODE(GuildBankPermissions_Struct, structs::GuildBankPermissions_Struct); + emu->Action = 6; + IN(Unknown04); + IN(SlotID); + IN(Unknown10); + IN(ItemID); + IN(Permissions); + strn0cpy(emu->MemberName, eq->MemberName, 64); + FINISH_DIRECT_DECODE(); + return; + } + case 6: { // GuildBankWithdraw + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 7; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 7: { // GuildBankSplitStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 8; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + case 8: { // GuildBankMergeStacks + DECODE_LENGTH_EXACT(structs::GuildBankWithdrawItem_Struct); + SETUP_DIRECT_DECODE(GuildBankWithdrawItem_Struct, structs::GuildBankWithdrawItem_Struct); + emu->Action = 9; + IN(Unknown04); + IN(SlotID); + IN(Area); + IN(Unknown12); + IN(Quantity); + FINISH_DIRECT_DECODE(); + return; + } + default: + Log.Out(Logs::Detail, Logs::Netcode, "Unhandled OP_GuildBank action"); + __packet->SetOpcode(OP_Unknown); /* invalidate the packet */ + return; + } + } + DECODE(OP_GuildDemote) { DECODE_LENGTH_EXACT(structs::GuildDemoteStruct); diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 3bb69af5e..9fe76e33c 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -57,6 +57,7 @@ E(OP_GroupFollow) E(OP_GroupFollow2) E(OP_GroupInvite) E(OP_GroupUpdate) +E(OP_GuildBank) E(OP_GuildMemberList) E(OP_GuildMemberUpdate) E(OP_GuildsList) @@ -152,6 +153,7 @@ D(OP_GroupFollow) D(OP_GroupFollow2) D(OP_GroupInvite) D(OP_GroupInvite2) +D(OP_GuildBank) D(OP_GuildDemote) D(OP_GuildRemove) D(OP_GuildStatus) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 81fc48eaa..1e93b7434 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1859,6 +1859,114 @@ struct GuildUpdate_Struct { GuildsListEntry_Struct entry; }; +struct GuildBankAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +}; + +struct GuildBankDepositAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint32 Fail; //1 = Fail, 0 = Success +}; + +struct GuildBankPromote_Struct +{ +/*00*/ uint32 Action; // 3 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 Slot; +/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3 +/*20*/ uint32 unknown20; +}; + +struct GuildBankPermissions_Struct +{ +/*00*/ uint32 Action; // 6 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits +/*12*/ uint32 ItemID; +/*16*/ uint32 Permissions; +/*20*/ char MemberName[64]; +}; + +struct GuildBankViewItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Unknown16; +}; + +struct GuildBankWithdrawItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Quantity; +/*20*/ +}; + +struct GuildBankItemUpdate_Struct +{ + void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity, + uint32 inPermissions, uint32 inAllowMerge, bool inUseable) + { + Action = inAction; + Unknown004 = inUnknown004; + SlotID = inSlotID; + Area = inArea; + Unknown012 = inUnknown012; + ItemID = inItemID; + Icon = inIcon; + Quantity = inQuantity; + Permissions = inPermissions; + AllowMerge = inAllowMerge; + Useable = inUseable; + ItemName[0] = '\0'; + Donator[0] = '\0'; + WhoFor[0] = '\0'; + }; + +/*000*/ uint32 Action; +/*004*/ uint32 Unknown004; +/*008*/ uint32 Unknown08; +/*012*/ uint16 SlotID; +/*014*/ uint16 Area; +/*016*/ uint32 Unknown012; +/*020*/ uint32 ItemID; +/*024*/ uint32 Icon; +/*028*/ uint32 Quantity; +/*032*/ uint32 Permissions; +/*036*/ uint8 AllowMerge; +/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission. +/*038*/ char ItemName[64]; +/*102*/ char Donator[64]; +/*166*/ char WhoFor[64]; +/*230*/ uint16 Unknown226; +}; + +struct GuildBankClear_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 DepositAreaCount; +/*16*/ uint32 MainAreaCount; +}; + /* ** Money Loot ** Length: 22 Bytes diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 8e9adfdc9..606c51c62 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -42,6 +42,7 @@ E(OP_GroupFollow) E(OP_GroupFollow2) E(OP_GroupInvite) E(OP_GroupUpdate) +E(OP_GuildBank) E(OP_GuildMemberList) E(OP_GuildMemberUpdate) E(OP_GuildsList) @@ -137,6 +138,7 @@ D(OP_GroupFollow) D(OP_GroupFollow2) D(OP_GroupInvite) D(OP_GroupInvite2) +D(OP_GuildBank) D(OP_GuildDemote) D(OP_GuildRemove) D(OP_GuildStatus) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index beb550cbc..e24935d35 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1889,6 +1889,114 @@ struct GuildUpdate_Struct { GuildsListEntry_Struct entry; }; +struct GuildBankAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +}; + +struct GuildBankDepositAck_Struct +{ +/*00*/ uint32 Action; // 10 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint32 Fail; //1 = Fail, 0 = Success +}; + +struct GuildBankPromote_Struct +{ +/*00*/ uint32 Action; // 3 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 Slot; +/*16*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3 +/*20*/ uint32 unknown20; +}; + +struct GuildBankPermissions_Struct +{ +/*00*/ uint32 Action; // 6 +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Unknown10; // Saw 1, probably indicating it is the main area rather than deposits +/*12*/ uint32 ItemID; +/*16*/ uint32 Permissions; +/*20*/ char MemberName[64]; +}; + +struct GuildBankViewItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; // 0 = Deposit area, 1 = Main area +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Unknown16; +}; + +struct GuildBankWithdrawItem_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*08*/ uint16 SlotID; +/*10*/ uint16 Area; +/*12*/ uint32 Unknown12; +/*16*/ uint32 Quantity; +/*20*/ +}; + +struct GuildBankItemUpdate_Struct +{ + void Init(uint32 inAction, uint32 inUnknown004, uint16 inSlotID, uint16 inArea, uint16 inUnknown012, uint32 inItemID, uint32 inIcon, uint32 inQuantity, + uint32 inPermissions, uint32 inAllowMerge, bool inUseable) + { + Action = inAction; + Unknown004 = inUnknown004; + SlotID = inSlotID; + Area = inArea; + Unknown012 = inUnknown012; + ItemID = inItemID; + Icon = inIcon; + Quantity = inQuantity; + Permissions = inPermissions; + AllowMerge = inAllowMerge; + Useable = inUseable; + ItemName[0] = '\0'; + Donator[0] = '\0'; + WhoFor[0] = '\0'; + }; + +/*000*/ uint32 Action; +/*004*/ uint32 Unknown004; +/*008*/ uint32 Unknown08; +/*012*/ uint16 SlotID; +/*014*/ uint16 Area; +/*016*/ uint32 Unknown012; +/*020*/ uint32 ItemID; +/*024*/ uint32 Icon; +/*028*/ uint32 Quantity; +/*032*/ uint32 Permissions; +/*036*/ uint8 AllowMerge; +/*037*/ uint8 Useable; // Used in conjunction with the Public-if-useable permission. +/*038*/ char ItemName[64]; +/*102*/ char Donator[64]; +/*166*/ char WhoFor[64]; +/*230*/ uint16 Unknown226; +}; + +struct GuildBankClear_Struct +{ +/*00*/ uint32 Action; +/*04*/ uint32 Unknown04; +/*08*/ uint32 Unknown08; +/*12*/ uint32 DepositAreaCount; +/*16*/ uint32 MainAreaCount; +}; + /* ** Money Loot ** Length: 22 Bytes diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index dfd8f0e84..7a33eb459 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -131,6 +131,7 @@ OP_GuildPromote=0x2945 OP_GuildPublicNote=0x3c2c OP_GuildManageBanker=0x389c # Was 0x096d OP_GuildBank=0x2ab0 # Was 0x10c3 +OP_GuildBankItemList=0x1cbf OP_SetGuildRank=0x3599 OP_GuildUpdateURLAndChannel=0x7851 OP_GuildStatus=0x25a5 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 0d1cb20ec..6afb7209e 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -130,6 +130,7 @@ OP_GuildPromote=0x6a98 OP_GuildPublicNote=0x5053 OP_GuildManageBanker=0x3f35 OP_GuildBank=0x5134 +OP_GuildBankItemList=0x7850 OP_SetGuildRank=0x0b9c OP_GuildUpdateURLAndChannel=0x2958 OP_GuildStatus=0x7326 diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c955399b8..a766f0470 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6683,20 +6683,6 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app) uint32 Action = VARSTRUCT_DECODE_TYPE(uint32, Buffer); uint32 sentAction = Action; - if (GetClientVersion() >= ClientVersion::RoF) - { - Action += 1; - /* - // Need to find all of the action types for RoF and switch case here - switch(Action) - { - case 4: - Action = 5; - break; - } - */ - } - if (!IsInAGuild()) { Message(13, "You must be in a Guild to use the Guild Bank."); diff --git a/zone/guild.cpp b/zone/guild.cpp index 12f785b02..7b3c104f8 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -248,7 +248,9 @@ void Client::RefreshGuildInfo() if((guild_id != OldGuildID) && GuildBanks) { - ClearGuildBank(); + // Unsure about this for RoF+ ... But they don't have that action anymore so fuck it + if (GetClientVersion() < ClientVersion::RoF) + ClearGuildBank(); if(guild_id != GUILD_NONE) GuildBanks->SendGuildBank(this); diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index 8754a60e8..ed9957908 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -688,11 +688,68 @@ void GuildBankManager::SendGuildBank(Client *c) return; } + auto &guild_bank = *Iterator; + + // RoF+ uses a bulk list packet -- This is also how the Action 0 of older clients basically works + if (c->GetClientVersionBit() & BIT_RoFAndLater) { + auto outapp = new EQApplicationPacket(OP_GuildBankItemList, sizeof(GuildBankItemListEntry_Struct) * 240); + for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) { + const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); + if (Item) { + outapp->WriteUInt8(1); + outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Permissions); + outapp->WriteString(guild_bank->Items.DepositArea[i].WhoFor); + outapp->WriteString(guild_bank->Items.DepositArea[i].Donator); + outapp->WriteUInt32(Item->ID); + outapp->WriteUInt32(Item->Icon); + if (Item->Stackable) { + outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Quantity); + outapp->WriteUInt8(Item->StackSize == guild_bank->Items.DepositArea[i].Quantity ? 0 : 1); + } else { + outapp->WriteUInt32(1); + outapp->WriteUInt8(0); + } + outapp->WriteUInt8(Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0); + outapp->WriteString(Item->Name); + } else { + outapp->WriteUInt8(0); // empty + } + } + outapp->SetWritePosition(outapp->GetWritePosition() + 20); // newer clients have 40 deposit slots, keep them 0 for now + + for (int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) { + const Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); + if (Item) { + outapp->WriteUInt8(1); + outapp->WriteUInt32(guild_bank->Items.MainArea[i].Permissions); + outapp->WriteString(guild_bank->Items.MainArea[i].WhoFor); + outapp->WriteString(guild_bank->Items.MainArea[i].Donator); + outapp->WriteUInt32(Item->ID); + outapp->WriteUInt32(Item->Icon); + if (Item->Stackable) { + outapp->WriteUInt32(guild_bank->Items.MainArea[i].Quantity); + outapp->WriteUInt8(Item->StackSize == guild_bank->Items.MainArea[i].Quantity ? 0 : 1); + } else { + outapp->WriteUInt32(1); + outapp->WriteUInt8(0); + } + outapp->WriteUInt8(Item->IsEquipable(c->GetBaseRace(), c->GetBaseClass()) ? 1 : 0); + outapp->WriteString(Item->Name); + } else { + outapp->WriteUInt8(0); // empty + } + } + + outapp->size = outapp->GetWritePosition(); // truncate to used size + c->FastQueuePacket(&outapp); + return; + } + for(int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) { - if((*Iterator)->Items.DepositArea[i].ItemID > 0) + if(guild_bank->Items.DepositArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem((*Iterator)->Items.DepositArea[i].ItemID); + const Item_Struct *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID); if(!Item) continue; @@ -703,22 +760,22 @@ void GuildBankManager::SendGuildBank(Client *c) if(!Item->Stackable) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon, 1, - (*Iterator)->Items.DepositArea[i].Permissions, 0, 0); + guild_bank->Items.DepositArea[i].Permissions, 0, 0); else { - if((*Iterator)->Items.DepositArea[i].Quantity == Item->StackSize) + if(guild_bank->Items.DepositArea[i].Quantity == Item->StackSize) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.DepositArea[i].Quantity, (*Iterator)->Items.DepositArea[i].Permissions, 0, 0); + guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 0, 0); else gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.DepositArea[i].Quantity, (*Iterator)->Items.DepositArea[i].Permissions, 1, 0); + guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 1, 0); } strn0cpy(gbius->ItemName, Item->Name, sizeof(gbius->ItemName)); - strn0cpy(gbius->Donator, (*Iterator)->Items.DepositArea[i].Donator, sizeof(gbius->Donator)); + strn0cpy(gbius->Donator, guild_bank->Items.DepositArea[i].Donator, sizeof(gbius->Donator)); - strn0cpy(gbius->WhoFor, (*Iterator)->Items.DepositArea[i].WhoFor, sizeof(gbius->WhoFor)); + strn0cpy(gbius->WhoFor, guild_bank->Items.DepositArea[i].WhoFor, sizeof(gbius->WhoFor)); c->FastQueuePacket(&outapp); } @@ -726,9 +783,9 @@ void GuildBankManager::SendGuildBank(Client *c) for(int i = 0; i < GUILD_BANK_MAIN_AREA_SIZE; ++i) { - if((*Iterator)->Items.MainArea[i].ItemID > 0) + if(guild_bank->Items.MainArea[i].ItemID > 0) { - const Item_Struct *Item = database.GetItem((*Iterator)->Items.MainArea[i].ItemID); + const Item_Struct *Item = database.GetItem(guild_bank->Items.MainArea[i].ItemID); if(!Item) continue; @@ -741,22 +798,22 @@ void GuildBankManager::SendGuildBank(Client *c) if(!Item->Stackable) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon, 1, - (*Iterator)->Items.MainArea[i].Permissions, 0, Useable); + guild_bank->Items.MainArea[i].Permissions, 0, Useable); else { - if((*Iterator)->Items.MainArea[i].Quantity == Item->StackSize) + if(guild_bank->Items.MainArea[i].Quantity == Item->StackSize) gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.MainArea[i].Quantity, (*Iterator)->Items.MainArea[i].Permissions, 0, Useable); + guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 0, Useable); else gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon, - (*Iterator)->Items.MainArea[i].Quantity, (*Iterator)->Items.MainArea[i].Permissions, 1, Useable); + guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 1, Useable); } strn0cpy(gbius->ItemName, Item->Name, sizeof(gbius->ItemName)); - strn0cpy(gbius->Donator, (*Iterator)->Items.MainArea[i].Donator, sizeof(gbius->Donator)); + strn0cpy(gbius->Donator, guild_bank->Items.MainArea[i].Donator, sizeof(gbius->Donator)); - strn0cpy(gbius->WhoFor, (*Iterator)->Items.MainArea[i].WhoFor, sizeof(gbius->WhoFor)); + strn0cpy(gbius->WhoFor, guild_bank->Items.MainArea[i].WhoFor, sizeof(gbius->WhoFor)); c->FastQueuePacket(&outapp); }