mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-02-04 09:15:08 +01:00
Merge pull request #115 from ZeruLight/feature/warehouse-v2
feature/warehouse-v2
This commit is contained in:
175
common/mhfitem/mhfitem.go
Normal file
175
common/mhfitem/mhfitem.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package mhfitem
|
||||
|
||||
import (
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/common/token"
|
||||
_config "erupe-ce/config"
|
||||
)
|
||||
|
||||
type MHFItem struct {
|
||||
ItemID uint16
|
||||
}
|
||||
|
||||
type MHFSigilEffect struct {
|
||||
ID uint16
|
||||
Level uint16
|
||||
}
|
||||
|
||||
type MHFSigil struct {
|
||||
Effects []MHFSigilEffect
|
||||
Unk0 uint8
|
||||
Unk1 uint8
|
||||
Unk2 uint8
|
||||
Unk3 uint8
|
||||
}
|
||||
|
||||
type MHFEquipment struct {
|
||||
WarehouseID uint32
|
||||
ItemType uint8
|
||||
Unk0 uint8
|
||||
ItemID uint16
|
||||
Level uint16
|
||||
Decorations []MHFItem
|
||||
Sigils []MHFSigil
|
||||
Unk1 uint16
|
||||
}
|
||||
|
||||
type MHFItemStack struct {
|
||||
WarehouseID uint32
|
||||
Item MHFItem
|
||||
Quantity uint16
|
||||
Unk0 uint32
|
||||
}
|
||||
|
||||
func ReadWarehouseItem(bf *byteframe.ByteFrame) MHFItemStack {
|
||||
var item MHFItemStack
|
||||
item.WarehouseID = bf.ReadUint32()
|
||||
if item.WarehouseID == 0 {
|
||||
item.WarehouseID = token.RNG.Uint32()
|
||||
}
|
||||
item.Item.ItemID = bf.ReadUint16()
|
||||
item.Quantity = bf.ReadUint16()
|
||||
item.Unk0 = bf.ReadUint32()
|
||||
return item
|
||||
}
|
||||
|
||||
func DiffItemStacks(o []MHFItemStack, u []MHFItemStack) []MHFItemStack {
|
||||
// o = old, u = update, f = final
|
||||
var f []MHFItemStack
|
||||
for _, uItem := range u {
|
||||
exists := false
|
||||
for i := range o {
|
||||
if o[i].WarehouseID == uItem.WarehouseID {
|
||||
exists = true
|
||||
o[i].Quantity = uItem.Quantity
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
uItem.WarehouseID = token.RNG.Uint32()
|
||||
f = append(f, uItem)
|
||||
}
|
||||
}
|
||||
for _, oItem := range o {
|
||||
if oItem.Quantity > 0 {
|
||||
f = append(f, oItem)
|
||||
}
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (is MHFItemStack) ToBytes() []byte {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(is.WarehouseID)
|
||||
bf.WriteUint16(is.Item.ItemID)
|
||||
bf.WriteUint16(is.Quantity)
|
||||
bf.WriteUint32(is.Unk0)
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func SerializeWarehouseItems(i []MHFItemStack) []byte {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(uint16(len(i)))
|
||||
bf.WriteUint16(0) // Unused
|
||||
for _, j := range i {
|
||||
bf.WriteBytes(j.ToBytes())
|
||||
}
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment {
|
||||
var equipment MHFEquipment
|
||||
equipment.Decorations = make([]MHFItem, 3)
|
||||
equipment.Sigils = make([]MHFSigil, 3)
|
||||
for i := 0; i < 3; i++ {
|
||||
equipment.Sigils[i].Effects = make([]MHFSigilEffect, 3)
|
||||
}
|
||||
equipment.WarehouseID = bf.ReadUint32()
|
||||
if equipment.WarehouseID == 0 {
|
||||
equipment.WarehouseID = token.RNG.Uint32()
|
||||
}
|
||||
equipment.ItemType = bf.ReadUint8()
|
||||
equipment.Unk0 = bf.ReadUint8()
|
||||
equipment.ItemID = bf.ReadUint16()
|
||||
equipment.Level = bf.ReadUint16()
|
||||
for i := 0; i < 3; i++ {
|
||||
equipment.Decorations[i].ItemID = bf.ReadUint16()
|
||||
}
|
||||
if _config.ErupeConfig.RealClientMode >= _config.G1 {
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
equipment.Sigils[i].Effects[j].ID = bf.ReadUint16()
|
||||
}
|
||||
for j := 0; j < 3; j++ {
|
||||
equipment.Sigils[i].Effects[j].Level = bf.ReadUint16()
|
||||
}
|
||||
equipment.Sigils[i].Unk0 = bf.ReadUint8()
|
||||
equipment.Sigils[i].Unk1 = bf.ReadUint8()
|
||||
equipment.Sigils[i].Unk2 = bf.ReadUint8()
|
||||
equipment.Sigils[i].Unk3 = bf.ReadUint8()
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
|
||||
equipment.Unk1 = bf.ReadUint16()
|
||||
}
|
||||
return equipment
|
||||
}
|
||||
|
||||
func (e MHFEquipment) ToBytes() []byte {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(e.WarehouseID)
|
||||
bf.WriteUint8(e.ItemType)
|
||||
bf.WriteUint8(e.Unk0)
|
||||
bf.WriteUint16(e.ItemID)
|
||||
bf.WriteUint16(e.Level)
|
||||
for i := 0; i < 3; i++ {
|
||||
bf.WriteUint16(e.Decorations[i].ItemID)
|
||||
}
|
||||
if _config.ErupeConfig.RealClientMode >= _config.G1 {
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
bf.WriteUint16(e.Sigils[i].Effects[j].ID)
|
||||
}
|
||||
for j := 0; j < 3; j++ {
|
||||
bf.WriteUint16(e.Sigils[i].Effects[j].Level)
|
||||
}
|
||||
bf.WriteUint8(e.Sigils[i].Unk0)
|
||||
bf.WriteUint8(e.Sigils[i].Unk1)
|
||||
bf.WriteUint8(e.Sigils[i].Unk2)
|
||||
bf.WriteUint8(e.Sigils[i].Unk3)
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.RealClientMode >= _config.Z1 {
|
||||
bf.WriteUint16(e.Unk1)
|
||||
}
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func SerializeWarehouseEquipment(i []MHFEquipment) []byte {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(uint16(len(i)))
|
||||
bf.WriteUint16(0) // Unused
|
||||
for _, j := range i {
|
||||
bf.WriteBytes(j.ToBytes())
|
||||
}
|
||||
return bf.Data()
|
||||
}
|
||||
@@ -5,18 +5,19 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var RNG = NewRNG()
|
||||
|
||||
// Generate returns an alphanumeric token of specified length
|
||||
func Generate(length int) string {
|
||||
rng := RNG()
|
||||
var chars = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
||||
b := make([]rune, length)
|
||||
for i := range b {
|
||||
b[i] = chars[rng.Intn(len(chars))]
|
||||
b[i] = chars[RNG.Intn(len(chars))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// RNG returns a new RNG generator
|
||||
func RNG() *rand.Rand {
|
||||
// NewRNG returns a new NewRNG generator
|
||||
func NewRNG() *rand.Rand {
|
||||
return rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
// MsgMhfEnumerateWarehouse represents the MSG_MHF_ENUMERATE_WAREHOUSE
|
||||
type MsgMhfEnumerateWarehouse struct {
|
||||
AckHandle uint32
|
||||
BoxType string
|
||||
BoxType uint8
|
||||
BoxIndex uint8
|
||||
}
|
||||
|
||||
@@ -23,15 +23,10 @@ func (m *MsgMhfEnumerateWarehouse) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfEnumerateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
boxType := bf.ReadUint8()
|
||||
switch boxType {
|
||||
case 0:
|
||||
m.BoxType = "item"
|
||||
case 1:
|
||||
m.BoxType = "equip"
|
||||
}
|
||||
m.BoxType = bf.ReadUint8()
|
||||
m.BoxIndex = bf.ReadUint8()
|
||||
_ = bf.ReadUint16()
|
||||
bf.ReadUint8() // Zeroed
|
||||
bf.ReadUint8() // Zeroed
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
type MsgMhfOperateWarehouse struct {
|
||||
AckHandle uint32
|
||||
Operation uint8
|
||||
BoxType string
|
||||
BoxType uint8
|
||||
BoxIndex uint8
|
||||
Name string
|
||||
}
|
||||
@@ -27,17 +27,13 @@ func (m *MsgMhfOperateWarehouse) Opcode() network.PacketID {
|
||||
func (m *MsgMhfOperateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Operation = bf.ReadUint8()
|
||||
boxType := bf.ReadUint8()
|
||||
switch boxType {
|
||||
case 0:
|
||||
m.BoxType = "item"
|
||||
case 1:
|
||||
m.BoxType = "equip"
|
||||
}
|
||||
m.BoxType = bf.ReadUint8()
|
||||
m.BoxIndex = bf.ReadUint8()
|
||||
_ = bf.ReadUint8() // lenName
|
||||
_ = bf.ReadUint16() // Unk
|
||||
m.Name = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
|
||||
lenName := bf.ReadUint8()
|
||||
bf.ReadUint16() // Zeroed
|
||||
if lenName > 0 {
|
||||
m.Name = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,24 +2,18 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"erupe-ce/common/mhfitem"
|
||||
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/clientctx"
|
||||
)
|
||||
|
||||
type Item struct {
|
||||
Unk0 uint32
|
||||
ItemID uint16
|
||||
Amount uint16
|
||||
Unk1 uint32
|
||||
}
|
||||
|
||||
// MsgMhfUpdateGuildItem represents the MSG_MHF_UPDATE_GUILD_ITEM
|
||||
type MsgMhfUpdateGuildItem struct {
|
||||
AckHandle uint32
|
||||
GuildID uint32
|
||||
Items []Item
|
||||
AckHandle uint32
|
||||
GuildID uint32
|
||||
UpdatedItems []mhfitem.MHFItemStack
|
||||
}
|
||||
|
||||
// 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 {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.GuildID = bf.ReadUint32()
|
||||
itemCount := int(bf.ReadUint16())
|
||||
changes := int(bf.ReadUint16())
|
||||
bf.ReadUint8() // Zeroed
|
||||
bf.ReadUint8() // Zeroed
|
||||
m.Items = make([]Item, itemCount)
|
||||
|
||||
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()
|
||||
for i := 0; i < changes; i++ {
|
||||
m.UpdatedItems = append(m.UpdatedItems, mhfitem.ReadWarehouseItem(bf))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"erupe-ce/common/mhfitem"
|
||||
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network"
|
||||
@@ -10,8 +11,8 @@ import (
|
||||
|
||||
// MsgMhfUpdateUnionItem represents the MSG_MHF_UPDATE_UNION_ITEM
|
||||
type MsgMhfUpdateUnionItem struct {
|
||||
AckHandle uint32
|
||||
Items []Item
|
||||
AckHandle uint32
|
||||
UpdatedItems []mhfitem.MHFItemStack
|
||||
}
|
||||
|
||||
// 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
|
||||
func (m *MsgMhfUpdateUnionItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
itemCount := int(bf.ReadUint16())
|
||||
changes := int(bf.ReadUint16())
|
||||
bf.ReadUint8() // Zeroed
|
||||
bf.ReadUint8() // Zeroed
|
||||
m.Items = make([]Item, itemCount)
|
||||
|
||||
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()
|
||||
for i := 0; i < changes; i++ {
|
||||
m.UpdatedItems = append(m.UpdatedItems, mhfitem.ReadWarehouseItem(bf))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,25 +3,18 @@ package mhfpacket
|
||||
import (
|
||||
"errors"
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/common/mhfitem"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/clientctx"
|
||||
)
|
||||
|
||||
type WarehouseStack struct {
|
||||
ID uint32
|
||||
Index uint16
|
||||
EquipType uint16
|
||||
ItemID uint16
|
||||
Quantity uint16
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// MsgMhfUpdateWarehouse represents the MSG_MHF_UPDATE_WAREHOUSE
|
||||
type MsgMhfUpdateWarehouse struct {
|
||||
AckHandle uint32
|
||||
BoxType string
|
||||
BoxIndex uint8
|
||||
Updates []WarehouseStack
|
||||
AckHandle uint32
|
||||
BoxType uint8
|
||||
BoxIndex uint8
|
||||
UpdatedItems []mhfitem.MHFItemStack
|
||||
UpdatedEquipment []mhfitem.MHFEquipment
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -32,35 +25,19 @@ func (m *MsgMhfUpdateWarehouse) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfUpdateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
boxType := bf.ReadUint8()
|
||||
switch boxType {
|
||||
case 0:
|
||||
m.BoxType = "item"
|
||||
case 1:
|
||||
m.BoxType = "equip"
|
||||
}
|
||||
m.BoxType = bf.ReadUint8()
|
||||
m.BoxIndex = bf.ReadUint8()
|
||||
changes := int(bf.ReadUint16())
|
||||
var stackUpdate WarehouseStack
|
||||
bf.ReadUint8() // Zeroed
|
||||
bf.ReadUint8() // Zeroed
|
||||
for i := 0; i < changes; i++ {
|
||||
switch boxType {
|
||||
switch m.BoxType {
|
||||
case 0:
|
||||
stackUpdate.ID = bf.ReadUint32()
|
||||
stackUpdate.Index = bf.ReadUint16()
|
||||
stackUpdate.ItemID = bf.ReadUint16()
|
||||
stackUpdate.Quantity = bf.ReadUint16()
|
||||
_ = bf.ReadUint16() // Unk
|
||||
m.Updates = append(m.Updates, stackUpdate)
|
||||
m.UpdatedItems = append(m.UpdatedItems, mhfitem.ReadWarehouseItem(bf))
|
||||
case 1:
|
||||
stackUpdate.ID = bf.ReadUint32()
|
||||
stackUpdate.Index = bf.ReadUint16()
|
||||
stackUpdate.EquipType = bf.ReadUint16()
|
||||
stackUpdate.ItemID = bf.ReadUint16()
|
||||
stackUpdate.Data = bf.ReadBytes(56)
|
||||
m.Updates = append(m.Updates, stackUpdate)
|
||||
m.UpdatedEquipment = append(m.UpdatedEquipment, mhfitem.ReadWarehouseEquipment(bf))
|
||||
}
|
||||
}
|
||||
_ = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
6
schemas/patch-schema/20-reset-warehouses.sql
Normal file
6
schemas/patch-schema/20-reset-warehouses.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
|
||||
UPDATE guilds SET item_box=NULL;
|
||||
UPDATE users SET item_box=NULL;
|
||||
|
||||
END;
|
||||
@@ -3,6 +3,7 @@ package channelserver
|
||||
import (
|
||||
"encoding/binary"
|
||||
"erupe-ce/common/mhfcourse"
|
||||
"erupe-ce/common/mhfitem"
|
||||
"erupe-ce/common/mhfmon"
|
||||
ps "erupe-ce/common/pascalstring"
|
||||
"erupe-ce/common/stringsupport"
|
||||
@@ -817,93 +818,33 @@ func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateUnionItem)
|
||||
var boxContents []byte
|
||||
bf := byteframe.NewByteFrame()
|
||||
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 err != nil {
|
||||
s.logger.Error("Failed to get shared item box contents from db", zap.Error(err))
|
||||
bf.WriteBytes(make([]byte, 4))
|
||||
} else {
|
||||
if len(boxContents) == 0 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
func userGetItems(s *Session) []mhfitem.MHFItemStack {
|
||||
var data []byte
|
||||
var items []mhfitem.MHFItemStack
|
||||
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)
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
box.ReadUint16() // Unused
|
||||
for i := 0; i < int(numStacks); i++ {
|
||||
items = append(items, mhfitem.ReadWarehouseItem(box))
|
||||
}
|
||||
}
|
||||
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())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem)
|
||||
// Get item cache from DB
|
||||
var boxContents []byte
|
||||
var oldItems []Item
|
||||
|
||||
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 err != nil {
|
||||
s.logger.Error("Failed to get shared item box contents from db", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete empty item stacks
|
||||
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]
|
||||
}
|
||||
}
|
||||
|
||||
// Create new item cache
|
||||
bf := byteframe.NewByteFrame()
|
||||
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))
|
||||
}
|
||||
newStacks := mhfitem.DiffItemStacks(userGetItems(s), pkt.UpdatedItems)
|
||||
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(newStacks), s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -937,19 +878,19 @@ func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfExchangeWeeklyStamp)
|
||||
var total, redeemed uint16
|
||||
var tktStack mhfpacket.WarehouseStack
|
||||
var tktStack mhfitem.MHFItemStack
|
||||
if pkt.Unk1 == 0xA { // Yearly Sub Ex
|
||||
s.server.db.QueryRow("UPDATE stamps SET hl_total=hl_total-48, hl_redeemed=hl_redeemed-48 WHERE character_id=$1 RETURNING hl_total, hl_redeemed", s.charID).Scan(&total, &redeemed)
|
||||
tktStack = mhfpacket.WarehouseStack{ItemID: 0x08A2, Quantity: 1}
|
||||
tktStack = mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: 2210}, Quantity: 1}
|
||||
} else {
|
||||
s.server.db.QueryRow(fmt.Sprintf("UPDATE stamps SET %s_redeemed=%s_redeemed+8 WHERE character_id=$1 RETURNING %s_total, %s_redeemed", pkt.StampType, pkt.StampType, pkt.StampType, pkt.StampType), s.charID).Scan(&total, &redeemed)
|
||||
if pkt.StampType == "hl" {
|
||||
tktStack = mhfpacket.WarehouseStack{ItemID: 0x065E, Quantity: 5}
|
||||
tktStack = mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: 1630}, Quantity: 5}
|
||||
} else {
|
||||
tktStack = mhfpacket.WarehouseStack{ItemID: 0x065F, Quantity: 5}
|
||||
tktStack = mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: 1631}, Quantity: 5}
|
||||
}
|
||||
}
|
||||
addWarehouseGift(s, "item", tktStack)
|
||||
addWarehouseItem(s, tktStack)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(total)
|
||||
bf.WriteUint16(redeemed)
|
||||
@@ -1120,13 +1061,13 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(pkt.Reward2)
|
||||
bf.WriteUint16(pkt.Item2)
|
||||
bf.WriteUint16(pkt.Quantity2)
|
||||
addWarehouseGift(s, "item", mhfpacket.WarehouseStack{ItemID: pkt.Item2, Quantity: pkt.Quantity2})
|
||||
addWarehouseItem(s, mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: pkt.Item2}, Quantity: pkt.Quantity2})
|
||||
} else if stamps%15 == 0 {
|
||||
bf.WriteUint16(1)
|
||||
bf.WriteUint16(pkt.Reward1)
|
||||
bf.WriteUint16(pkt.Item1)
|
||||
bf.WriteUint16(pkt.Quantity1)
|
||||
addWarehouseGift(s, "item", mhfpacket.WarehouseStack{ItemID: pkt.Item1, Quantity: pkt.Quantity1})
|
||||
addWarehouseItem(s, mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: pkt.Item1}, Quantity: pkt.Quantity1})
|
||||
} else {
|
||||
bf.WriteBytes(make([]byte, 8))
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
m := binpacket.MsgBinChat{
|
||||
Type: BinaryMessageTypeChat,
|
||||
Flags: 4,
|
||||
Message: fmt.Sprintf(`%d`, token.RNG().Intn(100)+1),
|
||||
Message: fmt.Sprintf(`%d`, token.RNG.Intn(100)+1),
|
||||
SenderName: author,
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
@@ -101,8 +101,7 @@ func generateFeatureWeapons(count int) activeFeature {
|
||||
nums := make([]int, 0)
|
||||
var result int
|
||||
for len(nums) < count {
|
||||
rng := token.RNG()
|
||||
num := rng.Intn(_max)
|
||||
num := token.RNG.Intn(_max)
|
||||
exist := false
|
||||
for _, v := range nums {
|
||||
if v == num {
|
||||
|
||||
@@ -455,7 +455,7 @@ func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
team := uint32(token.RNG().Intn(2))
|
||||
team := uint32(token.RNG.Intn(2))
|
||||
switch team {
|
||||
case 0:
|
||||
s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID)
|
||||
|
||||
@@ -3,9 +3,9 @@ package channelserver
|
||||
import (
|
||||
"database/sql"
|
||||
"database/sql/driver"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"erupe-ce/common/mhfitem"
|
||||
_config "erupe-ce/config"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -1554,100 +1554,34 @@ func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildItem)
|
||||
var boxContents []byte
|
||||
bf := byteframe.NewByteFrame()
|
||||
err := s.server.db.QueryRow("SELECT item_box FROM guilds WHERE id = $1", pkt.GuildID).Scan(&boxContents)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild item box contents from db", zap.Error(err))
|
||||
bf.WriteBytes(make([]byte, 4))
|
||||
} else {
|
||||
if len(boxContents) == 0 {
|
||||
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)
|
||||
}
|
||||
}
|
||||
func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack {
|
||||
var data []byte
|
||||
var items []mhfitem.MHFItemStack
|
||||
s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
box.ReadUint16() // Unused
|
||||
for i := 0; i < int(numStacks); i++ {
|
||||
items = append(items, mhfitem.ReadWarehouseItem(box))
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
return items
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
ItemId uint16
|
||||
Amount uint16
|
||||
func handleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildItem)
|
||||
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) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateGuildItem)
|
||||
|
||||
// Get item cache from DB
|
||||
var boxContents []byte
|
||||
var oldItems []Item
|
||||
err := s.server.db.QueryRow("SELECT item_box FROM guilds WHERE id = $1", pkt.GuildID).Scan(&boxContents)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild item box contents from db", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete empty item stacks
|
||||
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]
|
||||
}
|
||||
}
|
||||
|
||||
// Create new item cache
|
||||
bf := byteframe.NewByteFrame()
|
||||
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 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})
|
||||
newStacks := mhfitem.DiffItemStacks(guildGetItems(s, pkt.GuildID), pkt.UpdatedItems)
|
||||
s.server.db.Exec(`UPDATE guilds SET item_box=$1 WHERE id=$2`, mhfitem.SerializeWarehouseItems(newStacks), pkt.GuildID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
@@ -2,8 +2,10 @@ package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/common/mhfitem"
|
||||
ps "erupe-ce/common/pascalstring"
|
||||
"erupe-ce/common/stringsupport"
|
||||
"erupe-ce/common/token"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"fmt"
|
||||
@@ -406,7 +408,12 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 1:
|
||||
bf.WriteUint8(0)
|
||||
case 2:
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET %s%dname=$1 WHERE character_id=$2", pkt.BoxType, pkt.BoxIndex), pkt.Name, s.charID)
|
||||
switch pkt.BoxType {
|
||||
case 0:
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET item%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID)
|
||||
case 1:
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET equip%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID)
|
||||
}
|
||||
case 3:
|
||||
bf.WriteUint32(0) // Usage renewal time, >1 = disabled
|
||||
bf.WriteUint16(10000) // Usages
|
||||
@@ -424,81 +431,63 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func addWarehouseGift(s *Session, boxType string, giftStack mhfpacket.WarehouseStack) {
|
||||
giftBox := getWarehouseBox(s, boxType, 10)
|
||||
if boxType == "item" {
|
||||
exists := false
|
||||
for i, stack := range giftBox {
|
||||
if stack.ItemID == giftStack.ItemID {
|
||||
exists = true
|
||||
giftBox[i].Quantity += giftStack.Quantity
|
||||
break
|
||||
}
|
||||
}
|
||||
if exists == false {
|
||||
giftBox = append(giftBox, giftStack)
|
||||
}
|
||||
} else {
|
||||
giftBox = append(giftBox, giftStack)
|
||||
}
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET %s10=$1 WHERE character_id=$2", boxType), boxToBytes(giftBox, boxType), s.charID)
|
||||
func addWarehouseItem(s *Session, item mhfitem.MHFItemStack) {
|
||||
giftBox := warehouseGetItems(s, 10)
|
||||
item.WarehouseID = token.RNG.Uint32()
|
||||
giftBox = append(giftBox, item)
|
||||
s.server.db.Exec("UPDATE warehouse SET item10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseItems(giftBox), s.charID)
|
||||
}
|
||||
|
||||
func getWarehouseBox(s *Session, boxType string, boxIndex uint8) []mhfpacket.WarehouseStack {
|
||||
func addWarehouseEquipment(s *Session, equipment mhfitem.MHFEquipment) {
|
||||
giftBox := warehouseGetEquipment(s, 10)
|
||||
equipment.WarehouseID = token.RNG.Uint32()
|
||||
giftBox = append(giftBox, equipment)
|
||||
s.server.db.Exec("UPDATE warehouse SET equip10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseEquipment(giftBox), s.charID)
|
||||
}
|
||||
|
||||
func warehouseGetItems(s *Session, index uint8) []mhfitem.MHFItemStack {
|
||||
var data []byte
|
||||
s.server.db.QueryRow(fmt.Sprintf("SELECT %s%d FROM warehouse WHERE character_id=$1", boxType, boxIndex), s.charID).Scan(&data)
|
||||
var items []mhfitem.MHFItemStack
|
||||
s.server.db.QueryRow(fmt.Sprintf(`SELECT item%d FROM warehouse WHERE character_id=$1`, index), s.charID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
stacks := make([]mhfpacket.WarehouseStack, numStacks)
|
||||
box.ReadUint16() // Unused
|
||||
for i := 0; i < int(numStacks); i++ {
|
||||
if boxType == "item" {
|
||||
stacks[i].ID = box.ReadUint32()
|
||||
stacks[i].Index = box.ReadUint16()
|
||||
stacks[i].ItemID = box.ReadUint16()
|
||||
stacks[i].Quantity = box.ReadUint16()
|
||||
box.ReadUint16()
|
||||
} else {
|
||||
stacks[i].ID = box.ReadUint32()
|
||||
stacks[i].Index = box.ReadUint16()
|
||||
stacks[i].EquipType = box.ReadUint16()
|
||||
stacks[i].ItemID = box.ReadUint16()
|
||||
stacks[i].Data = box.ReadBytes(56)
|
||||
}
|
||||
items = append(items, mhfitem.ReadWarehouseItem(box))
|
||||
}
|
||||
return stacks
|
||||
} else {
|
||||
return make([]mhfpacket.WarehouseStack, 0)
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func boxToBytes(stacks []mhfpacket.WarehouseStack, boxType string) []byte {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(uint16(len(stacks)))
|
||||
for i, stack := range stacks {
|
||||
if boxType == "item" {
|
||||
bf.WriteUint32(stack.ID)
|
||||
bf.WriteUint16(uint16(i + 1))
|
||||
bf.WriteUint16(stack.ItemID)
|
||||
bf.WriteUint16(stack.Quantity)
|
||||
bf.WriteUint16(0)
|
||||
} else {
|
||||
bf.WriteUint32(stack.ID)
|
||||
bf.WriteUint16(uint16(i + 1))
|
||||
bf.WriteUint16(stack.EquipType)
|
||||
bf.WriteUint16(stack.ItemID)
|
||||
bf.WriteBytes(stack.Data)
|
||||
func warehouseGetEquipment(s *Session, index uint8) []mhfitem.MHFEquipment {
|
||||
var data []byte
|
||||
var equipment []mhfitem.MHFEquipment
|
||||
s.server.db.QueryRow(fmt.Sprintf(`SELECT equip%d FROM warehouse WHERE character_id=$1`, index), s.charID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
box.ReadUint16() // Unused
|
||||
for i := 0; i < int(numStacks); i++ {
|
||||
equipment = append(equipment, mhfitem.ReadWarehouseEquipment(box))
|
||||
}
|
||||
}
|
||||
bf.WriteUint16(0)
|
||||
return bf.Data()
|
||||
return equipment
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateWarehouse)
|
||||
box := getWarehouseBox(s, pkt.BoxType, pkt.BoxIndex)
|
||||
if len(box) > 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, boxToBytes(box, pkt.BoxType))
|
||||
bf := byteframe.NewByteFrame()
|
||||
switch pkt.BoxType {
|
||||
case 0:
|
||||
items := warehouseGetItems(s, pkt.BoxIndex)
|
||||
bf.WriteBytes(mhfitem.SerializeWarehouseItems(items))
|
||||
case 1:
|
||||
equipment := warehouseGetEquipment(s, pkt.BoxIndex)
|
||||
bf.WriteBytes(mhfitem.SerializeWarehouseEquipment(equipment))
|
||||
}
|
||||
if bf.Index() > 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
@@ -506,49 +495,34 @@ func handleMsgMhfEnumerateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfUpdateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateWarehouse)
|
||||
box := getWarehouseBox(s, pkt.BoxType, pkt.BoxIndex)
|
||||
// Update existing stacks
|
||||
var newStacks []mhfpacket.WarehouseStack
|
||||
for _, update := range pkt.Updates {
|
||||
exists := false
|
||||
if pkt.BoxType == "item" {
|
||||
for i, stack := range box {
|
||||
if stack.Index == update.Index {
|
||||
switch pkt.BoxType {
|
||||
case 0:
|
||||
newStacks := mhfitem.DiffItemStacks(warehouseGetItems(s, pkt.BoxIndex), pkt.UpdatedItems)
|
||||
s.server.db.Exec(fmt.Sprintf(`UPDATE warehouse SET item%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseItems(newStacks), s.charID)
|
||||
case 1:
|
||||
var fEquip []mhfitem.MHFEquipment
|
||||
oEquips := warehouseGetEquipment(s, pkt.BoxIndex)
|
||||
for _, uEquip := range pkt.UpdatedEquipment {
|
||||
exists := false
|
||||
for i := range oEquips {
|
||||
if oEquips[i].WarehouseID == uEquip.WarehouseID {
|
||||
exists = true
|
||||
box[i].Quantity = update.Quantity
|
||||
// Will set removed items to 0
|
||||
oEquips[i].ItemID = uEquip.ItemID
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i, stack := range box {
|
||||
if stack.Index == update.Index {
|
||||
exists = true
|
||||
box[i].ItemID = update.ItemID
|
||||
break
|
||||
}
|
||||
if !exists {
|
||||
uEquip.WarehouseID = token.RNG.Uint32()
|
||||
fEquip = append(fEquip, uEquip)
|
||||
}
|
||||
}
|
||||
if exists == false {
|
||||
newStacks = append(newStacks, update)
|
||||
}
|
||||
}
|
||||
// Append new stacks
|
||||
for _, stack := range newStacks {
|
||||
box = append(box, stack)
|
||||
}
|
||||
// Slice empty stacks
|
||||
var cleanedBox []mhfpacket.WarehouseStack
|
||||
for _, stack := range box {
|
||||
if pkt.BoxType == "item" {
|
||||
if stack.Quantity > 0 {
|
||||
cleanedBox = append(cleanedBox, stack)
|
||||
}
|
||||
} else {
|
||||
if stack.ItemID != 0 {
|
||||
cleanedBox = append(cleanedBox, stack)
|
||||
for _, oEquip := range oEquips {
|
||||
if oEquip.ItemID > 0 {
|
||||
fEquip = append(fEquip, oEquip)
|
||||
}
|
||||
}
|
||||
s.server.db.Exec(fmt.Sprintf(`UPDATE warehouse SET equip%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseEquipment(fEquip), s.charID)
|
||||
}
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET %s%d=$1 WHERE character_id=$2", pkt.BoxType, pkt.BoxIndex), boxToBytes(cleanedBox, pkt.BoxType), s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user