Files
Erupe/server/channelserver/handlers_guild_tresure.go
Houmgaor d2a9b0ba5c refactor(channelserver): migrate remaining guild SQL into GuildRepository
Move ~39 inline SQL queries from six handler files into repo_guild.go,
consolidating all guild-related DB access (posts, alliances, adventures,
treasure hunts, meals, kill logs, scouts) behind GuildRepository methods.

Handler files now contain only packet serialization, business logic, and
ACK responses with no direct database calls.
2026-02-20 22:14:48 +01:00

157 lines
4.8 KiB
Go

package channelserver
import (
"erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport"
"erupe-ce/network/mhfpacket"
"time"
"go.uber.org/zap"
)
// TreasureHunt represents a guild treasure hunt entry.
type TreasureHunt struct {
HuntID uint32 `db:"id"`
HostID uint32 `db:"host_id"`
Destination uint32 `db:"destination"`
Level uint32 `db:"level"`
Start time.Time `db:"start"`
Acquired bool `db:"acquired"`
Collected bool `db:"collected"`
HuntData []byte `db:"hunt_data"`
Hunters uint32 `db:"hunters"`
Claimed bool `db:"claimed"`
}
func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildTresure)
guild, err := s.server.guildRepo.GetByCharID(s.charID)
if err != nil || guild == nil {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
var hunts []TreasureHunt
switch pkt.MaxHunts {
case 1:
hunt, err := s.server.guildRepo.GetPendingHunt(s.charID)
if err == nil && hunt != nil {
hunts = append(hunts, *hunt)
}
case 30:
guildHunts, err := s.server.guildRepo.ListGuildHunts(guild.ID, s.charID)
if err != nil {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return
}
for _, hunt := range guildHunts {
if hunt.Start.Add(time.Second * time.Duration(s.server.erupeConfig.GameplayOptions.TreasureHuntExpiry)).After(TimeAdjusted()) {
hunts = append(hunts, *hunt)
}
}
if len(hunts) > 30 {
hunts = hunts[:30]
}
}
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(len(hunts)))
bf.WriteUint16(uint16(len(hunts)))
for _, h := range hunts {
bf.WriteUint32(h.HuntID)
bf.WriteUint32(h.Destination)
bf.WriteUint32(h.Level)
bf.WriteUint32(h.Hunters)
bf.WriteUint32(uint32(h.Start.Unix()))
bf.WriteBool(h.Collected)
bf.WriteBool(h.Claimed)
bf.WriteBytes(h.HuntData)
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfRegistGuildTresure)
bf := byteframe.NewByteFrameFromBytes(pkt.Data)
huntData := byteframe.NewByteFrame()
guild, err := s.server.guildRepo.GetByCharID(s.charID)
if err != nil || guild == nil {
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
return
}
guildCats := getGuildAirouList(s)
destination := bf.ReadUint32()
level := bf.ReadUint32()
huntData.WriteUint32(s.charID)
huntData.WriteBytes(stringsupport.PaddedString(s.Name, 18, true))
catsUsed := ""
for i := 0; i < 5; i++ {
catID := bf.ReadUint32()
huntData.WriteUint32(catID)
if catID > 0 {
catsUsed = stringsupport.CSVAdd(catsUsed, int(catID))
for _, cat := range guildCats {
if cat.ID == catID {
huntData.WriteBytes(cat.Name)
break
}
}
huntData.WriteBytes(bf.ReadBytes(9))
}
}
if err := s.server.guildRepo.CreateHunt(guild.ID, s.charID, destination, level, huntData.Data(), catsUsed); err != nil {
s.logger.Error("Failed to register guild treasure hunt", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresure)
if err := s.server.guildRepo.AcquireHunt(pkt.HuntID); err != nil {
s.logger.Error("Failed to acquire guild treasure hunt", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfOperateGuildTresureReport)
switch pkt.State {
case 0: // Report registration
if err := s.server.guildRepo.RegisterHuntReport(pkt.HuntID, s.charID); err != nil {
s.logger.Error("Failed to register treasure hunt report", zap.Error(err))
}
case 1: // Collected by hunter
if err := s.server.guildRepo.CollectHunt(pkt.HuntID); err != nil {
s.logger.Error("Failed to collect treasure hunt", zap.Error(err))
}
case 2: // Claim treasure
if err := s.server.guildRepo.ClaimHuntReward(pkt.HuntID, s.charID); err != nil {
s.logger.Error("Failed to claim treasure hunt reward", zap.Error(err))
}
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
// TreasureSouvenir represents a guild treasure souvenir entry.
type TreasureSouvenir struct {
Destination uint32
Quantity uint32
}
func handleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetGuildTresureSouvenir)
bf := byteframe.NewByteFrame()
bf.WriteUint32(0)
souvenirs := []TreasureSouvenir{}
bf.WriteUint16(uint16(len(souvenirs)))
for _, souvenir := range souvenirs {
bf.WriteUint32(souvenir.Destination)
bf.WriteUint32(souvenir.Quantity)
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfAcquireGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresureSouvenir)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}