fix(channelserver): handle bare Exec errors and filter expected ErrNoRows

138 bare db.Exec calls across 22 handler files silently dropped write
errors. Each is now wrapped with error check and zap logging.

4 QueryRow sites that legitimately return sql.ErrNoRows during normal
operation (new player mezfes, festa rankings, empty guild item box)
now filter it out to reduce log noise.
This commit is contained in:
Houmgaor
2026-02-17 23:33:44 +01:00
parent 88fc17e790
commit 47f7a1f636
22 changed files with 446 additions and 156 deletions

View File

@@ -303,7 +303,9 @@ func logoutPlayer(s *Session) {
if mhfcourse.CourseExists(30, s.courses) { if mhfcourse.CourseExists(30, s.courses) {
rpGained = timePlayed / 900 rpGained = timePlayed / 900
timePlayed = timePlayed % 900 timePlayed = timePlayed % 900
_, _ = s.server.db.Exec("UPDATE characters SET cafe_time=cafe_time+$1 WHERE id=$2", sessionTime, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET cafe_time=cafe_time+$1 WHERE id=$2", sessionTime, s.charID); err != nil {
s.logger.Error("Failed to update cafe time", zap.Error(err))
}
} else { } else {
rpGained = timePlayed / 1800 rpGained = timePlayed / 1800
timePlayed = timePlayed % 1800 timePlayed = timePlayed % 1800
@@ -329,8 +331,12 @@ func logoutPlayer(s *Session) {
} }
// Update time_played and guild treasure hunt // Update time_played and guild treasure hunt
_, _ = s.server.db.Exec("UPDATE characters SET time_played = $1 WHERE id = $2", timePlayed, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET time_played = $1 WHERE id = $2", timePlayed, s.charID); err != nil {
_, _ = s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE character_id=$1`, s.charID) s.logger.Error("Failed to update time played", zap.Error(err))
}
if _, err := s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE character_id=$1`, s.charID); err != nil {
s.logger.Error("Failed to clear treasure hunt", zap.Error(err))
}
} }
// NOW do cleanup (after save is complete) // NOW do cleanup (after save is complete)
@@ -449,7 +455,9 @@ func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {
for i := 0; i < 176; i++ { for i := 0; i < 176; i++ {
val = bf.ReadUint8() val = bf.ReadUint8()
if val > 0 && mhfmon.Monsters[i].Large { if val > 0 && mhfmon.Monsters[i].Large {
_, _ = s.server.db.Exec(`INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, $2, $3, $4)`, s.charID, i, val, TimeAdjusted()) if _, err := s.server.db.Exec(`INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, $2, $3, $4)`, s.charID, i, val, TimeAdjusted()); err != nil {
s.logger.Error("Failed to insert kill log", zap.Error(err))
}
} }
} }
} }
@@ -977,7 +985,9 @@ func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem) pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem)
newStacks := mhfitem.DiffItemStacks(userGetItems(s), pkt.UpdatedItems) 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) if _, 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(newStacks), s.charID); err != nil {
s.logger.Error("Failed to update union item box", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -990,13 +1000,19 @@ func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
err := s.server.db.QueryRow(fmt.Sprintf("SELECT %s_checked FROM stamps WHERE character_id=$1", pkt.StampType), s.charID).Scan(&lastCheck) err := s.server.db.QueryRow(fmt.Sprintf("SELECT %s_checked FROM stamps WHERE character_id=$1", pkt.StampType), s.charID).Scan(&lastCheck)
if err != nil { if err != nil {
lastCheck = TimeAdjusted() lastCheck = TimeAdjusted()
_, _ = s.server.db.Exec("INSERT INTO stamps (character_id, hl_checked, ex_checked) VALUES ($1, $2, $2)", s.charID, TimeAdjusted()) if _, err := s.server.db.Exec("INSERT INTO stamps (character_id, hl_checked, ex_checked) VALUES ($1, $2, $2)", s.charID, TimeAdjusted()); err != nil {
s.logger.Error("Failed to insert stamps record", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec(fmt.Sprintf(`UPDATE stamps SET %s_checked=$1 WHERE character_id=$2`, pkt.StampType), TimeAdjusted(), s.charID) if _, err := s.server.db.Exec(fmt.Sprintf(`UPDATE stamps SET %s_checked=$1 WHERE character_id=$2`, pkt.StampType), TimeAdjusted(), s.charID); err != nil {
s.logger.Error("Failed to update stamp check time", zap.Error(err))
}
} }
if lastCheck.Before(TimeWeekStart()) { if lastCheck.Before(TimeWeekStart()) {
_, _ = s.server.db.Exec(fmt.Sprintf("UPDATE stamps SET %s_total=%s_total+1 WHERE character_id=$1", pkt.StampType, pkt.StampType), s.charID) if _, err := s.server.db.Exec(fmt.Sprintf("UPDATE stamps SET %s_total=%s_total+1 WHERE character_id=$1", pkt.StampType, pkt.StampType), s.charID); err != nil {
s.logger.Error("Failed to increment stamp total", zap.Error(err))
}
updated = 1 updated = 1
} }
@@ -1043,7 +1059,9 @@ func getGoocooData(s *Session, cid uint32) [][]byte {
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
err := s.server.db.QueryRow(fmt.Sprintf("SELECT goocoo%d FROM goocoo WHERE id=$1", i), cid).Scan(&goocoo) err := s.server.db.QueryRow(fmt.Sprintf("SELECT goocoo%d FROM goocoo WHERE id=$1", i), cid).Scan(&goocoo)
if err != nil { if err != nil {
_, _ = s.server.db.Exec("INSERT INTO goocoo (id) VALUES ($1)", s.charID) if _, err := s.server.db.Exec("INSERT INTO goocoo (id) VALUES ($1)", s.charID); err != nil {
s.logger.Error("Failed to insert goocoo record", zap.Error(err))
}
return goocoos return goocoos
} }
if err == nil && goocoo != nil { if err == nil && goocoo != nil {
@@ -1069,7 +1087,9 @@ func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateGuacot) pkt := p.(*mhfpacket.MsgMhfUpdateGuacot)
for _, goocoo := range pkt.Goocoos { for _, goocoo := range pkt.Goocoos {
if goocoo.Data1[0] == 0 { if goocoo.Data1[0] == 0 {
_, _ = s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=NULL WHERE id=$1", goocoo.Index), s.charID) if _, err := s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=NULL WHERE id=$1", goocoo.Index), s.charID); err != nil {
s.logger.Error("Failed to clear goocoo slot", zap.Error(err))
}
} else { } else {
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
bf.WriteUint32(goocoo.Index) bf.WriteUint32(goocoo.Index)
@@ -1081,7 +1101,9 @@ func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) {
} }
bf.WriteUint8(uint8(len(goocoo.Name))) bf.WriteUint8(uint8(len(goocoo.Name)))
bf.WriteBytes(goocoo.Name) bf.WriteBytes(goocoo.Name)
_, _ = s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=$1 WHERE id=$2", goocoo.Index), bf.Data(), s.charID) if _, err := s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=$1 WHERE id=$2", goocoo.Index), bf.Data(), s.charID); err != nil {
s.logger.Error("Failed to update goocoo slot", zap.Error(err))
}
dumpSaveData(s, bf.Data(), fmt.Sprintf("goocoo-%d", goocoo.Index)) dumpSaveData(s, bf.Data(), fmt.Sprintf("goocoo-%d", goocoo.Index))
} }
} }
@@ -1144,7 +1166,9 @@ func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) {
var dailyTime time.Time var dailyTime time.Time
_ = s.server.db.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.charID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime) _ = s.server.db.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.charID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime)
if TimeAdjusted().After(dailyTime) { if TimeAdjusted().After(dailyTime) {
_, _ = s.server.db.Exec("UPDATE characters SET bonus_quests = 0, daily_quests = 0 WHERE id=$1", s.charID) if _, err := s.server.db.Exec("UPDATE characters SET bonus_quests = 0, daily_quests = 0 WHERE id=$1", s.charID); err != nil {
s.logger.Error("Failed to reset daily quests", zap.Error(err))
}
} }
var bonusQuests, dailyQuests, promoPoints uint32 var bonusQuests, dailyQuests, promoPoints uint32
@@ -1174,9 +1198,13 @@ func handleMsgMhfUpdateEtcPoint(s *Session, p mhfpacket.MHFPacket) {
err := s.server.db.QueryRow(fmt.Sprintf(`SELECT %s FROM characters WHERE id = $1`, column), s.charID).Scan(&value) err := s.server.db.QueryRow(fmt.Sprintf(`SELECT %s FROM characters WHERE id = $1`, column), s.charID).Scan(&value)
if err == nil { if err == nil {
if value+pkt.Delta < 0 { if value+pkt.Delta < 0 {
_, _ = s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = 0 WHERE id = $1`, column), s.charID) if _, err := s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = 0 WHERE id = $1`, column), s.charID); err != nil {
s.logger.Error("Failed to reset etc point", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = %s + $1 WHERE id = $2`, column, column), pkt.Delta, s.charID) if _, err := s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = %s + $1 WHERE id = $2`, column, column), pkt.Delta, s.charID); err != nil {
s.logger.Error("Failed to update etc point", zap.Error(err))
}
} }
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
@@ -1517,7 +1545,9 @@ func handleMsgMhfUpdateEquipSkinHist(s *Session, p mhfpacket.MHFPacket) {
bitInByte := bit % 8 bitInByte := bit % 8
data[startByte+byteInd] |= bits.Reverse8(1 << uint(bitInByte)) data[startByte+byteInd] |= bits.Reverse8(1 << uint(bitInByte))
dumpSaveData(s, data, "skinhist") dumpSaveData(s, data, "skinhist")
_, _ = s.server.db.Exec("UPDATE characters SET skin_hist=$1 WHERE id=$2", data, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET skin_hist=$1 WHERE id=$2", data, s.charID); err != nil {
s.logger.Error("Failed to update skin history", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -1600,7 +1630,9 @@ func handleMsgMhfGetTrendWeapon(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfUpdateUseTrendWeaponLog(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateUseTrendWeaponLog(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateUseTrendWeaponLog) pkt := p.(*mhfpacket.MsgMhfUpdateUseTrendWeaponLog)
_, _ = s.server.db.Exec(`INSERT INTO trend_weapons (weapon_id, weapon_type, count) VALUES ($1, $2, 1) ON CONFLICT (weapon_id) DO if _, err := s.server.db.Exec(`INSERT INTO trend_weapons (weapon_id, weapon_type, count) VALUES ($1, $2, 1) ON CONFLICT (weapon_id) DO
UPDATE SET count = trend_weapons.count+1`, pkt.WeaponID, pkt.WeaponType) UPDATE SET count = trend_weapons.count+1`, pkt.WeaponID, pkt.WeaponType); err != nil {
s.logger.Error("Failed to update trend weapon log", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -5,6 +5,8 @@ import (
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"fmt" "fmt"
"io" "io"
"go.uber.org/zap"
) )
var achievementCurves = [][]int32{ var achievementCurves = [][]int32{
@@ -90,7 +92,9 @@ func handleMsgMhfGetAchievement(s *Session, p mhfpacket.MHFPacket) {
var exists int var exists int
err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", pkt.CharID).Scan(&exists) err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", pkt.CharID).Scan(&exists)
if err != nil { if err != nil {
_, _ = s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", pkt.CharID) if _, err := s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", pkt.CharID); err != nil {
s.logger.Error("Failed to insert achievements record", zap.Error(err))
}
} }
var scores [33]int32 var scores [33]int32
@@ -152,10 +156,14 @@ func handleMsgMhfAddAchievement(s *Session, p mhfpacket.MHFPacket) {
var exists int var exists int
err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", s.charID).Scan(&exists) err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", s.charID).Scan(&exists)
if err != nil { if err != nil {
_, _ = s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", s.charID) if _, err := s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", s.charID); err != nil {
s.logger.Error("Failed to insert achievements record", zap.Error(err))
}
} }
_, _ = s.server.db.Exec(fmt.Sprintf("UPDATE achievements SET ach%d=ach%d+1 WHERE id=$1", pkt.AchievementID, pkt.AchievementID), s.charID) if _, err := s.server.db.Exec(fmt.Sprintf("UPDATE achievements SET ach%d=ach%d+1 WHERE id=$1", pkt.AchievementID, pkt.AchievementID), s.charID); err != nil {
s.logger.Error("Failed to update achievement score", zap.Error(err))
}
} }
func handleMsgMhfPaymentAchievement(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPaymentAchievement(s *Session, p mhfpacket.MHFPacket) {}

View File

@@ -58,7 +58,9 @@ func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) {
bondBonus = 5 // Bond point bonus quests bondBonus = 5 // Bond point bonus quests
bonusQuests = s.server.erupeConfig.GameplayOptions.BonusQuestAllowance bonusQuests = s.server.erupeConfig.GameplayOptions.BonusQuestAllowance
dailyQuests = s.server.erupeConfig.GameplayOptions.DailyQuestAllowance dailyQuests = s.server.erupeConfig.GameplayOptions.DailyQuestAllowance
_, _ = s.server.db.Exec("UPDATE characters SET daily_time=$1, bonus_quests = $2, daily_quests = $3 WHERE id=$4", midday, bonusQuests, dailyQuests, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET daily_time=$1, bonus_quests = $2, daily_quests = $3 WHERE id=$4", midday, bonusQuests, dailyQuests, s.charID); err != nil {
s.logger.Error("Failed to update daily cafe data", zap.Error(err))
}
bf.WriteBool(true) // Success? bf.WriteBool(true) // Success?
} else { } else {
bf.WriteBool(false) bf.WriteBool(false)
@@ -77,12 +79,18 @@ func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) {
err := s.server.db.QueryRow(`SELECT cafe_reset FROM characters WHERE id=$1`, s.charID).Scan(&cafeReset) err := s.server.db.QueryRow(`SELECT cafe_reset FROM characters WHERE id=$1`, s.charID).Scan(&cafeReset)
if err != nil { if err != nil {
cafeReset = TimeWeekNext() cafeReset = TimeWeekNext()
_, _ = s.server.db.Exec(`UPDATE characters SET cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID) if _, err := s.server.db.Exec(`UPDATE characters SET cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID); err != nil {
s.logger.Error("Failed to set cafe reset time", zap.Error(err))
}
} }
if TimeAdjusted().After(cafeReset) { if TimeAdjusted().After(cafeReset) {
cafeReset = TimeWeekNext() cafeReset = TimeWeekNext()
_, _ = s.server.db.Exec(`UPDATE characters SET cafe_time=0, cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID) if _, err := s.server.db.Exec(`UPDATE characters SET cafe_time=0, cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID); err != nil {
_, _ = s.server.db.Exec(`DELETE FROM cafe_accepted WHERE character_id=$1`, s.charID) s.logger.Error("Failed to reset cafe time", zap.Error(err))
}
if _, err := s.server.db.Exec(`DELETE FROM cafe_accepted WHERE character_id=$1`, s.charID); err != nil {
s.logger.Error("Failed to delete accepted cafe bonuses", zap.Error(err))
}
} }
var cafeTime uint32 var cafeTime uint32
@@ -199,7 +207,9 @@ func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket
_ = addPointNetcafe(s, int(cafeBonus.Quantity)) _ = addPointNetcafe(s, int(cafeBonus.Quantity))
} }
} }
_, _ = s.server.db.Exec("INSERT INTO public.cafe_accepted VALUES ($1, $2)", cbID, s.charID) if _, err := s.server.db.Exec("INSERT INTO public.cafe_accepted VALUES ($1, $2)", cbID, s.charID); err != nil {
s.logger.Error("Failed to insert accepted cafe bonus", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -215,7 +225,9 @@ func addPointNetcafe(s *Session, p int) error {
} else { } else {
points += p points += p
} }
_, _ = s.server.db.Exec("UPDATE characters SET netcafe_points=$1 WHERE id=$2", points, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET netcafe_points=$1 WHERE id=$2", points, s.charID); err != nil {
s.logger.Error("Failed to update netcafe points", zap.Error(err))
}
return nil return nil
} }
@@ -228,7 +240,9 @@ func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
return return
} }
_, _ = s.server.db.Exec("UPDATE characters SET boost_time=$1 WHERE id=$2", boostLimit, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET boost_time=$1 WHERE id=$2", boostLimit, s.charID); err != nil {
s.logger.Error("Failed to update boost time", zap.Error(err))
}
bf.WriteUint32(uint32(boostLimit.Unix())) bf.WriteUint32(uint32(boostLimit.Unix()))
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }

View File

@@ -123,12 +123,16 @@ func parseChatCommand(s *Session, command string) {
err := s.server.db.QueryRow(`SELECT id, username FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, cid).Scan(&uid, &uname) err := s.server.db.QueryRow(`SELECT id, username FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, cid).Scan(&uid, &uname)
if err == nil { if err == nil {
if expiry.IsZero() { if expiry.IsZero() {
_, _ = s.server.db.Exec(`INSERT INTO bans VALUES ($1) if _, err := s.server.db.Exec(`INSERT INTO bans VALUES ($1)
ON CONFLICT (user_id) DO UPDATE SET expires=NULL`, uid) ON CONFLICT (user_id) DO UPDATE SET expires=NULL`, uid); err != nil {
s.logger.Error("Failed to ban user", zap.Error(err))
}
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname)) sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname))
} else { } else {
_, _ = s.server.db.Exec(`INSERT INTO bans VALUES ($1, $2) if _, err := s.server.db.Exec(`INSERT INTO bans VALUES ($1, $2)
ON CONFLICT (user_id) DO UPDATE SET expires=$2`, uid, expiry) ON CONFLICT (user_id) DO UPDATE SET expires=$2`, uid, expiry); err != nil {
s.logger.Error("Failed to ban user with expiry", zap.Error(err))
}
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname)+fmt.Sprintf(s.server.i18n.commands.ban.length, expiry.Format(time.DateTime))) sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname)+fmt.Sprintf(s.server.i18n.commands.ban.length, expiry.Format(time.DateTime)))
} }
s.server.DisconnectUser(uid) s.server.DisconnectUser(uid)
@@ -150,7 +154,9 @@ func parseChatCommand(s *Session, command string) {
if err := s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&state); err != nil { if err := s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&state); err != nil {
s.logger.Error("Failed to get timer state", zap.Error(err)) s.logger.Error("Failed to get timer state", zap.Error(err))
} }
_, _ = s.server.db.Exec(`UPDATE users u SET timer=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, !state, s.charID) if _, err := s.server.db.Exec(`UPDATE users u SET timer=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, !state, s.charID); err != nil {
s.logger.Error("Failed to update timer setting", zap.Error(err))
}
if state { if state {
sendServerChatMessage(s, s.server.i18n.commands.timer.disabled) sendServerChatMessage(s, s.server.i18n.commands.timer.disabled)
} else { } else {
@@ -308,7 +314,9 @@ func parseChatCommand(s *Session, command string) {
} }
err := s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.charID).Scan(&rightsInt) err := s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.charID).Scan(&rightsInt)
if err == nil { if err == nil {
_, _ = s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", rightsInt+delta, s.charID) if _, err := s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", rightsInt+delta, s.charID); err != nil {
s.logger.Error("Failed to update user rights", zap.Error(err))
}
} }
updateRights(s) updateRights(s)
} else { } else {
@@ -406,7 +414,9 @@ func parseChatCommand(s *Session, command string) {
randToken := make([]byte, 4) randToken := make([]byte, 4)
_, _ = rand.Read(randToken) _, _ = rand.Read(randToken)
_token = fmt.Sprintf("%x-%x", randToken[:2], randToken[2:]) _token = fmt.Sprintf("%x-%x", randToken[:2], randToken[2:])
_, _ = s.server.db.Exec(`UPDATE users u SET discord_token = $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, _token, s.charID) if _, err := s.server.db.Exec(`UPDATE users u SET discord_token = $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, _token, s.charID); err != nil {
s.logger.Error("Failed to update discord token", zap.Error(err))
}
} }
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.discord.success, _token)) sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.discord.success, _token))
} else { } else {

View File

@@ -186,8 +186,10 @@ func (save *CharacterSaveData) Save(s *Session) {
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 if _, err := 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) `, save.HouseTier, save.HouseData, save.BookshelfData, save.GalleryData, save.ToreData, save.GardenData, s.charID); err != nil {
s.logger.Error("Failed to update user binary house data", zap.Error(err))
}
} }
func (save *CharacterSaveData) Compress() error { func (save *CharacterSaveData) Compress() error {

View File

@@ -94,7 +94,9 @@ func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) {
} else { } else {
csv = stringsupport.CSVAdd(csv, int(cid)) csv = stringsupport.CSVAdd(csv, int(cid))
} }
_, _ = s.server.db.Exec("UPDATE characters SET blocked=$1 WHERE id=$2", csv, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET blocked=$1 WHERE id=$2", csv, s.charID); err != nil {
s.logger.Error("Failed to update blocked list", zap.Error(err))
}
} }
} else { // Friendlist } else { // Friendlist
err := s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&csv) err := s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&csv)
@@ -104,7 +106,9 @@ func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) {
} else { } else {
csv = stringsupport.CSVAdd(csv, int(cid)) csv = stringsupport.CSVAdd(csv, int(cid))
} }
_, _ = s.server.db.Exec("UPDATE characters SET friends=$1 WHERE id=$2", csv, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET friends=$1 WHERE id=$2", csv, s.charID); err != nil {
s.logger.Error("Failed to update friends list", zap.Error(err))
}
} }
} }
} }

View File

@@ -78,7 +78,9 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
s.rawConn.Close() s.rawConn.Close()
s.logger.Warn("Save cancelled due to corruption.") s.logger.Warn("Save cancelled due to corruption.")
if s.server.erupeConfig.DeleteOnSaveCorruption { if s.server.erupeConfig.DeleteOnSaveCorruption {
_, _ = s.server.db.Exec("UPDATE characters SET deleted=true WHERE id=$1", s.charID) if _, err := s.server.db.Exec("UPDATE characters SET deleted=true WHERE id=$1", s.charID); err != nil {
s.logger.Error("Failed to mark character as deleted", zap.Error(err))
}
} }
return return
} }

View File

@@ -170,11 +170,17 @@ func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) {
case 17: case 17:
_ = addPointNetcafe(s, int(item.Quantity)) _ = addPointNetcafe(s, int(item.Quantity))
case 19: case 19:
_, _ = s.server.db.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID) if _, err := s.server.db.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID); err != nil {
s.logger.Error("Failed to update gacha premium", zap.Error(err))
}
case 20: case 20:
_, _ = s.server.db.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID) if _, err := s.server.db.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID); err != nil {
s.logger.Error("Failed to update gacha trial", zap.Error(err))
}
case 21: case 21:
_, _ = s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID) if _, err := s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID); err != nil {
s.logger.Error("Failed to update frontier points", zap.Error(err))
}
case 23: case 23:
saveData, err := GetCharacterSaveData(s, s.charID) saveData, err := GetCharacterSaveData(s, s.charID)
if err == nil { if err == nil {

View File

@@ -12,7 +12,9 @@ import (
) )
func cleanupDiva(s *Session) { func cleanupDiva(s *Session) {
_, _ = s.server.db.Exec("DELETE FROM events WHERE event_type='diva'") if _, err := s.server.db.Exec("DELETE FROM events WHERE event_type='diva'"); err != nil {
s.logger.Error("Failed to delete diva events", zap.Error(err))
}
} }
func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 { func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 {
@@ -49,7 +51,9 @@ func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 {
cleanupDiva(s) cleanupDiva(s)
// Generate a new diva defense, starting midnight tomorrow // Generate a new diva defense, starting midnight tomorrow
start = uint32(midnight.Add(24 * time.Hour).Unix()) start = uint32(midnight.Add(24 * time.Hour).Unix())
_, _ = s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('diva', to_timestamp($1)::timestamp without time zone)", start) if _, err := s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('diva', to_timestamp($1)::timestamp without time zone)", start); err != nil {
s.logger.Error("Failed to insert diva event", zap.Error(err))
}
} }
timestamps[0] = start timestamps[0] = start
timestamps[1] = timestamps[0] + 601200 timestamps[1] = timestamps[0] + 601200

View File

@@ -8,6 +8,7 @@ import (
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"go.uber.org/zap"
) )
type Event struct { type Event struct {
@@ -69,7 +70,9 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
weapons := token.RNG.Intn(s.server.erupeConfig.GameplayOptions.MaxFeatureWeapons-s.server.erupeConfig.GameplayOptions.MinFeatureWeapons+1) + s.server.erupeConfig.GameplayOptions.MinFeatureWeapons weapons := token.RNG.Intn(s.server.erupeConfig.GameplayOptions.MaxFeatureWeapons-s.server.erupeConfig.GameplayOptions.MinFeatureWeapons+1) + s.server.erupeConfig.GameplayOptions.MinFeatureWeapons
temp = generateFeatureWeapons(weapons) temp = generateFeatureWeapons(weapons)
temp.StartTime = t temp.StartTime = t
_, _ = s.server.db.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, temp.StartTime, temp.ActiveFeatures) if _, err := s.server.db.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, temp.StartTime, temp.ActiveFeatures); err != nil {
s.logger.Error("Failed to insert feature weapon", zap.Error(err))
}
} }
features = append(features, temp) features = append(features, temp)
} }
@@ -155,7 +158,9 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {
{WeekReq: 5, Expiration: temp}, {WeekReq: 5, Expiration: temp},
} }
for _, boost := range loginBoosts { for _, boost := range loginBoosts {
_, _ = s.server.db.Exec(`INSERT INTO login_boost VALUES ($1, $2, $3, $4)`, s.charID, boost.WeekReq, boost.Expiration, time.Time{}) if _, err := s.server.db.Exec(`INSERT INTO login_boost VALUES ($1, $2, $3, $4)`, s.charID, boost.WeekReq, boost.Expiration, time.Time{}); err != nil {
s.logger.Error("Failed to insert login boost", zap.Error(err))
}
} }
} }
@@ -164,7 +169,9 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {
if !boost.Reset.IsZero() && boost.Reset.Before(TimeAdjusted()) { if !boost.Reset.IsZero() && boost.Reset.Before(TimeAdjusted()) {
boost.Expiration = TimeWeekStart() boost.Expiration = TimeWeekStart()
boost.Reset = time.Time{} boost.Reset = time.Time{}
_, _ = s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, boost.Expiration, boost.Reset, s.charID, boost.WeekReq) if _, err := s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, boost.Expiration, boost.Reset, s.charID, boost.WeekReq); err != nil {
s.logger.Error("Failed to reset login boost", zap.Error(err))
}
} }
boost.WeekCount = uint8((TimeAdjusted().Unix()-boost.Expiration.Unix())/604800 + 1) boost.WeekCount = uint8((TimeAdjusted().Unix()-boost.Expiration.Unix())/604800 + 1)
@@ -207,7 +214,9 @@ func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) {
expiration = TimeAdjusted().Add(240 * time.Minute) expiration = TimeAdjusted().Add(240 * time.Minute)
} }
bf.WriteUint32(uint32(expiration.Unix())) bf.WriteUint32(uint32(expiration.Unix()))
_, _ = s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, expiration, TimeWeekNext(), s.charID, pkt.BoostWeekUsed) if _, err := s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, expiration, TimeWeekNext(), s.charID, pkt.BoostWeekUsed); err != nil {
s.logger.Error("Failed to use login boost", zap.Error(err))
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data()) doAckBufSucceed(s, pkt.AckHandle, bf.Data())
} }

View File

@@ -1,26 +1,32 @@
package channelserver package channelserver
import ( import (
"database/sql"
"errors"
"sort"
"time"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring" ps "erupe-ce/common/pascalstring"
"erupe-ce/common/token" "erupe-ce/common/token"
_config "erupe-ce/config" _config "erupe-ce/config"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"go.uber.org/zap" "go.uber.org/zap"
"sort"
"time"
) )
func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSaveMezfesData) pkt := p.(*mhfpacket.MsgMhfSaveMezfesData)
_, _ = s.server.db.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.charID) if _, err := s.server.db.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.charID); err != nil {
s.logger.Error("Failed to save mezfes data", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} }
func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfLoadMezfesData) pkt := p.(*mhfpacket.MsgMhfLoadMezfesData)
var data []byte var data []byte
if err := s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data); err != nil { if err := s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data); err != nil && !errors.Is(err, sql.ErrNoRows) {
s.logger.Error("Failed to load mezfes data", zap.Error(err)) s.logger.Error("Failed to load mezfes data", zap.Error(err))
} }
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
@@ -96,11 +102,21 @@ func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {
} }
func cleanupFesta(s *Session) { func cleanupFesta(s *Session) {
_, _ = s.server.db.Exec("DELETE FROM events WHERE event_type='festa'") if _, err := s.server.db.Exec("DELETE FROM events WHERE event_type='festa'"); err != nil {
_, _ = s.server.db.Exec("DELETE FROM festa_registrations") s.logger.Error("Failed to delete festa events", zap.Error(err))
_, _ = s.server.db.Exec("DELETE FROM festa_submissions") }
_, _ = s.server.db.Exec("DELETE FROM festa_prizes_accepted") if _, err := s.server.db.Exec("DELETE FROM festa_registrations"); err != nil {
_, _ = s.server.db.Exec("UPDATE guild_characters SET trial_vote=NULL") s.logger.Error("Failed to delete festa registrations", zap.Error(err))
}
if _, err := s.server.db.Exec("DELETE FROM festa_submissions"); err != nil {
s.logger.Error("Failed to delete festa submissions", zap.Error(err))
}
if _, err := s.server.db.Exec("DELETE FROM festa_prizes_accepted"); err != nil {
s.logger.Error("Failed to delete festa prizes accepted", zap.Error(err))
}
if _, err := s.server.db.Exec("UPDATE guild_characters SET trial_vote=NULL"); err != nil {
s.logger.Error("Failed to reset festa trial votes", zap.Error(err))
}
} }
func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 { func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
@@ -134,7 +150,9 @@ func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
cleanupFesta(s) cleanupFesta(s)
// Generate a new festa, starting midnight tomorrow // Generate a new festa, starting midnight tomorrow
start = uint32(midnight.Add(24 * time.Hour).Unix()) start = uint32(midnight.Add(24 * time.Hour).Unix())
_, _ = s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('festa', to_timestamp($1)::timestamp without time zone)", start) if _, err := s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('festa', to_timestamp($1)::timestamp without time zone)", start); err != nil {
s.logger.Error("Failed to insert festa event", zap.Error(err))
}
} }
timestamps[0] = start timestamps[0] = start
timestamps[1] = timestamps[0] + 604800 timestamps[1] = timestamps[0] + 604800
@@ -324,7 +342,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
WHERE fs.trial_type = $1 WHERE fs.trial_type = $1
GROUP BY fs.guild_id, g.name, fr.team GROUP BY fs.guild_id, g.name, fr.team
ORDER BY _ DESC LIMIT 1 ORDER BY _ DESC LIMIT 1
`, i+1).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil { `, i+1).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil && !errors.Is(err, sql.ErrNoRows) {
s.logger.Error("Failed to get festa trial ranking", zap.Error(err)) s.logger.Error("Failed to get festa trial ranking", zap.Error(err))
} }
bf.WriteUint32(guildID) bf.WriteUint32(guildID)
@@ -346,7 +364,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
WHERE EXTRACT(EPOCH FROM fs.timestamp)::int > $1 AND EXTRACT(EPOCH FROM fs.timestamp)::int < $2 WHERE EXTRACT(EPOCH FROM fs.timestamp)::int > $1 AND EXTRACT(EPOCH FROM fs.timestamp)::int < $2
GROUP BY fs.guild_id, g.name, fr.team GROUP BY fs.guild_id, g.name, fr.team
ORDER BY _ DESC LIMIT 1 ORDER BY _ DESC LIMIT 1
`, timestamps[1]+offset, timestamps[1]+offset+86400).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil { `, timestamps[1]+offset, timestamps[1]+offset+86400).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil && !errors.Is(err, sql.ErrNoRows) {
s.logger.Error("Failed to get festa daily ranking", zap.Error(err)) s.logger.Error("Failed to get festa daily ranking", zap.Error(err))
} }
bf.WriteUint32(guildID) bf.WriteUint32(guildID)
@@ -466,7 +484,9 @@ func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfVoteFesta(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfVoteFesta(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfVoteFesta) pkt := p.(*mhfpacket.MsgMhfVoteFesta)
_, _ = s.server.db.Exec(`UPDATE guild_characters SET trial_vote=$1 WHERE character_id=$2`, pkt.TrialID, s.charID) if _, err := s.server.db.Exec(`UPDATE guild_characters SET trial_vote=$1 WHERE character_id=$2`, pkt.TrialID, s.charID); err != nil {
s.logger.Error("Failed to update festa trial vote", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -480,9 +500,13 @@ func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {
team := uint32(token.RNG.Intn(2)) team := uint32(token.RNG.Intn(2))
switch team { switch team {
case 0: case 0:
_, _ = s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID) if _, err := s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID); err != nil {
s.logger.Error("Failed to register guild for festa blue team", zap.Error(err))
}
case 1: case 1:
_, _ = s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'red')", guild.ID) if _, err := s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'red')", guild.ID); err != nil {
s.logger.Error("Failed to register guild for festa red team", zap.Error(err))
}
} }
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
bf.WriteUint32(team) bf.WriteUint32(team)
@@ -512,19 +536,25 @@ func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfAcquireFesta(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfAcquireFesta(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireFesta) pkt := p.(*mhfpacket.MsgMhfAcquireFesta)
_, _ = s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES (0, $1)", s.charID) if _, err := s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES (0, $1)", s.charID); err != nil {
s.logger.Error("Failed to accept festa prize", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
func handleMsgMhfAcquireFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfAcquireFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireFestaPersonalPrize) pkt := p.(*mhfpacket.MsgMhfAcquireFestaPersonalPrize)
_, _ = s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID) if _, err := s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID); err != nil {
s.logger.Error("Failed to accept festa personal prize", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
func handleMsgMhfAcquireFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfAcquireFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireFestaIntermediatePrize) pkt := p.(*mhfpacket.MsgMhfAcquireFestaIntermediatePrize)
_, _ = s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID) if _, err := s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID); err != nil {
s.logger.Error("Failed to accept festa intermediate prize", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -715,9 +715,13 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
case mhfpacket.OperateGuildDonateRank: case mhfpacket.OperateGuildDonateRank:
bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, 0)) bf.WriteBytes(handleDonateRP(s, uint16(pkt.Data1.ReadUint32()), guild, 0))
case mhfpacket.OperateGuildSetApplicationDeny: case mhfpacket.OperateGuildSetApplicationDeny:
_, _ = s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID) if _, err := s.server.db.Exec("UPDATE guilds SET recruiting=false WHERE id=$1", guild.ID); err != nil {
s.logger.Error("Failed to deny guild applications", zap.Error(err))
}
case mhfpacket.OperateGuildSetApplicationAllow: case mhfpacket.OperateGuildSetApplicationAllow:
_, _ = s.server.db.Exec("UPDATE guilds SET recruiting=true WHERE id=$1", guild.ID) if _, err := s.server.db.Exec("UPDATE guilds SET recruiting=true WHERE id=$1", guild.ID); err != nil {
s.logger.Error("Failed to allow guild applications", zap.Error(err))
}
case mhfpacket.OperateGuildSetAvoidLeadershipTrue: case mhfpacket.OperateGuildSetAvoidLeadershipTrue:
handleAvoidLeadershipUpdate(s, pkt, true) handleAvoidLeadershipUpdate(s, pkt, true)
case mhfpacket.OperateGuildSetAvoidLeadershipFalse: case mhfpacket.OperateGuildSetAvoidLeadershipFalse:
@@ -751,7 +755,9 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
case mhfpacket.OperateGuildChangePugi3: case mhfpacket.OperateGuildChangePugi3:
handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 3) handleChangePugi(s, uint8(pkt.Data1.ReadUint32()), guild, 3)
case mhfpacket.OperateGuildUnlockOutfit: case mhfpacket.OperateGuildUnlockOutfit:
_, _ = s.server.db.Exec(`UPDATE guilds SET pugi_outfits=$1 WHERE id=$2`, pkt.Data1.ReadUint32(), guild.ID) if _, err := s.server.db.Exec(`UPDATE guilds SET pugi_outfits=$1 WHERE id=$2`, pkt.Data1.ReadUint32(), guild.ID); err != nil {
s.logger.Error("Failed to unlock guild pugi outfit", zap.Error(err))
}
case mhfpacket.OperateGuildDonateRoom: case mhfpacket.OperateGuildDonateRoom:
quantity := uint16(pkt.Data1.ReadUint32()) quantity := uint16(pkt.Data1.ReadUint32())
bf.WriteBytes(handleDonateRP(s, quantity, guild, 2)) bf.WriteBytes(handleDonateRP(s, quantity, guild, 2))
@@ -759,7 +765,9 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
quantity := uint16(pkt.Data1.ReadUint32()) quantity := uint16(pkt.Data1.ReadUint32())
bf.WriteBytes(handleDonateRP(s, quantity, guild, 1)) bf.WriteBytes(handleDonateRP(s, quantity, guild, 1))
// TODO: Move this value onto rp_yesterday and reset to 0... daily? // TODO: Move this value onto rp_yesterday and reset to 0... daily?
_, _ = s.server.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.charID) if _, err := s.server.db.Exec(`UPDATE guild_characters SET rp_today=rp_today+$1 WHERE character_id=$2`, quantity, s.charID); err != nil {
s.logger.Error("Failed to update guild character daily RP", zap.Error(err))
}
case mhfpacket.OperateGuildEventExchange: case mhfpacket.OperateGuildEventExchange:
rp := uint16(pkt.Data1.ReadUint32()) rp := uint16(pkt.Data1.ReadUint32())
var balance uint32 var balance uint32
@@ -825,15 +833,25 @@ func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte {
saveData.Save(s) saveData.Save(s)
switch _type { switch _type {
case 0: case 0:
_, _ = s.server.db.Exec(`UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2`, amount, guild.ID) if _, err := s.server.db.Exec(`UPDATE guilds SET rank_rp = rank_rp + $1 WHERE id = $2`, amount, guild.ID); err != nil {
s.logger.Error("Failed to update guild rank RP", zap.Error(err))
}
case 1: case 1:
_, _ = s.server.db.Exec(`UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2`, amount, guild.ID) if _, err := s.server.db.Exec(`UPDATE guilds SET event_rp = event_rp + $1 WHERE id = $2`, amount, guild.ID); err != nil {
s.logger.Error("Failed to update guild event RP", zap.Error(err))
}
case 2: case 2:
if resetRoom { if resetRoom {
_, _ = s.server.db.Exec(`UPDATE guilds SET room_rp = 0 WHERE id = $1`, guild.ID) if _, err := s.server.db.Exec(`UPDATE guilds SET room_rp = 0 WHERE id = $1`, guild.ID); err != nil {
_, _ = s.server.db.Exec(`UPDATE guilds SET room_expiry = $1 WHERE id = $2`, TimeAdjusted().Add(time.Hour*24*7), guild.ID) s.logger.Error("Failed to reset guild room RP", zap.Error(err))
}
if _, err := s.server.db.Exec(`UPDATE guilds SET room_expiry = $1 WHERE id = $2`, TimeAdjusted().Add(time.Hour*24*7), guild.ID); err != nil {
s.logger.Error("Failed to update guild room expiry", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec(`UPDATE guilds SET room_rp = room_rp + $1 WHERE id = $2`, amount, guild.ID) if _, err := s.server.db.Exec(`UPDATE guilds SET room_rp = room_rp + $1 WHERE id = $2`, amount, guild.ID); err != nil {
s.logger.Error("Failed to update guild room RP", zap.Error(err))
}
} }
} }
_, _ = bf.Seek(0, 0) _, _ = bf.Seek(0, 0)
@@ -1597,7 +1615,7 @@ func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) {
func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack { func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack {
var data []byte var data []byte
var items []mhfitem.MHFItemStack var items []mhfitem.MHFItemStack
if err := s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data); err != nil { if err := s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data); err != nil && !errors.Is(err, sql.ErrNoRows) {
s.logger.Error("Failed to get guild item box", zap.Error(err)) s.logger.Error("Failed to get guild item box", zap.Error(err))
} }
if len(data) > 0 { if len(data) > 0 {
@@ -1622,7 +1640,9 @@ func handleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateGuildItem) pkt := p.(*mhfpacket.MsgMhfUpdateGuildItem)
newStacks := mhfitem.DiffItemStacks(guildGetItems(s, pkt.GuildID), pkt.UpdatedItems) 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) if _, err := s.server.db.Exec(`UPDATE guilds SET item_box=$1 WHERE id=$2`, mhfitem.SerializeWarehouseItems(newStacks), pkt.GuildID); err != nil {
s.logger.Error("Failed to update guild item box", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -1810,7 +1830,9 @@ func handleMsgMhfRegistGuildCooking(s *Session, p mhfpacket.MHFPacket) {
guild, _ := GetGuildInfoByCharacterId(s, s.charID) guild, _ := GetGuildInfoByCharacterId(s, s.charID)
startTime := TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.ClanMealDuration-3600) * time.Second) startTime := TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.ClanMealDuration-3600) * time.Second)
if pkt.OverwriteID != 0 { if pkt.OverwriteID != 0 {
_, _ = s.server.db.Exec("UPDATE guild_meals SET meal_id = $1, level = $2, created_at = $3 WHERE id = $4", pkt.MealID, pkt.Success, startTime, pkt.OverwriteID) if _, err := s.server.db.Exec("UPDATE guild_meals SET meal_id = $1, level = $2, created_at = $3 WHERE id = $4", pkt.MealID, pkt.Success, startTime, pkt.OverwriteID); err != nil {
s.logger.Error("Failed to update guild meal", zap.Error(err))
}
} else { } else {
_ = s.server.db.QueryRow("INSERT INTO guild_meals (guild_id, meal_id, level, created_at) VALUES ($1, $2, $3, $4) RETURNING id", guild.ID, pkt.MealID, pkt.Success, startTime).Scan(&pkt.OverwriteID) _ = s.server.db.QueryRow("INSERT INTO guild_meals (guild_id, meal_id, level, created_at) VALUES ($1, $2, $3, $4) RETURNING id", guild.ID, pkt.MealID, pkt.Success, startTime).Scan(&pkt.OverwriteID)
} }
@@ -1843,7 +1865,9 @@ func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) {
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
switch pkt.Operation { switch pkt.Operation {
case 0: // Acquire case 0: // Acquire
_, _ = s.server.db.Exec(`UPDATE guild_characters SET box_claimed=$1 WHERE character_id=$2`, TimeAdjusted(), s.charID) if _, err := s.server.db.Exec(`UPDATE guild_characters SET box_claimed=$1 WHERE character_id=$2`, TimeAdjusted(), s.charID); err != nil {
s.logger.Error("Failed to update guild hunt box claimed time", zap.Error(err))
}
case 1: // Enumerate case 1: // Enumerate
bf.WriteUint8(0) // Entries bf.WriteUint8(0) // Entries
rows, err := s.server.db.Query(`SELECT kl.id, kl.monster FROM kill_logs kl rows, err := s.server.db.Query(`SELECT kl.id, kl.monster FROM kill_logs kl
@@ -1913,7 +1937,9 @@ func handleMsgMhfEnumerateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
return return
} }
_, _ = s.server.db.Exec("UPDATE characters SET guild_post_checked = now() WHERE id = $1", s.charID) if _, err := s.server.db.Exec("UPDATE characters SET guild_post_checked = now() WHERE id = $1", s.charID); err != nil {
s.logger.Error("Failed to update guild post checked time", zap.Error(err))
}
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
var postCount uint32 var postCount uint32
for msgs.Next() { for msgs.Next() {
@@ -1952,21 +1978,31 @@ func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
} }
switch pkt.MessageOp { switch pkt.MessageOp {
case 0: // Create message case 0: // Create message
_, _ = s.server.db.Exec("INSERT INTO guild_posts (guild_id, author_id, stamp_id, post_type, title, body) VALUES ($1, $2, $3, $4, $5, $6)", guild.ID, s.charID, pkt.StampID, pkt.PostType, pkt.Title, pkt.Body) if _, err := s.server.db.Exec("INSERT INTO guild_posts (guild_id, author_id, stamp_id, post_type, title, body) VALUES ($1, $2, $3, $4, $5, $6)", guild.ID, s.charID, pkt.StampID, pkt.PostType, pkt.Title, pkt.Body); err != nil {
s.logger.Error("Failed to insert guild post", zap.Error(err))
}
maxPosts := 100 maxPosts := 100
if pkt.PostType == 1 { if pkt.PostType == 1 {
maxPosts = 4 maxPosts = 4
} }
_, _ = s.server.db.Exec(`DELETE FROM guild_posts WHERE id IN ( if _, err := s.server.db.Exec(`DELETE FROM guild_posts WHERE id IN (
SELECT id FROM guild_posts WHERE guild_id = $1 AND post_type = $2 SELECT id FROM guild_posts WHERE guild_id = $1 AND post_type = $2
ORDER BY created_at DESC OFFSET $3 ORDER BY created_at DESC OFFSET $3
)`, guild.ID, pkt.PostType, maxPosts) )`, guild.ID, pkt.PostType, maxPosts); err != nil {
s.logger.Error("Failed to purge excess guild posts", zap.Error(err))
}
case 1: // Delete message case 1: // Delete message
_, _ = s.server.db.Exec("DELETE FROM guild_posts WHERE id = $1", pkt.PostID) if _, err := s.server.db.Exec("DELETE FROM guild_posts WHERE id = $1", pkt.PostID); err != nil {
s.logger.Error("Failed to delete guild post", zap.Error(err))
}
case 2: // Update message case 2: // Update message
_, _ = s.server.db.Exec("UPDATE guild_posts SET title = $1, body = $2 WHERE id = $3", pkt.Title, pkt.Body, pkt.PostID) if _, err := s.server.db.Exec("UPDATE guild_posts SET title = $1, body = $2 WHERE id = $3", pkt.Title, pkt.Body, pkt.PostID); err != nil {
s.logger.Error("Failed to update guild post", zap.Error(err))
}
case 3: // Update stamp case 3: // Update stamp
_, _ = s.server.db.Exec("UPDATE guild_posts SET stamp_id = $1 WHERE id = $2", pkt.StampID, pkt.PostID) if _, err := s.server.db.Exec("UPDATE guild_posts SET stamp_id = $1 WHERE id = $2", pkt.StampID, pkt.PostID); err != nil {
s.logger.Error("Failed to update guild post stamp", zap.Error(err))
}
case 4: // Like message case 4: // Like message
var likedBy string var likedBy string
err := s.server.db.QueryRow("SELECT liked_by FROM guild_posts WHERE id = $1", pkt.PostID).Scan(&likedBy) err := s.server.db.QueryRow("SELECT liked_by FROM guild_posts WHERE id = $1", pkt.PostID).Scan(&likedBy)
@@ -1975,10 +2011,14 @@ func handleMsgMhfUpdateGuildMessageBoard(s *Session, p mhfpacket.MHFPacket) {
} else { } else {
if pkt.LikeState { if pkt.LikeState {
likedBy = stringsupport.CSVAdd(likedBy, int(s.charID)) likedBy = stringsupport.CSVAdd(likedBy, int(s.charID))
_, _ = s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID) if _, err := s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID); err != nil {
s.logger.Error("Failed to update guild post likes", zap.Error(err))
}
} else { } else {
likedBy = stringsupport.CSVRemove(likedBy, int(s.charID)) likedBy = stringsupport.CSVRemove(likedBy, int(s.charID))
_, _ = s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID) if _, err := s.server.db.Exec("UPDATE guild_posts SET liked_by = $1 WHERE id = $2", likedBy, pkt.PostID); err != nil {
s.logger.Error("Failed to update guild post likes", zap.Error(err))
}
} }
} }
case 5: // Check for new messages case 5: // Check for new messages
@@ -2019,7 +2059,9 @@ func handleMsgMhfUpdateGuild(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfSetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfSetGuildManageRight(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSetGuildManageRight) pkt := p.(*mhfpacket.MsgMhfSetGuildManageRight)
_, _ = s.server.db.Exec("UPDATE guild_characters SET recruiter=$1 WHERE character_id=$2", pkt.Allowed, pkt.CharID) if _, err := s.server.db.Exec("UPDATE guild_characters SET recruiter=$1 WHERE character_id=$2", pkt.Allowed, pkt.CharID); err != nil {
s.logger.Error("Failed to update guild manage right", zap.Error(err))
}
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -145,11 +145,17 @@ func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
case mhfpacket.OPERATE_JOINT_LEAVE: case mhfpacket.OPERATE_JOINT_LEAVE:
if guild.LeaderCharID == s.charID { if guild.LeaderCharID == s.charID {
if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 { if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 {
_, _ = s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID) if _, err := s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID); err != nil {
s.logger.Error("Failed to update alliance on guild leave", zap.Error(err))
}
} else if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 { } else if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 {
_, _ = s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID) if _, err := s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID); err != nil {
s.logger.Error("Failed to remove sub guild 1 from alliance", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID) if _, err := s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID); err != nil {
s.logger.Error("Failed to remove sub guild 2 from alliance", zap.Error(err))
}
} }
// NOTE: Alliance join requests are not yet implemented (no DB table exists), // NOTE: Alliance join requests are not yet implemented (no DB table exists),
// so there are no pending applications to clean up on leave. // so there are no pending applications to clean up on leave.
@@ -165,11 +171,17 @@ func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
if alliance.ParentGuild.LeaderCharID == s.charID { if alliance.ParentGuild.LeaderCharID == s.charID {
kickedGuildID := pkt.Data1.ReadUint32() kickedGuildID := pkt.Data1.ReadUint32()
if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 { if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 {
_, _ = s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID) if _, err := s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID); err != nil {
s.logger.Error("Failed to update alliance on guild kick", zap.Error(err))
}
} else if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 { } else if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 {
_, _ = s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID) if _, err := s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID); err != nil {
s.logger.Error("Failed to remove kicked sub guild 1 from alliance", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID) if _, err := s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID); err != nil {
s.logger.Error("Failed to remove kicked sub guild 2 from alliance", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} else { } else {

View File

@@ -5,6 +5,8 @@ import (
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"time" "time"
"go.uber.org/zap"
) )
type TreasureHunt struct { type TreasureHunt struct {
@@ -108,14 +110,18 @@ func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {
huntData.WriteBytes(bf.ReadBytes(9)) huntData.WriteBytes(bf.ReadBytes(9))
} }
} }
_, _ = s.server.db.Exec(`INSERT INTO guild_hunts (guild_id, host_id, destination, level, hunt_data, cats_used) VALUES ($1, $2, $3, $4, $5, $6) if _, err := s.server.db.Exec(`INSERT INTO guild_hunts (guild_id, host_id, destination, level, hunt_data, cats_used) VALUES ($1, $2, $3, $4, $5, $6)
`, guild.ID, s.charID, destination, level, huntData.Data(), catsUsed) `, 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)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresure) pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresure)
_, _ = s.server.db.Exec(`UPDATE guild_hunts SET acquired=true WHERE id=$1`, pkt.HuntID) if _, err := s.server.db.Exec(`UPDATE guild_hunts SET acquired=true WHERE id=$1`, pkt.HuntID); err != nil {
s.logger.Error("Failed to acquire guild treasure hunt", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -123,12 +129,20 @@ func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfOperateGuildTresureReport) pkt := p.(*mhfpacket.MsgMhfOperateGuildTresureReport)
switch pkt.State { switch pkt.State {
case 0: // Report registration case 0: // Report registration
_, _ = s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=$1 WHERE character_id=$2`, pkt.HuntID, s.charID) if _, err := s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=$1 WHERE character_id=$2`, pkt.HuntID, s.charID); err != nil {
s.logger.Error("Failed to register treasure hunt report", zap.Error(err))
}
case 1: // Collected by hunter case 1: // Collected by hunter
_, _ = s.server.db.Exec(`UPDATE guild_hunts SET collected=true WHERE id=$1`, pkt.HuntID) if _, err := s.server.db.Exec(`UPDATE guild_hunts SET collected=true WHERE id=$1`, pkt.HuntID); err != nil {
_, _ = s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE treasure_hunt=$1`, pkt.HuntID) s.logger.Error("Failed to mark treasure hunt collected", zap.Error(err))
}
if _, err := s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE treasure_hunt=$1`, pkt.HuntID); err != nil {
s.logger.Error("Failed to clear treasure hunt from guild characters", zap.Error(err))
}
case 2: // Claim treasure case 2: // Claim treasure
_, _ = s.server.db.Exec(`INSERT INTO guild_hunts_claimed VALUES ($1, $2)`, pkt.HuntID, s.charID) if _, err := s.server.db.Exec(`INSERT INTO guild_hunts_claimed VALUES ($1, $2)`, 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)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -41,7 +41,9 @@ FROM warehouse
func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateInterior) pkt := p.(*mhfpacket.MsgMhfUpdateInterior)
_, _ = s.server.db.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.charID) if _, err := s.server.db.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.charID); err != nil {
s.logger.Error("Failed to update house furniture", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -142,7 +144,9 @@ 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.server.db.Exec(`UPDATE user_binary SET house_state=$1, house_password=$2 WHERE id=$3`, pkt.State, pkt.Password, s.charID) if _, err := s.server.db.Exec(`UPDATE user_binary SET house_state=$1, house_password=$2 WHERE id=$3`, pkt.State, pkt.Password, s.charID); err != nil {
s.logger.Error("Failed to update house state", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -248,7 +252,9 @@ func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateMyhouseInfo) pkt := p.(*mhfpacket.MsgMhfUpdateMyhouseInfo)
_, _ = s.server.db.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.charID) if _, err := s.server.db.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.charID); err != nil {
s.logger.Error("Failed to update myhouse mission", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -317,7 +323,9 @@ func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {
} }
dumpSaveData(s, bf.Data(), "decomyset") dumpSaveData(s, bf.Data(), "decomyset")
_, _ = s.server.db.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", bf.Data(), s.charID) if _, err := s.server.db.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", bf.Data(), s.charID); err != nil {
s.logger.Error("Failed to save decomyset", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -361,9 +369,13 @@ func handleMsgMhfAcquireTitle(s *Session, p mhfpacket.MHFPacket) {
var exists int var exists int
err := s.server.db.QueryRow(`SELECT count(*) FROM titles WHERE id=$1 AND char_id=$2`, title, s.charID).Scan(&exists) err := s.server.db.QueryRow(`SELECT count(*) FROM titles WHERE id=$1 AND char_id=$2`, title, s.charID).Scan(&exists)
if err != nil || exists == 0 { if err != nil || exists == 0 {
_, _ = s.server.db.Exec(`INSERT INTO titles VALUES ($1, $2, now(), now())`, title, s.charID) if _, err := s.server.db.Exec(`INSERT INTO titles VALUES ($1, $2, now(), now())`, title, s.charID); err != nil {
s.logger.Error("Failed to insert title", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec(`UPDATE titles SET updated_at=now() WHERE id=$1 AND char_id=$2`, title, s.charID) if _, err := s.server.db.Exec(`UPDATE titles SET updated_at=now() WHERE id=$1 AND char_id=$2`, title, s.charID); err != nil {
s.logger.Error("Failed to update title", zap.Error(err))
}
} }
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
@@ -375,7 +387,9 @@ func initializeWarehouse(s *Session) {
var t int var t int
err := s.server.db.QueryRow("SELECT character_id FROM warehouse WHERE character_id=$1", s.charID).Scan(&t) err := s.server.db.QueryRow("SELECT character_id FROM warehouse WHERE character_id=$1", s.charID).Scan(&t)
if err != nil { if err != nil {
_, _ = s.server.db.Exec("INSERT INTO warehouse (character_id) VALUES ($1)", s.charID) if _, err := s.server.db.Exec("INSERT INTO warehouse (character_id) VALUES ($1)", s.charID); err != nil {
s.logger.Error("Failed to initialize warehouse", zap.Error(err))
}
} }
} }
@@ -418,9 +432,13 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {
case 2: case 2:
switch pkt.BoxType { switch pkt.BoxType {
case 0: case 0:
_, _ = s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET item%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID) if _, err := s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET item%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID); err != nil {
s.logger.Error("Failed to rename warehouse item box", zap.Error(err))
}
case 1: case 1:
_, _ = s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET equip%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID) if _, err := s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET equip%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID); err != nil {
s.logger.Error("Failed to rename warehouse equip box", zap.Error(err))
}
} }
case 3: case 3:
bf.WriteUint32(0) // Usage renewal time, >1 = disabled bf.WriteUint32(0) // Usage renewal time, >1 = disabled
@@ -443,7 +461,9 @@ func addWarehouseItem(s *Session, item mhfitem.MHFItemStack) {
giftBox := warehouseGetItems(s, 10) giftBox := warehouseGetItems(s, 10)
item.WarehouseID = token.RNG.Uint32() item.WarehouseID = token.RNG.Uint32()
giftBox = append(giftBox, item) giftBox = append(giftBox, item)
_, _ = s.server.db.Exec("UPDATE warehouse SET item10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseItems(giftBox), s.charID) if _, err := s.server.db.Exec("UPDATE warehouse SET item10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseItems(giftBox), s.charID); err != nil {
s.logger.Error("Failed to update warehouse gift box", zap.Error(err))
}
} }
func warehouseGetItems(s *Session, index uint8) []mhfitem.MHFItemStack { func warehouseGetItems(s *Session, index uint8) []mhfitem.MHFItemStack {

View File

@@ -216,7 +216,9 @@ func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) {
return return
} }
_, _ = s.server.db.Exec(`UPDATE mail SET read = true WHERE id = $1`, mail.ID) if _, err := s.server.db.Exec(`UPDATE mail SET read = true WHERE id = $1`, mail.ID); err != nil {
s.logger.Error("Failed to mark mail as read", zap.Error(err))
}
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
body := stringsupport.UTF8ToSJIS(mail.Body) body := stringsupport.UTF8ToSJIS(mail.Body)
bf.WriteNullTerminatedBytes(body) bf.WriteNullTerminatedBytes(body)
@@ -303,13 +305,21 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) {
switch pkt.Operation { switch pkt.Operation {
case mhfpacket.OperateMailDelete: case mhfpacket.OperateMailDelete:
_, _ = s.server.db.Exec(`UPDATE mail SET deleted = true WHERE id = $1`, mail.ID) if _, err := s.server.db.Exec(`UPDATE mail SET deleted = true WHERE id = $1`, mail.ID); err != nil {
s.logger.Error("Failed to delete mail", zap.Error(err))
}
case mhfpacket.OperateMailLock: case mhfpacket.OperateMailLock:
_, _ = s.server.db.Exec(`UPDATE mail SET locked = TRUE WHERE id = $1`, mail.ID) if _, err := s.server.db.Exec(`UPDATE mail SET locked = TRUE WHERE id = $1`, mail.ID); err != nil {
s.logger.Error("Failed to lock mail", zap.Error(err))
}
case mhfpacket.OperateMailUnlock: case mhfpacket.OperateMailUnlock:
_, _ = s.server.db.Exec(`UPDATE mail SET locked = FALSE WHERE id = $1`, mail.ID) if _, err := s.server.db.Exec(`UPDATE mail SET locked = FALSE WHERE id = $1`, mail.ID); err != nil {
s.logger.Error("Failed to unlock mail", zap.Error(err))
}
case mhfpacket.OperateMailAcquireItem: case mhfpacket.OperateMailAcquireItem:
_, _ = s.server.db.Exec(`UPDATE mail SET attached_item_received = TRUE WHERE id = $1`, mail.ID) if _, err := s.server.db.Exec(`UPDATE mail SET attached_item_received = TRUE WHERE id = $1`, mail.ID); err != nil {
s.logger.Error("Failed to mark mail item received", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -178,7 +178,9 @@ func handleMsgMhfCreateMercenary(s *Session, p mhfpacket.MHFPacket) {
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
var nextID uint32 var nextID uint32
_ = s.server.db.QueryRow("SELECT nextval('rasta_id_seq')").Scan(&nextID) _ = s.server.db.QueryRow("SELECT nextval('rasta_id_seq')").Scan(&nextID)
_, _ = s.server.db.Exec("UPDATE characters SET rasta_id=$1 WHERE id=$2", nextID, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET rasta_id=$1 WHERE id=$2", nextID, s.charID); err != nil {
s.logger.Error("Failed to set rasta ID", zap.Error(err))
}
bf.WriteUint32(nextID) bf.WriteUint32(nextID)
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
} }
@@ -188,9 +190,13 @@ func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) {
dumpSaveData(s, pkt.MercData, "mercenary") dumpSaveData(s, pkt.MercData, "mercenary")
if len(pkt.MercData) > 0 { if len(pkt.MercData) > 0 {
temp := byteframe.NewByteFrameFromBytes(pkt.MercData) temp := byteframe.NewByteFrameFromBytes(pkt.MercData)
_, _ = s.server.db.Exec("UPDATE characters SET savemercenary=$1, rasta_id=$2 WHERE id=$3", pkt.MercData, temp.ReadUint32(), s.charID) if _, err := s.server.db.Exec("UPDATE characters SET savemercenary=$1, rasta_id=$2 WHERE id=$3", pkt.MercData, temp.ReadUint32(), s.charID); err != nil {
s.logger.Error("Failed to save mercenary data", zap.Error(err))
}
}
if _, err := s.server.db.Exec("UPDATE characters SET gcp=$1, pact_id=$2 WHERE id=$3", pkt.GCP, pkt.PactMercID, s.charID); err != nil {
s.logger.Error("Failed to update GCP and pact ID", zap.Error(err))
} }
_, _ = s.server.db.Exec("UPDATE characters SET gcp=$1, pact_id=$2 WHERE id=$3", pkt.GCP, pkt.PactMercID, s.charID)
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} }
@@ -273,11 +279,17 @@ func handleMsgMhfContractMercenary(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfContractMercenary) pkt := p.(*mhfpacket.MsgMhfContractMercenary)
switch pkt.Op { switch pkt.Op {
case 0: // Form loan case 0: // Form loan
_, _ = s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID) if _, err := s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID); err != nil {
s.logger.Error("Failed to form mercenary loan", zap.Error(err))
}
case 1: // Cancel lend case 1: // Cancel lend
_, _ = s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.charID) if _, err := s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.charID); err != nil {
s.logger.Error("Failed to cancel mercenary lend", zap.Error(err))
}
case 2: // Cancel loan case 2: // Cancel loan
_, _ = s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", pkt.CID) if _, err := s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", pkt.CID); err != nil {
s.logger.Error("Failed to cancel mercenary loan", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -332,7 +344,9 @@ func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) {
s.logger.Error("Failed to compress airou", zap.Error(err)) s.logger.Error("Failed to compress airou", zap.Error(err))
} else { } else {
comp = append([]byte{0x01}, comp...) comp = append([]byte{0x01}, comp...)
_, _ = s.server.db.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", comp, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", comp, s.charID); err != nil {
s.logger.Error("Failed to save otomoairou", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -206,7 +206,9 @@ func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfSaveFavoriteQuest) pkt := p.(*mhfpacket.MsgMhfSaveFavoriteQuest)
dumpSaveData(s, pkt.Data, "favquest") dumpSaveData(s, pkt.Data, "favquest")
_, _ = s.server.db.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.charID) if _, err := s.server.db.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.charID); err != nil {
s.logger.Error("Failed to save favorite quest", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} }

View File

@@ -33,9 +33,13 @@ func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) {
var t int var t int
err = s.server.db.QueryRow("SELECT character_id FROM rengoku_score WHERE character_id=$1", s.charID).Scan(&t) err = s.server.db.QueryRow("SELECT character_id FROM rengoku_score WHERE character_id=$1", s.charID).Scan(&t)
if err != nil { if err != nil {
_, _ = s.server.db.Exec("INSERT INTO rengoku_score (character_id) VALUES ($1)", s.charID) if _, err := s.server.db.Exec("INSERT INTO rengoku_score (character_id) VALUES ($1)", s.charID); err != nil {
s.logger.Error("Failed to insert rengoku score", zap.Error(err))
}
}
if _, err := s.server.db.Exec("UPDATE rengoku_score SET max_stages_mp=$1, max_points_mp=$2, max_stages_sp=$3, max_points_sp=$4 WHERE character_id=$5", maxStageMp, maxScoreMp, maxStageSp, maxScoreSp, s.charID); err != nil {
s.logger.Error("Failed to update rengoku score", zap.Error(err))
} }
_, _ = s.server.db.Exec("UPDATE rengoku_score SET max_stages_mp=$1, max_points_mp=$2, max_stages_sp=$3, max_points_sp=$4 WHERE character_id=$5", maxStageMp, maxScoreMp, maxStageSp, maxScoreSp, s.charID)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -6,6 +6,8 @@ import (
_config "erupe-ce/config" _config "erupe-ce/config"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"math/rand" "math/rand"
"go.uber.org/zap"
) )
type ShopItem struct { type ShopItem struct {
@@ -270,11 +272,13 @@ func handleMsgMhfAcquireExchangeShop(s *Session, p mhfpacket.MHFPacket) {
continue continue
} }
buyCount := bf.ReadUint32() buyCount := bf.ReadUint32()
_, _ = s.server.db.Exec(`INSERT INTO shop_items_bought (character_id, shop_item_id, bought) if _, err := s.server.db.Exec(`INSERT INTO shop_items_bought (character_id, shop_item_id, bought)
VALUES ($1,$2,$3) ON CONFLICT (character_id, shop_item_id) VALUES ($1,$2,$3) ON CONFLICT (character_id, shop_item_id)
DO UPDATE SET bought = bought + $3 DO UPDATE SET bought = bought + $3
WHERE EXCLUDED.character_id=$1 AND EXCLUDED.shop_item_id=$2 WHERE EXCLUDED.character_id=$1 AND EXCLUDED.shop_item_id=$2
`, s.charID, itemHash, buyCount) `, s.charID, itemHash, buyCount); err != nil {
s.logger.Error("Failed to update shop item purchase count", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} }
@@ -300,10 +304,14 @@ func handleMsgMhfGetGachaPoint(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfUseGachaPoint(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfUseGachaPoint(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUseGachaPoint) pkt := p.(*mhfpacket.MsgMhfUseGachaPoint)
if pkt.TrialCoins > 0 { if pkt.TrialCoins > 0 {
_, _ = s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.TrialCoins, s.charID) if _, err := s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.TrialCoins, s.charID); err != nil {
s.logger.Error("Failed to deduct gacha trial coins", zap.Error(err))
}
} }
if pkt.PremiumCoins > 0 { if pkt.PremiumCoins > 0 {
_, _ = s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.PremiumCoins, s.charID) if _, err := s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.PremiumCoins, s.charID); err != nil {
s.logger.Error("Failed to deduct gacha premium coins", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -312,9 +320,13 @@ func spendGachaCoin(s *Session, quantity uint16) {
var gt uint16 var gt uint16
_ = s.server.db.QueryRow(`SELECT COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&gt) _ = s.server.db.QueryRow(`SELECT COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&gt)
if quantity <= gt { if quantity <= gt {
_, _ = s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID) if _, err := s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID); err != nil {
s.logger.Error("Failed to deduct gacha trial coins", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID) if _, err := s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID); err != nil {
s.logger.Error("Failed to deduct gacha premium coins", zap.Error(err))
}
} }
} }
@@ -343,7 +355,9 @@ func transactGacha(s *Session, gachaID uint32, rollID uint8) (int, error) {
case 20: case 20:
spendGachaCoin(s, itemNumber) spendGachaCoin(s, itemNumber)
case 21: case 21:
_, _ = s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", itemNumber, s.charID) if _, err := s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", itemNumber, s.charID); err != nil {
s.logger.Error("Failed to deduct frontier points for gacha", zap.Error(err))
}
} }
return rolls, nil return rolls, nil
} }
@@ -383,7 +397,9 @@ func addGachaItem(s *Session, items []GachaItem) {
newItem.WriteUint16(items[i].ItemID) newItem.WriteUint16(items[i].ItemID)
newItem.WriteUint16(items[i].Quantity) newItem.WriteUint16(items[i].Quantity)
} }
_, _ = s.server.db.Exec(`UPDATE characters SET gacha_items = $1 WHERE id = $2`, newItem.Data(), s.charID) if _, err := s.server.db.Exec(`UPDATE characters SET gacha_items = $1 WHERE id = $2`, newItem.Data(), s.charID); err != nil {
s.logger.Error("Failed to update gacha items", zap.Error(err))
}
} }
func getRandomEntries(entries []GachaEntry, rolls int, isBox bool) ([]GachaEntry, error) { func getRandomEntries(entries []GachaEntry, rolls int, isBox bool) ([]GachaEntry, error) {
@@ -436,9 +452,13 @@ func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) {
update := byteframe.NewByteFrame() update := byteframe.NewByteFrame()
update.WriteUint8(uint8(len(data[181:]) / 5)) update.WriteUint8(uint8(len(data[181:]) / 5))
update.WriteBytes(data[181:]) update.WriteBytes(data[181:])
_, _ = s.server.db.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", update.Data(), s.charID) if _, err := s.server.db.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", update.Data(), s.charID); err != nil {
s.logger.Error("Failed to update gacha items overflow", zap.Error(err))
}
} else { } else {
_, _ = s.server.db.Exec("UPDATE characters SET gacha_items = null WHERE id = $1", s.charID) if _, err := s.server.db.Exec("UPDATE characters SET gacha_items = null WHERE id = $1", s.charID); err != nil {
s.logger.Error("Failed to clear gacha items", zap.Error(err))
}
} }
} }
} }
@@ -507,9 +527,15 @@ func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1)) doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
return return
} }
_, _ = s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+(SELECT frontier_points FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.GachaID, pkt.RollType, s.charID) if _, err := s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+(SELECT frontier_points FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.GachaID, pkt.RollType, s.charID); err != nil {
_, _ = s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID) s.logger.Error("Failed to award stepup gacha frontier points", zap.Error(err))
_, _ = s.server.db.Exec(`INSERT INTO gacha_stepup (gacha_id, step, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, pkt.RollType+1, s.charID) }
if _, err := s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID); err != nil {
s.logger.Error("Failed to delete gacha stepup state", zap.Error(err))
}
if _, err := s.server.db.Exec(`INSERT INTO gacha_stepup (gacha_id, step, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, pkt.RollType+1, s.charID); err != nil {
s.logger.Error("Failed to insert gacha stepup state", zap.Error(err))
}
rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID) rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID)
if err != nil { if err != nil {
@@ -567,7 +593,9 @@ func handleMsgMhfGetStepupStatus(s *Session, p mhfpacket.MHFPacket) {
var stepCheck int var stepCheck int
_ = s.server.db.QueryRow(`SELECT COUNT(1) FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, pkt.GachaID, step).Scan(&stepCheck) _ = s.server.db.QueryRow(`SELECT COUNT(1) FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, pkt.GachaID, step).Scan(&stepCheck)
if stepCheck == 0 { if stepCheck == 0 {
_, _ = s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID) if _, err := s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID); err != nil {
s.logger.Error("Failed to reset gacha stepup state", zap.Error(err))
}
step = 0 step = 0
} }
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
@@ -627,7 +655,9 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) {
if err != nil { if err != nil {
continue continue
} }
_, _ = s.server.db.Exec(`INSERT INTO gacha_box (gacha_id, entry_id, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, rewardEntries[i].ID, s.charID) if _, err := s.server.db.Exec(`INSERT INTO gacha_box (gacha_id, entry_id, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, rewardEntries[i].ID, s.charID); err != nil {
s.logger.Error("Failed to insert gacha box entry", zap.Error(err))
}
for items.Next() { for items.Next() {
err = items.StructScan(&reward) err = items.StructScan(&reward)
if err == nil { if err == nil {
@@ -648,7 +678,9 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfResetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfResetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfResetBoxGachaInfo) pkt := p.(*mhfpacket.MsgMhfResetBoxGachaInfo)
_, _ = s.server.db.Exec("DELETE FROM gacha_box WHERE gacha_id = $1 AND character_id = $2", pkt.GachaID, s.charID) if _, err := s.server.db.Exec("DELETE FROM gacha_box WHERE gacha_id = $1 AND character_id = $2", pkt.GachaID, s.charID); err != nil {
s.logger.Error("Failed to reset gacha box", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }

View File

@@ -65,7 +65,9 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), COALESCE(skills, $1) FROM tower WHERE char_id=$2 err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), COALESCE(skills, $1) FROM tower WHERE char_id=$2
`, EmptyTowerCSV(64), s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Floors, &towerInfo.Level[1].Floors, &tempSkills) `, EmptyTowerCSV(64), s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Floors, &towerInfo.Level[1].Floors, &tempSkills)
if err != nil { if err != nil {
_, _ = s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID) if _, err := s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID); err != nil {
s.logger.Error("Failed to initialize tower data", zap.Error(err))
}
} }
if _config.ErupeConfig.RealClientMode <= _config.G7 { if _config.ErupeConfig.RealClientMode <= _config.G7 {
@@ -143,10 +145,14 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
case 2: case 2:
var skills string var skills string
_ = s.server.db.QueryRow(`SELECT COALESCE(skills, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(64), s.charID).Scan(&skills) _ = s.server.db.QueryRow(`SELECT COALESCE(skills, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(64), s.charID).Scan(&skills)
_, _ = s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Skill), stringsupport.CSVGetIndex(skills, int(pkt.Skill))+1), pkt.Cost, s.charID) if _, err := s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Skill), stringsupport.CSVGetIndex(skills, int(pkt.Skill))+1), pkt.Cost, s.charID); err != nil {
s.logger.Error("Failed to update tower skills", zap.Error(err))
}
case 1, 7: case 1, 7:
// This might give too much TSP? No idea what the rate is supposed to be // This might give too much TSP? No idea what the rate is supposed to be
_, _ = s.server.db.Exec(`UPDATE tower SET tr=$1, trp=COALESCE(trp, 0)+$2, tsp=COALESCE(tsp, 0)+$3, block1=COALESCE(block1, 0)+$4 WHERE char_id=$5`, pkt.TR, pkt.TRP, pkt.Cost, pkt.Block1, s.charID) if _, err := s.server.db.Exec(`UPDATE tower SET tr=$1, trp=COALESCE(trp, 0)+$2, tsp=COALESCE(tsp, 0)+$3, block1=COALESCE(block1, 0)+$4 WHERE char_id=$5`, pkt.TR, pkt.TRP, pkt.Cost, pkt.Block1, s.charID); err != nil {
s.logger.Error("Failed to update tower progress", zap.Error(err))
}
} }
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
} }
@@ -382,12 +388,18 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) {
sd.RP -= pkt.DonatedRP sd.RP -= pkt.DonatedRP
sd.Save(s) sd.Save(s)
if donated+int(pkt.DonatedRP) >= requirement { if donated+int(pkt.DonatedRP) >= requirement {
_, _ = s.server.db.Exec(`UPDATE guilds SET tower_mission_page=tower_mission_page+1 WHERE id=$1`, pkt.GuildID) if _, err := s.server.db.Exec(`UPDATE guilds SET tower_mission_page=tower_mission_page+1 WHERE id=$1`, pkt.GuildID); err != nil {
_, _ = s.server.db.Exec(`UPDATE guild_characters SET tower_mission_1=NULL, tower_mission_2=NULL, tower_mission_3=NULL WHERE guild_id=$1`, pkt.GuildID) s.logger.Error("Failed to advance tower mission page", zap.Error(err))
}
if _, err := s.server.db.Exec(`UPDATE guild_characters SET tower_mission_1=NULL, tower_mission_2=NULL, tower_mission_3=NULL WHERE guild_id=$1`, pkt.GuildID); err != nil {
s.logger.Error("Failed to reset tower mission progress", zap.Error(err))
}
pkt.DonatedRP = uint16(requirement - donated) pkt.DonatedRP = uint16(requirement - donated)
} }
bf.WriteUint32(uint32(pkt.DonatedRP)) bf.WriteUint32(uint32(pkt.DonatedRP))
_, _ = s.server.db.Exec(`UPDATE guilds SET tower_rp=tower_rp+$1 WHERE id=$2`, pkt.DonatedRP, pkt.GuildID) if _, err := s.server.db.Exec(`UPDATE guilds SET tower_rp=tower_rp+$1 WHERE id=$2`, pkt.DonatedRP, pkt.GuildID); err != nil {
s.logger.Error("Failed to update guild tower RP", zap.Error(err))
}
} else { } else {
bf.WriteUint32(0) bf.WriteUint32(0)
} }
@@ -486,7 +498,9 @@ func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {
switch pkt.Op { switch pkt.Op {
case 1: // Add gem case 1: // Add gem
i := int((pkt.Gem >> 8 * 5) + (pkt.Gem - pkt.Gem&0xFF00 - 1%5)) i := int((pkt.Gem >> 8 * 5) + (pkt.Gem - pkt.Gem&0xFF00 - 1%5))
_, _ = s.server.db.Exec(`UPDATE tower SET gems=$1 WHERE char_id=$2`, stringsupport.CSVSetIndex(gems, i, stringsupport.CSVGetIndex(gems, i)+int(pkt.Quantity)), s.charID) if _, err := s.server.db.Exec(`UPDATE tower SET gems=$1 WHERE char_id=$2`, stringsupport.CSVSetIndex(gems, i, stringsupport.CSVGetIndex(gems, i)+int(pkt.Quantity)), s.charID); err != nil {
s.logger.Error("Failed to update tower gems", zap.Error(err))
}
case 2: // Transfer gem case 2: // Transfer gem
// no way im doing this for now // no way im doing this for now
} }

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"erupe-ce/network/mhfpacket" "erupe-ce/network/mhfpacket"
"go.uber.org/zap"
) )
func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {}
@@ -19,10 +20,14 @@ func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
var exists []byte var exists []byte
err := s.server.db.QueryRow("SELECT type2 FROM user_binary 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_binary (id) VALUES ($1)", s.charID) if _, err := s.server.db.Exec("INSERT INTO user_binary (id) VALUES ($1)", s.charID); err != nil {
s.logger.Error("Failed to insert user binary", zap.Error(err))
}
} }
_, _ = s.server.db.Exec(fmt.Sprintf("UPDATE user_binary SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.charID) if _, err := s.server.db.Exec(fmt.Sprintf("UPDATE user_binary SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.charID); err != nil {
s.logger.Error("Failed to update user binary", zap.Error(err))
}
msg := &mhfpacket.MsgSysNotifyUserBinary{ msg := &mhfpacket.MsgSysNotifyUserBinary{
CharID: s.charID, CharID: s.charID,