mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 07:25:03 +01:00
implement persistent house data
This commit is contained in:
19
patch-schema/persistent-house.sql
Normal file
19
patch-schema/persistent-house.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.user_binary
|
||||||
|
(
|
||||||
|
id serial NOT NULL PRIMARY KEY,
|
||||||
|
type2 bytea,
|
||||||
|
type3 bytea,
|
||||||
|
house_tier bytea,
|
||||||
|
house_state int,
|
||||||
|
house_password text,
|
||||||
|
house_data bytea,
|
||||||
|
house_furniture bytea,
|
||||||
|
bookshelf bytea,
|
||||||
|
gallery bytea,
|
||||||
|
tore bytea,
|
||||||
|
garden bytea
|
||||||
|
);
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -94,6 +94,9 @@ func (save *CharacterSaveData) Save(s *Session) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID))
|
s.logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.server.db.Exec(`UPDATE user_binary SET house_tier=$1, house_data=$2, bookshelf=$3, gallery=$4, tore=$5, garden=$6 WHERE id=$7
|
||||||
|
`, save.HouseTier, save.HouseData, save.BookshelfData, save.GalleryData, save.ToreData, save.GardenData, s.charID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (save *CharacterSaveData) Compress() error {
|
func (save *CharacterSaveData) Compress() error {
|
||||||
|
|||||||
@@ -38,24 +38,26 @@ FROM warehouse
|
|||||||
|
|
||||||
func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfUpdateInterior)
|
pkt := p.(*mhfpacket.MsgMhfUpdateInterior)
|
||||||
_, err := s.server.db.Exec("UPDATE characters SET house=$1 WHERE id=$2", pkt.InteriorData, s.charID)
|
s.server.db.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.charID)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
type HouseData struct {
|
type HouseData struct {
|
||||||
CharID uint32 `db:"id"`
|
CharID uint32 `db:"id"`
|
||||||
HRP uint16 `db:"hrp"`
|
HRP uint16 `db:"hrp"`
|
||||||
GR uint16 `db:"gr"`
|
GR uint16 `db:"gr"`
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
|
HouseState uint8 `db:"house_state"`
|
||||||
|
HousePassword string `db:"house_password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfEnumerateHouse)
|
pkt := p.(*mhfpacket.MsgMhfEnumerateHouse)
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
|
bf.WriteUint16(0)
|
||||||
var houses []HouseData
|
var houses []HouseData
|
||||||
|
houseQuery := `SELECT c.id, hrp, gr, name, COALESCE(ub.house_state, 2) as house_state, COALESCE(ub.house_password, '') as house_password
|
||||||
|
FROM characters c LEFT JOIN user_binary ub ON ub.id = c.id WHERE c.id=$1`
|
||||||
switch pkt.Method {
|
switch pkt.Method {
|
||||||
case 1:
|
case 1:
|
||||||
var friendsList string
|
var friendsList string
|
||||||
@@ -63,17 +65,15 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
cids := stringsupport.CSVElems(friendsList)
|
cids := stringsupport.CSVElems(friendsList)
|
||||||
for _, cid := range cids {
|
for _, cid := range cids {
|
||||||
house := HouseData{}
|
house := HouseData{}
|
||||||
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE id=$1", cid)
|
row := s.server.db.QueryRowx(houseQuery, cid)
|
||||||
err := row.StructScan(&house)
|
err := row.StructScan(&house)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
houses = append(houses, house)
|
houses = append(houses, house)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||||
if err != nil {
|
if err != nil || guild == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
guildMembers, err := GetGuildMembers(s, guild.ID, false)
|
guildMembers, err := GetGuildMembers(s, guild.ID, false)
|
||||||
@@ -82,58 +82,48 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
for _, member := range guildMembers {
|
for _, member := range guildMembers {
|
||||||
house := HouseData{}
|
house := HouseData{}
|
||||||
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE id=$1", member.CharID)
|
row := s.server.db.QueryRowx(houseQuery, member.CharID)
|
||||||
err := row.StructScan(&house)
|
err = row.StructScan(&house)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
houses = append(houses, house)
|
houses = append(houses, house)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
|
houseQuery = `SELECT c.id, hrp, gr, name, COALESCE(ub.house_state, 2) as house_state, COALESCE(ub.house_password, '') as house_password
|
||||||
|
FROM characters c LEFT JOIN user_binary ub ON ub.id = c.id WHERE name ILIKE $1`
|
||||||
house := HouseData{}
|
house := HouseData{}
|
||||||
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE name ILIKE $1", fmt.Sprintf(`%%%s%%`, pkt.Name))
|
rows, _ := s.server.db.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name))
|
||||||
err := row.StructScan(&house)
|
for rows.Next() {
|
||||||
if err != nil {
|
err := rows.StructScan(&house)
|
||||||
panic(err)
|
if err == nil {
|
||||||
} else {
|
houses = append(houses, house)
|
||||||
houses = append(houses, house)
|
}
|
||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
house := HouseData{}
|
house := HouseData{}
|
||||||
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE id=$1", pkt.CharID)
|
row := s.server.db.QueryRowx(houseQuery, pkt.CharID)
|
||||||
err := row.StructScan(&house)
|
err := row.StructScan(&house)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
panic(err)
|
|
||||||
} else {
|
|
||||||
houses = append(houses, house)
|
houses = append(houses, house)
|
||||||
}
|
}
|
||||||
case 5: // Recent visitors
|
case 5: // Recent visitors
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var exists int
|
|
||||||
for _, house := range houses {
|
for _, house := range houses {
|
||||||
for _, session := range s.server.sessions {
|
bf.WriteUint32(house.CharID)
|
||||||
if session.charID == house.CharID {
|
bf.WriteUint8(house.HouseState)
|
||||||
exists++
|
if len(house.HousePassword) > 0 {
|
||||||
bf.WriteUint32(house.CharID)
|
bf.WriteUint8(3)
|
||||||
bf.WriteUint8(session.myseries.state)
|
} else {
|
||||||
if len(session.myseries.password) > 0 {
|
bf.WriteUint8(0)
|
||||||
bf.WriteUint8(3)
|
|
||||||
} else {
|
|
||||||
bf.WriteUint8(0)
|
|
||||||
}
|
|
||||||
bf.WriteUint16(house.HRP)
|
|
||||||
bf.WriteUint16(house.GR)
|
|
||||||
ps.Uint8(bf, house.Name, true)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
bf.WriteUint16(house.HRP)
|
||||||
|
bf.WriteUint16(house.GR)
|
||||||
|
ps.Uint8(bf, house.Name, true)
|
||||||
}
|
}
|
||||||
resp := byteframe.NewByteFrame()
|
bf.Seek(0, 0)
|
||||||
resp.WriteUint16(uint16(exists))
|
bf.WriteUint16(uint16(len(houses)))
|
||||||
resp.WriteBytes(bf.Data())
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||||
@@ -143,8 +133,7 @@ func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
// 03 = open friends
|
// 03 = open friends
|
||||||
// 04 = open guild
|
// 04 = open guild
|
||||||
// 05 = open friends+guild
|
// 05 = open friends+guild
|
||||||
s.myseries.state = pkt.State
|
s.server.db.Exec(`UPDATE user_binary SET house_state=$1, house_password=$2 WHERE id=$3`, pkt.State, pkt.Password, s.charID)
|
||||||
s.myseries.password = pkt.Password
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,63 +141,41 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgMhfLoadHouse)
|
pkt := p.(*mhfpacket.MsgMhfLoadHouse)
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
if pkt.Destination != 9 && len(pkt.Password) > 0 && pkt.CheckPass {
|
if pkt.Destination != 9 && len(pkt.Password) > 0 && pkt.CheckPass {
|
||||||
for _, session := range s.server.sessions {
|
var password string
|
||||||
if session.charID == pkt.CharID && pkt.Password != session.myseries.password {
|
s.server.db.Select(&password, `SELECT house_password FROM user_binary WHERE id=$1`, pkt.CharID)
|
||||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
if pkt.Password != password {
|
||||||
return
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var furniture []byte
|
var houseTier, houseData, houseFurniture, bookshelf, gallery, tore, garden []byte
|
||||||
err := s.server.db.QueryRow("SELECT house FROM characters WHERE id=$1", pkt.CharID).Scan(&furniture)
|
s.server.db.QueryRow(`SELECT house_tier, house_data, house_furniture, bookshelf, gallery, tore, garden FROM user_binary WHERE id=$1
|
||||||
if err != nil {
|
`, pkt.CharID).Scan(&houseTier, &houseData, &houseFurniture, &bookshelf, &gallery, &tore, &garden)
|
||||||
panic(err)
|
if houseFurniture == nil {
|
||||||
}
|
houseFurniture = make([]byte, 20)
|
||||||
if furniture == nil {
|
|
||||||
furniture = make([]byte, 20)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch pkt.Destination {
|
switch pkt.Destination {
|
||||||
case 3: // Others house
|
case 3: // Others house
|
||||||
for _, session := range s.server.sessions {
|
bf.WriteBytes(houseTier)
|
||||||
if session.charID == pkt.CharID {
|
bf.WriteBytes(houseData)
|
||||||
bf.WriteBytes(session.myseries.houseTier)
|
bf.WriteBytes(make([]byte, 19)) // Padding?
|
||||||
bf.WriteBytes(session.myseries.houseData)
|
bf.WriteBytes(houseFurniture)
|
||||||
bf.WriteBytes(make([]byte, 19)) // Padding?
|
|
||||||
bf.WriteBytes(furniture)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 4: // Bookshelf
|
case 4: // Bookshelf
|
||||||
for _, session := range s.server.sessions {
|
bf.WriteBytes(bookshelf)
|
||||||
if session.charID == pkt.CharID {
|
|
||||||
bf.WriteBytes(session.myseries.bookshelfData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 5: // Gallery
|
case 5: // Gallery
|
||||||
for _, session := range s.server.sessions {
|
bf.WriteBytes(gallery)
|
||||||
if session.charID == pkt.CharID {
|
|
||||||
bf.WriteBytes(session.myseries.galleryData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 8: // Tore
|
case 8: // Tore
|
||||||
for _, session := range s.server.sessions {
|
bf.WriteBytes(tore)
|
||||||
if session.charID == pkt.CharID {
|
|
||||||
bf.WriteBytes(session.myseries.toreData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 9: // Own house
|
case 9: // Own house
|
||||||
bf.WriteBytes(furniture)
|
bf.WriteBytes(houseFurniture)
|
||||||
case 10: // Garden
|
case 10: // Garden
|
||||||
for _, session := range s.server.sessions {
|
bf.WriteBytes(garden)
|
||||||
if session.charID == pkt.CharID {
|
c, d := getGookData(s, pkt.CharID)
|
||||||
bf.WriteBytes(session.myseries.gardenData)
|
bf.WriteUint16(c)
|
||||||
c, d := getGookData(s, pkt.CharID)
|
bf.WriteUint16(0)
|
||||||
bf.WriteUint16(c)
|
bf.WriteBytes(d)
|
||||||
bf.WriteUint16(0)
|
|
||||||
bf.WriteBytes(d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if len(bf.Data()) == 0 {
|
if len(bf.Data()) == 0 {
|
||||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.server.userBinaryPartsLock.Unlock()
|
s.server.userBinaryPartsLock.Unlock()
|
||||||
|
|
||||||
var exists []byte
|
var exists []byte
|
||||||
err := s.server.db.QueryRow("SELECT type2 FROM user_binaries WHERE id=$1", s.charID).Scan(&exists)
|
err := s.server.db.QueryRow("SELECT type2 FROM user_binary WHERE id=$1", s.charID).Scan(&exists)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.server.db.Exec("INSERT INTO user_binaries (id) VALUES ($1)", s.charID)
|
s.server.db.Exec("INSERT INTO user_binary (id) VALUES ($1)", s.charID)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.server.db.Exec(fmt.Sprintf("UPDATE user_binaries SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.charID)
|
s.server.db.Exec(fmt.Sprintf("UPDATE user_binary SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.charID)
|
||||||
|
|
||||||
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
CharID: s.charID,
|
CharID: s.charID,
|
||||||
@@ -42,7 +42,7 @@ func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
// If we can't get the real data, try to get it from the database.
|
// If we can't get the real data, try to get it from the database.
|
||||||
if !ok {
|
if !ok {
|
||||||
err := s.server.db.QueryRow(fmt.Sprintf("SELECT type%d FROM user_binaries WHERE id=$1", pkt.BinaryType), pkt.CharID).Scan(&data)
|
err := s.server.db.QueryRow(fmt.Sprintf("SELECT type%d FROM user_binary WHERE id=$1", pkt.BinaryType), pkt.CharID).Scan(&data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user