mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-02-04 09:15:08 +01:00
implement guild treasure hunting
This commit is contained in:
@@ -145,6 +145,14 @@ func CSVContains(csv string, v int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func CSVLength(csv string) int {
|
||||
if csv == "" {
|
||||
return 0
|
||||
}
|
||||
s := strings.Split(csv, ",")
|
||||
return len(s)
|
||||
}
|
||||
|
||||
// ConvertUTF8ToShiftJIS converts a UTF8 string to a Shift-JIS []byte.
|
||||
func ConvertUTF8ToShiftJIS(text string) ([]byte, error) {
|
||||
r := bytes.NewBuffer([]byte(text))
|
||||
|
||||
@@ -37,4 +37,19 @@ CREATE TABLE IF NOT EXISTS public.guild_meals
|
||||
expires int NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.guild_hunts
|
||||
(
|
||||
id serial NOT NULL PRIMARY KEY,
|
||||
guild_id int NOT NULL,
|
||||
host_id int NOT NULL,
|
||||
destination int NOT NULL,
|
||||
level int NOT NULL,
|
||||
return int NOT NULL,
|
||||
acquired bool NOT NULL DEFAULT false,
|
||||
claimed bool NOT NULL DEFAULT false,
|
||||
hunters text NOT NULL DEFAULT '',
|
||||
treasure text NOT NULL DEFAULT '',
|
||||
hunt_data bytea NOT NULL
|
||||
);
|
||||
|
||||
END;
|
||||
@@ -1,18 +1,18 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"errors"
|
||||
|
||||
"erupe-ce/network/clientctx"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/clientctx"
|
||||
)
|
||||
|
||||
// MsgMhfAcquireGuildTresure represents the MSG_MHF_ACQUIRE_GUILD_TRESURE
|
||||
type MsgMhfAcquireGuildTresure struct {
|
||||
AckHandle uint32
|
||||
Unk0 uint32
|
||||
Unk1 uint8
|
||||
AckHandle uint32
|
||||
HuntID uint32
|
||||
Unk uint8
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -22,10 +22,10 @@ func (m *MsgMhfAcquireGuildTresure) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfAcquireGuildTresure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
m.Unk1 = bf.ReadUint8()
|
||||
return nil
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.HuntID = bf.ReadUint32()
|
||||
m.Unk = bf.ReadUint8()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"errors"
|
||||
|
||||
"erupe-ce/network/clientctx"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/clientctx"
|
||||
)
|
||||
|
||||
// MsgMhfOperateGuildTresureReport represents the MSG_MHF_OPERATE_GUILD_TRESURE_REPORT
|
||||
type MsgMhfOperateGuildTresureReport struct{
|
||||
AckHandle uint32
|
||||
HuntID uint32
|
||||
Unk uint16
|
||||
type MsgMhfOperateGuildTresureReport struct {
|
||||
AckHandle uint32
|
||||
HuntID uint32
|
||||
State uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -22,10 +22,10 @@ func (m *MsgMhfOperateGuildTresureReport) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfOperateGuildTresureReport) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.HuntID = bf.ReadUint32()
|
||||
m.Unk = bf.ReadUint16()
|
||||
return nil
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.HuntID = bf.ReadUint32()
|
||||
m.State = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"errors"
|
||||
|
||||
"erupe-ce/network/clientctx"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/clientctx"
|
||||
)
|
||||
|
||||
// MsgMhfRegistGuildTresure represents the MSG_MHF_REGIST_GUILD_TRESURE
|
||||
type MsgMhfRegistGuildTresure struct {
|
||||
AckHandle uint32
|
||||
Data []byte
|
||||
AckHandle uint32
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -21,10 +21,10 @@ func (m *MsgMhfRegistGuildTresure) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfRegistGuildTresure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Data = bf.ReadBytes(uint(bf.ReadUint16()))
|
||||
_ = bf.ReadUint32()
|
||||
return nil
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Data = bf.ReadBytes(uint(bf.ReadUint16()))
|
||||
_ = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -239,6 +239,7 @@ func logoutPlayer(s *Session) {
|
||||
|
||||
removeSessionFromSemaphore(s)
|
||||
removeSessionFromStage(s)
|
||||
treasureHuntUnregister(s)
|
||||
|
||||
saveData, err := GetCharacterSaveData(s, s.charID)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,25 +1,166 @@
|
||||
package channelserver
|
||||
|
||||
import "erupe-ce/network/mhfpacket"
|
||||
import (
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/common/stringsupport"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
)
|
||||
|
||||
type TreasureHunt struct {
|
||||
HuntID uint32 `db:"id"`
|
||||
HostID uint32 `db:"host_id"`
|
||||
Destination uint32 `db:"destination"`
|
||||
Level uint32 `db:"level"`
|
||||
Return uint32 `db:"return"`
|
||||
Acquired bool `db:"acquired"`
|
||||
Claimed bool `db:"claimed"`
|
||||
Hunters string `db:"hunters"`
|
||||
Treasure string `db:"treasure"`
|
||||
HuntData []byte `db:"hunt_data"`
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildTresure)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
hunts := 0
|
||||
rows, _ := s.server.db.Queryx("SELECT id, host_id, destination, level, return, acquired, claimed, hunters, treasure, hunt_data FROM guild_hunts WHERE guild_id=$1", guild.ID)
|
||||
for rows.Next() {
|
||||
hunt := &TreasureHunt{}
|
||||
err = rows.StructScan(&hunt)
|
||||
// Remove self from other hunter count
|
||||
hunt.Hunters = stringsupport.CSVRemove(hunt.Hunters, int(s.charID))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if pkt.MaxHunts == 1 {
|
||||
if hunt.HostID != s.charID || hunt.Acquired {
|
||||
continue
|
||||
}
|
||||
hunts++
|
||||
bf.WriteUint32(hunt.HuntID)
|
||||
bf.WriteUint32(hunt.Destination)
|
||||
bf.WriteUint32(hunt.Level)
|
||||
bf.WriteUint32(uint32(stringsupport.CSVLength(hunt.Hunters)))
|
||||
bf.WriteUint32(hunt.Return)
|
||||
bf.WriteBool(false)
|
||||
bf.WriteBool(false)
|
||||
bf.WriteBytes(hunt.HuntData)
|
||||
break
|
||||
} else if pkt.MaxHunts == 30 && hunt.Acquired && hunt.Level == 2 {
|
||||
hunts++
|
||||
bf.WriteUint32(hunt.HuntID)
|
||||
bf.WriteUint32(hunt.Destination)
|
||||
bf.WriteUint32(hunt.Level)
|
||||
bf.WriteUint32(uint32(stringsupport.CSVLength(hunt.Hunters)))
|
||||
bf.WriteUint32(hunt.Return)
|
||||
bf.WriteBool(hunt.Claimed)
|
||||
bf.WriteBool(stringsupport.CSVContains(hunt.Treasure, int(s.charID)))
|
||||
bf.WriteBytes(hunt.HuntData)
|
||||
}
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint16(uint16(hunts))
|
||||
resp.WriteUint16(uint16(hunts))
|
||||
resp.WriteBytes(bf.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildTresure)
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt.Data)
|
||||
huntData := byteframe.NewByteFrame()
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
guildCats := getGuildAirouList(s)
|
||||
destination := bf.ReadUint32()
|
||||
level := bf.ReadUint32()
|
||||
huntData.WriteUint32(s.charID)
|
||||
huntData.WriteBytes(stringsupport.PaddedString(s.Name, 18, true))
|
||||
for i := 0; i < 5; i++ {
|
||||
catID := bf.ReadUint32()
|
||||
huntData.WriteUint32(catID)
|
||||
if catID > 0 {
|
||||
for _, cat := range guildCats {
|
||||
if cat.CatID == catID {
|
||||
huntData.WriteBytes(cat.CatName)
|
||||
break
|
||||
}
|
||||
}
|
||||
huntData.WriteBytes(bf.ReadBytes(9))
|
||||
}
|
||||
}
|
||||
_, err = s.server.db.Exec("INSERT INTO guild_hunts (guild_id, host_id, destination, level, return, hunt_data) VALUES ($1, $2, $3, $4, $5, $6)",
|
||||
guild.ID, s.charID, destination, level, Time_Current_Adjusted().Unix(), huntData.Data())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresure)
|
||||
_, err := s.server.db.Exec("UPDATE guild_hunts SET acquired=true WHERE id=$1", pkt.HuntID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func treasureHuntUnregister(s *Session) {
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var huntID int
|
||||
var hunters string
|
||||
rows, _ := s.server.db.Queryx("SELECT id, hunters FROM guild_hunts WHERE guild_id=$1", guild.ID)
|
||||
for rows.Next() {
|
||||
rows.Scan(&huntID, &hunters)
|
||||
hunters = stringsupport.CSVRemove(hunters, int(s.charID))
|
||||
_, err = s.server.db.Exec("UPDATE guild_hunts SET hunters=$1 WHERE id=$2", hunters, huntID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperateGuildTresureReport)
|
||||
var csv string
|
||||
if pkt.State == 0 { // Report registration
|
||||
// Unregister from all other hunts
|
||||
treasureHuntUnregister(s)
|
||||
if pkt.HuntID != 0 {
|
||||
// Register to selected hunt
|
||||
err := s.server.db.QueryRow("SELECT hunters FROM guild_hunts WHERE id=$1", pkt.HuntID).Scan(&csv)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
csv = stringsupport.CSVAdd(csv, int(s.charID))
|
||||
_, err = s.server.db.Exec("UPDATE guild_hunts SET hunters=$1 WHERE id=$2", csv, pkt.HuntID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
} else if pkt.State == 1 { // Collected by hunter
|
||||
s.server.db.Exec("UPDATE guild_hunts SET hunters='', claimed=true WHERE id=$1", pkt.HuntID)
|
||||
} else if pkt.State == 2 { // Claim treasure
|
||||
err := s.server.db.QueryRow("SELECT treasure FROM guild_hunts WHERE id=$1", pkt.HuntID).Scan(&csv)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
csv = stringsupport.CSVAdd(csv, int(s.charID))
|
||||
_, err = s.server.db.Exec("UPDATE guild_hunts SET treasure=$1 WHERE id=$2", csv, pkt.HuntID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user