convert other Warehouse types to new system

This commit is contained in:
wish
2024-02-25 14:12:37 +11:00
parent a9b9c94347
commit 40d4aba3c4
6 changed files with 94 additions and 188 deletions

View File

@@ -2,24 +2,18 @@ package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/common/mhfitem"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network" "erupe-ce/network"
"erupe-ce/network/clientctx" "erupe-ce/network/clientctx"
) )
type Item struct {
Unk0 uint32
ItemID uint16
Amount uint16
Unk1 uint32
}
// MsgMhfUpdateGuildItem represents the MSG_MHF_UPDATE_GUILD_ITEM // MsgMhfUpdateGuildItem represents the MSG_MHF_UPDATE_GUILD_ITEM
type MsgMhfUpdateGuildItem struct { type MsgMhfUpdateGuildItem struct {
AckHandle uint32 AckHandle uint32
GuildID uint32 GuildID uint32
Items []Item UpdatedItems []mhfitem.MHFItemStack
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -31,18 +25,12 @@ func (m *MsgMhfUpdateGuildItem) Opcode() network.PacketID {
func (m *MsgMhfUpdateGuildItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfUpdateGuildItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
m.GuildID = bf.ReadUint32() m.GuildID = bf.ReadUint32()
itemCount := int(bf.ReadUint16()) changes := int(bf.ReadUint16())
bf.ReadUint8() // Zeroed bf.ReadUint8() // Zeroed
bf.ReadUint8() // Zeroed bf.ReadUint8() // Zeroed
m.Items = make([]Item, itemCount) for i := 0; i < changes; i++ {
m.UpdatedItems = append(m.UpdatedItems, mhfitem.ReadWarehouseItem(bf))
for i := 0; i < itemCount; i++ {
m.Items[i].Unk0 = bf.ReadUint32()
m.Items[i].ItemID = bf.ReadUint16()
m.Items[i].Amount = bf.ReadUint16()
m.Items[i].Unk1 = bf.ReadUint32()
} }
return nil return nil
} }

View File

@@ -2,6 +2,7 @@ package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/common/mhfitem"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network" "erupe-ce/network"
@@ -10,8 +11,8 @@ import (
// MsgMhfUpdateUnionItem represents the MSG_MHF_UPDATE_UNION_ITEM // MsgMhfUpdateUnionItem represents the MSG_MHF_UPDATE_UNION_ITEM
type MsgMhfUpdateUnionItem struct { type MsgMhfUpdateUnionItem struct {
AckHandle uint32 AckHandle uint32
Items []Item UpdatedItems []mhfitem.MHFItemStack
} }
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
@@ -22,18 +23,12 @@ func (m *MsgMhfUpdateUnionItem) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfUpdateUnionItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfUpdateUnionItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32() m.AckHandle = bf.ReadUint32()
itemCount := int(bf.ReadUint16()) changes := int(bf.ReadUint16())
bf.ReadUint8() // Zeroed bf.ReadUint8() // Zeroed
bf.ReadUint8() // Zeroed bf.ReadUint8() // Zeroed
m.Items = make([]Item, itemCount) for i := 0; i < changes; i++ {
m.UpdatedItems = append(m.UpdatedItems, mhfitem.ReadWarehouseItem(bf))
for i := 0; i < itemCount; i++ {
m.Items[i].Unk0 = bf.ReadUint32()
m.Items[i].ItemID = bf.ReadUint16()
m.Items[i].Amount = bf.ReadUint16()
m.Items[i].Unk1 = bf.ReadUint32()
} }
return nil return nil
} }

View File

@@ -28,7 +28,8 @@ func (m *MsgMhfUpdateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl
m.BoxType = bf.ReadUint8() m.BoxType = bf.ReadUint8()
m.BoxIndex = bf.ReadUint8() m.BoxIndex = bf.ReadUint8()
changes := int(bf.ReadUint16()) changes := int(bf.ReadUint16())
bf.ReadBytes(2) // Zeroed bf.ReadUint8() // Zeroed
bf.ReadUint8() // Zeroed
for i := 0; i < changes; i++ { for i := 0; i < changes; i++ {
switch m.BoxType { switch m.BoxType {
case 0: case 0:

View File

@@ -0,0 +1,6 @@
BEGIN;
UPDATE guilds SET item_box=NULL;
UPDATE users SET item_box=NULL;
END;

View File

@@ -7,6 +7,7 @@ import (
"erupe-ce/common/mhfmon" "erupe-ce/common/mhfmon"
ps "erupe-ce/common/pascalstring" ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
"erupe-ce/common/token"
_config "erupe-ce/config" _config "erupe-ce/config"
"fmt" "fmt"
"io" "io"
@@ -818,93 +819,53 @@ func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) { func userGetItems(s *Session) []mhfitem.MHFItemStack {
pkt := p.(*mhfpacket.MsgMhfEnumerateUnionItem) var data []byte
var boxContents []byte var items []mhfitem.MHFItemStack
bf := byteframe.NewByteFrame() s.server.db.QueryRow(`SELECT item_box FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&data)
err := s.server.db.QueryRow("SELECT item_box FROM users, characters WHERE characters.id = $1 AND users.id = characters.user_id", int(s.charID)).Scan(&boxContents) if len(data) > 0 {
if err != nil { box := byteframe.NewByteFrameFromBytes(data)
s.logger.Error("Failed to get shared item box contents from db", zap.Error(err)) numStacks := box.ReadUint16()
bf.WriteBytes(make([]byte, 4)) box.ReadUint16() // Unused
} else { for i := 0; i < int(numStacks); i++ {
if len(boxContents) == 0 { items = append(items, mhfitem.ReadWarehouseItem(box))
bf.WriteBytes(make([]byte, 4))
} else {
amount := len(boxContents) / 4
bf.WriteUint16(uint16(amount))
bf.WriteUint32(0x00)
bf.WriteUint16(0x00)
for i := 0; i < amount; i++ {
bf.WriteUint32(binary.BigEndian.Uint32(boxContents[i*4 : i*4+4]))
if i+1 != amount {
bf.WriteUint64(0x00)
}
}
} }
} }
return items
}
func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateUnionItem)
items := userGetItems(s)
bf := byteframe.NewByteFrame()
bf.WriteBytes(mhfitem.SerializeWarehouseItems(items))
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem) pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem)
// Get item cache from DB // o = old, u = update, f = final
var boxContents []byte var fItems []mhfitem.MHFItemStack
var oldItems []Item oItems := userGetItems(s)
for _, uItem := range pkt.UpdatedItems {
err := s.server.db.QueryRow("SELECT item_box FROM users, characters WHERE characters.id = $1 AND users.id = characters.user_id", int(s.charID)).Scan(&boxContents) exists := false
if err != nil { for i := range oItems {
s.logger.Error("Failed to get shared item box contents from db", zap.Error(err)) if oItems[i].WarehouseID == uItem.WarehouseID {
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) exists = true
return oItems[i].Quantity = uItem.Quantity
} else {
amount := len(boxContents) / 4
oldItems = make([]Item, amount)
for i := 0; i < amount; i++ {
oldItems[i].ItemId = binary.BigEndian.Uint16(boxContents[i*4 : i*4+2])
oldItems[i].Amount = binary.BigEndian.Uint16(boxContents[i*4+2 : i*4+4])
}
}
// Update item stacks
newItems := make([]Item, len(oldItems))
copy(newItems, oldItems)
for i := 0; i < len(pkt.Items); i++ {
for j := 0; j <= len(oldItems); j++ {
if j == len(oldItems) {
var newItem Item
newItem.ItemId = pkt.Items[i].ItemID
newItem.Amount = pkt.Items[i].Amount
newItems = append(newItems, newItem)
break
}
if pkt.Items[i].ItemID == oldItems[j].ItemId {
newItems[j].Amount = pkt.Items[i].Amount
break
} }
} }
} if !exists {
uItem.WarehouseID = token.RNG.Uint32()
// Delete empty item stacks fItems = append(fItems, uItem)
for i := len(newItems) - 1; i >= 0; i-- {
if int(newItems[i].Amount) == 0 {
copy(newItems[i:], newItems[i+1:])
newItems[len(newItems)-1] = make([]Item, 1)[0]
newItems = newItems[:len(newItems)-1]
} }
} }
for _, oItem := range oItems {
// Create new item cache if oItem.Quantity > 0 {
bf := byteframe.NewByteFrame() fItems = append(fItems, oItem)
for i := 0; i < len(newItems); i++ { }
bf.WriteUint16(newItems[i].ItemId)
bf.WriteUint16(newItems[i].Amount)
}
// Upload new item cache
_, err = s.server.db.Exec("UPDATE users SET item_box = $1 FROM characters WHERE users.id = characters.user_id AND characters.id = $2", bf.Data(), int(s.charID))
if err != nil {
s.logger.Error("Failed to update shared item box contents in db", zap.Error(err))
} }
s.server.db.Exec(`UPDATE users u SET item_box=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, mhfitem.SerializeWarehouseItems(fItems), s.charID)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -3,9 +3,10 @@ package channelserver
import ( import (
"database/sql" "database/sql"
"database/sql/driver" "database/sql/driver"
"encoding/binary"
"encoding/json" "encoding/json"
"errors" "errors"
"erupe-ce/common/mhfitem"
"erupe-ce/common/token"
_config "erupe-ce/config" _config "erupe-ce/config"
"fmt" "fmt"
"math" "math"
@@ -1554,100 +1555,54 @@ func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) { func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack {
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildItem) var data []byte
var boxContents []byte var items []mhfitem.MHFItemStack
bf := byteframe.NewByteFrame() s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data)
err := s.server.db.QueryRow("SELECT item_box FROM guilds WHERE id = $1", pkt.GuildID).Scan(&boxContents) if len(data) > 0 {
if err != nil { box := byteframe.NewByteFrameFromBytes(data)
s.logger.Error("Failed to get guild item box contents from db", zap.Error(err)) numStacks := box.ReadUint16()
bf.WriteBytes(make([]byte, 4)) box.ReadUint16() // Unused
} else { for i := 0; i < int(numStacks); i++ {
if len(boxContents) == 0 { items = append(items, mhfitem.ReadWarehouseItem(box))
bf.WriteBytes(make([]byte, 4))
} else {
amount := len(boxContents) / 4
bf.WriteUint16(uint16(amount))
bf.WriteUint32(0x00)
bf.WriteUint16(0x00)
for i := 0; i < amount; i++ {
bf.WriteUint32(binary.BigEndian.Uint32(boxContents[i*4 : i*4+4]))
if i+1 != amount {
bf.WriteUint64(0x00)
}
}
} }
} }
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) return items
} }
type Item struct { func handleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) {
ItemId uint16 pkt := p.(*mhfpacket.MsgMhfEnumerateGuildItem)
Amount uint16 items := guildGetItems(s, pkt.GuildID)
bf := byteframe.NewByteFrame()
bf.WriteBytes(mhfitem.SerializeWarehouseItems(items))
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateGuildItem) pkt := p.(*mhfpacket.MsgMhfUpdateGuildItem)
// o = old, u = update, f = final
// Get item cache from DB var fItems []mhfitem.MHFItemStack
var boxContents []byte oItems := guildGetItems(s, pkt.GuildID)
var oldItems []Item for _, uItem := range pkt.UpdatedItems {
err := s.server.db.QueryRow("SELECT item_box FROM guilds WHERE id = $1", pkt.GuildID).Scan(&boxContents) exists := false
if err != nil { for i := range oItems {
s.logger.Error("Failed to get guild item box contents from db", zap.Error(err)) if oItems[i].WarehouseID == uItem.WarehouseID {
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) exists = true
return oItems[i].Quantity = uItem.Quantity
} else {
amount := len(boxContents) / 4
oldItems = make([]Item, amount)
for i := 0; i < amount; i++ {
oldItems[i].ItemId = binary.BigEndian.Uint16(boxContents[i*4 : i*4+2])
oldItems[i].Amount = binary.BigEndian.Uint16(boxContents[i*4+2 : i*4+4])
}
}
// Update item stacks
newItems := make([]Item, len(oldItems))
copy(newItems, oldItems)
for i := 0; i < len(pkt.Items); i++ {
for j := 0; j <= len(oldItems); j++ {
if j == len(oldItems) {
var newItem Item
newItem.ItemId = pkt.Items[i].ItemID
newItem.Amount = pkt.Items[i].Amount
newItems = append(newItems, newItem)
break
}
if pkt.Items[i].ItemID == oldItems[j].ItemId {
newItems[j].Amount = pkt.Items[i].Amount
break
} }
} }
} if !exists {
uItem.WarehouseID = token.RNG.Uint32()
// Delete empty item stacks fItems = append(fItems, uItem)
for i := len(newItems) - 1; i >= 0; i-- {
if int(newItems[i].Amount) == 0 {
copy(newItems[i:], newItems[i+1:])
newItems[len(newItems)-1] = make([]Item, 1)[0]
newItems = newItems[:len(newItems)-1]
} }
} }
for _, oItem := range oItems {
// Create new item cache if oItem.Quantity > 0 {
bf := byteframe.NewByteFrame() fItems = append(fItems, oItem)
for i := 0; i < len(newItems); i++ { }
bf.WriteUint16(newItems[i].ItemId)
bf.WriteUint16(newItems[i].Amount)
} }
s.server.db.Exec(`UPDATE guilds SET item_box=$1 WHERE id=$2`, mhfitem.SerializeWarehouseItems(fItems), pkt.GuildID)
// Upload new item cache doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
_, err = s.server.db.Exec("UPDATE guilds SET item_box = $1 WHERE id = $2", bf.Data(), pkt.GuildID)
if err != nil {
s.logger.Error("Failed to update guild item box contents in db", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} }
func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) {