mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
fix: handle Query/QueryRow/transaction errors in channel server handlers
Add error checking and logging for ~25 database call sites that were silently dropping errors, preventing resource leaks (unclosed rows), nil pointer panics, and silent data corruption in festa transactions.
This commit is contained in:
@@ -147,7 +147,9 @@ func parseChatCommand(s *Session, command string) {
|
||||
case commands["Timer"].Prefix:
|
||||
if commands["Timer"].Enabled || s.isOp() {
|
||||
var state bool
|
||||
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)
|
||||
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.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 state {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.timer.disabled)
|
||||
@@ -161,7 +163,9 @@ func parseChatCommand(s *Session, command string) {
|
||||
if commands["PSN"].Enabled || s.isOp() {
|
||||
if len(args) > 1 {
|
||||
var exists int
|
||||
s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists)
|
||||
if err := s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists); err != nil {
|
||||
s.logger.Error("Failed to check PSN ID existence", zap.Error(err))
|
||||
}
|
||||
if exists == 0 {
|
||||
_, err := s.server.db.Exec(`UPDATE users u SET psn_id=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, args[1], s.charID)
|
||||
if err == nil {
|
||||
@@ -435,7 +439,9 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x03 && len(pkt.RawDataPayload) == 0x10 {
|
||||
if tmp.ReadUint16() == 0x0002 && tmp.ReadUint8() == 0x18 {
|
||||
var timer bool
|
||||
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(&timer)
|
||||
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(&timer); err != nil {
|
||||
s.logger.Error("Failed to get timer setting", zap.Error(err))
|
||||
}
|
||||
if timer {
|
||||
_ = tmp.ReadBytes(9)
|
||||
tmp.SetLE()
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func cleanupDiva(s *Session) {
|
||||
@@ -64,9 +65,14 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
id, start := uint32(0xCAFEBEEF), uint32(0)
|
||||
rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'")
|
||||
for rows.Next() {
|
||||
rows.Scan(&id, &start)
|
||||
rows, err := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'")
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query diva schedule", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
rows.Scan(&id, &start)
|
||||
}
|
||||
}
|
||||
|
||||
var timestamps []uint32
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"erupe-ce/common/token"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"go.uber.org/zap"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
@@ -19,7 +20,9 @@ func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadMezfesData)
|
||||
var data []byte
|
||||
s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data)
|
||||
if err := s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data); err != nil {
|
||||
s.logger.Error("Failed to load mezfes data", zap.Error(err))
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
if len(data) > 0 {
|
||||
bf.WriteBytes(data)
|
||||
@@ -168,9 +171,14 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
id, start := uint32(0xDEADBEEF), uint32(0)
|
||||
rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'")
|
||||
for rows.Next() {
|
||||
rows.Scan(&id, &start)
|
||||
rows, err := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'")
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query festa schedule", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
rows.Scan(&id, &start)
|
||||
}
|
||||
}
|
||||
|
||||
var timestamps []uint32
|
||||
@@ -190,8 +198,12 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
var blueSouls, redSouls uint32
|
||||
s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls)
|
||||
s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls)
|
||||
if err := s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls); err != nil {
|
||||
s.logger.Error("Failed to get blue souls", zap.Error(err))
|
||||
}
|
||||
if err := s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls); err != nil {
|
||||
s.logger.Error("Failed to get red souls", zap.Error(err))
|
||||
}
|
||||
|
||||
bf.WriteUint32(id)
|
||||
for _, timestamp := range timestamps {
|
||||
@@ -206,7 +218,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
var trials []FestaTrial
|
||||
var trial FestaTrial
|
||||
rows, _ = s.server.db.Queryx(`SELECT ft.*,
|
||||
rows, err = s.server.db.Queryx(`SELECT ft.*,
|
||||
COALESCE(CASE
|
||||
WHEN COUNT(gc.id) FILTER (WHERE fr.team = 'blue' AND gc.trial_vote = ft.id) >
|
||||
COUNT(gc.id) FILTER (WHERE fr.team = 'red' AND gc.trial_vote = ft.id)
|
||||
@@ -219,12 +231,16 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
LEFT JOIN public.guild_characters gc ON ft.id = gc.trial_vote
|
||||
LEFT JOIN public.festa_registrations fr ON gc.guild_id = fr.guild_id
|
||||
GROUP BY ft.id`)
|
||||
for rows.Next() {
|
||||
err := rows.StructScan(&trial)
|
||||
if err != nil {
|
||||
continue
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query festa trials", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
if err := rows.StructScan(&trial); err != nil {
|
||||
continue
|
||||
}
|
||||
trials = append(trials, trial)
|
||||
}
|
||||
trials = append(trials, trial)
|
||||
}
|
||||
bf.WriteUint16(uint16(len(trials)))
|
||||
for _, trial := range trials {
|
||||
@@ -300,7 +316,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
var guildID uint32
|
||||
var guildName string
|
||||
var guildTeam = FestivalColorNone
|
||||
s.server.db.QueryRow(`
|
||||
if err := s.server.db.QueryRow(`
|
||||
SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _
|
||||
FROM festa_submissions fs
|
||||
LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id
|
||||
@@ -308,7 +324,9 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
WHERE fs.trial_type = $1
|
||||
GROUP BY fs.guild_id, g.name, fr.team
|
||||
ORDER BY _ DESC LIMIT 1
|
||||
`, i+1).Scan(&guildID, &guildName, &guildTeam, &temp)
|
||||
`, i+1).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil {
|
||||
s.logger.Error("Failed to get festa trial ranking", zap.Error(err))
|
||||
}
|
||||
bf.WriteUint32(guildID)
|
||||
bf.WriteUint16(i + 1)
|
||||
bf.WriteInt16(FestivalColorCodes[guildTeam])
|
||||
@@ -320,7 +338,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
var guildName string
|
||||
var guildTeam = FestivalColorNone
|
||||
offset := 86400 * uint32(i)
|
||||
s.server.db.QueryRow(`
|
||||
if err := s.server.db.QueryRow(`
|
||||
SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _
|
||||
FROM festa_submissions fs
|
||||
LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id
|
||||
@@ -328,7 +346,9 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
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
|
||||
ORDER BY _ DESC LIMIT 1
|
||||
`, timestamps[1]+offset, timestamps[1]+offset+86400).Scan(&guildID, &guildName, &guildTeam, &temp)
|
||||
`, timestamps[1]+offset, timestamps[1]+offset+86400).Scan(&guildID, &guildName, &guildTeam, &temp); err != nil {
|
||||
s.logger.Error("Failed to get festa daily ranking", zap.Error(err))
|
||||
}
|
||||
bf.WriteUint32(guildID)
|
||||
bf.WriteUint16(i + 1)
|
||||
bf.WriteInt16(FestivalColorCodes[guildTeam])
|
||||
@@ -366,7 +386,9 @@ func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) {
|
||||
return
|
||||
}
|
||||
var souls, exists uint32
|
||||
s.server.db.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.charID).Scan(&souls)
|
||||
if err := s.server.db.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.charID).Scan(&souls); err != nil {
|
||||
s.logger.Error("Failed to get festa user souls", zap.Error(err))
|
||||
}
|
||||
err = s.server.db.QueryRow("SELECT prize_id FROM festa_prizes_accepted WHERE prize_id=0 AND character_id=$1", s.charID).Scan(&exists)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(souls)
|
||||
@@ -469,14 +491,22 @@ func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfChargeFesta)
|
||||
tx, _ := s.server.db.Begin()
|
||||
for i := range pkt.Souls {
|
||||
if pkt.Souls[i] == 0 {
|
||||
continue
|
||||
tx, err := s.server.db.Begin()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to begin festa submission transaction", zap.Error(err))
|
||||
} else {
|
||||
for i := range pkt.Souls {
|
||||
if pkt.Souls[i] == 0 {
|
||||
continue
|
||||
}
|
||||
if _, err := tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.charID, pkt.GuildID, i, pkt.Souls[i]); err != nil {
|
||||
s.logger.Error("Failed to insert festa submission", zap.Error(err))
|
||||
}
|
||||
}
|
||||
if err := tx.Commit(); err != nil {
|
||||
s.logger.Error("Failed to commit festa submissions", zap.Error(err))
|
||||
}
|
||||
_, _ = tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.charID, pkt.GuildID, i, pkt.Souls[i])
|
||||
}
|
||||
_ = tx.Commit()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -509,23 +539,27 @@ type Prize struct {
|
||||
|
||||
func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaPersonalPrize)
|
||||
rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.charID)
|
||||
rows, err := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.charID)
|
||||
var count uint32
|
||||
prizeData := byteframe.NewByteFrame()
|
||||
for rows.Next() {
|
||||
prize := &Prize{}
|
||||
err := rows.StructScan(&prize)
|
||||
if err != nil {
|
||||
continue
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query festa personal prizes", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
prize := &Prize{}
|
||||
if err := rows.StructScan(&prize); err != nil {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
prizeData.WriteUint32(prize.ID)
|
||||
prizeData.WriteUint32(prize.Tier)
|
||||
prizeData.WriteUint32(prize.SoulsReq)
|
||||
prizeData.WriteUint32(7) // Unk
|
||||
prizeData.WriteUint32(prize.ItemID)
|
||||
prizeData.WriteUint32(prize.NumItem)
|
||||
prizeData.WriteBool(prize.Claimed > 0)
|
||||
}
|
||||
count++
|
||||
prizeData.WriteUint32(prize.ID)
|
||||
prizeData.WriteUint32(prize.Tier)
|
||||
prizeData.WriteUint32(prize.SoulsReq)
|
||||
prizeData.WriteUint32(7) // Unk
|
||||
prizeData.WriteUint32(prize.ItemID)
|
||||
prizeData.WriteUint32(prize.NumItem)
|
||||
prizeData.WriteBool(prize.Claimed > 0)
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(count)
|
||||
@@ -535,23 +569,27 @@ func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket)
|
||||
|
||||
func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaIntermediatePrize)
|
||||
rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.charID)
|
||||
rows, err := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.charID)
|
||||
var count uint32
|
||||
prizeData := byteframe.NewByteFrame()
|
||||
for rows.Next() {
|
||||
prize := &Prize{}
|
||||
err := rows.StructScan(&prize)
|
||||
if err != nil {
|
||||
continue
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query festa intermediate prizes", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
prize := &Prize{}
|
||||
if err := rows.StructScan(&prize); err != nil {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
prizeData.WriteUint32(prize.ID)
|
||||
prizeData.WriteUint32(prize.Tier)
|
||||
prizeData.WriteUint32(prize.SoulsReq)
|
||||
prizeData.WriteUint32(7) // Unk
|
||||
prizeData.WriteUint32(prize.ItemID)
|
||||
prizeData.WriteUint32(prize.NumItem)
|
||||
prizeData.WriteBool(prize.Claimed > 0)
|
||||
}
|
||||
count++
|
||||
prizeData.WriteUint32(prize.ID)
|
||||
prizeData.WriteUint32(prize.Tier)
|
||||
prizeData.WriteUint32(prize.SoulsReq)
|
||||
prizeData.WriteUint32(7) // Unk
|
||||
prizeData.WriteUint32(prize.ItemID)
|
||||
prizeData.WriteUint32(prize.NumItem)
|
||||
prizeData.WriteBool(prize.Claimed > 0)
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(count)
|
||||
|
||||
@@ -763,7 +763,9 @@ func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
case mhfpacket.OperateGuildEventExchange:
|
||||
rp := uint16(pkt.Data1.ReadUint32())
|
||||
var balance uint32
|
||||
s.server.db.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, rp, guild.ID).Scan(&balance)
|
||||
if err := s.server.db.QueryRow(`UPDATE guilds SET event_rp=event_rp-$1 WHERE id=$2 RETURNING event_rp`, rp, guild.ID).Scan(&balance); err != nil {
|
||||
s.logger.Error("Failed to exchange guild event RP", zap.Error(err))
|
||||
}
|
||||
bf.WriteUint32(balance)
|
||||
default:
|
||||
panic(fmt.Sprintf("unhandled operate guild action '%d'", pkt.Action))
|
||||
@@ -811,7 +813,9 @@ func handleDonateRP(s *Session, amount uint16, guild *Guild, _type int) []byte {
|
||||
var resetRoom bool
|
||||
if _type == 2 {
|
||||
var currentRP uint16
|
||||
s.server.db.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guild.ID).Scan(¤tRP)
|
||||
if err := s.server.db.QueryRow(`SELECT room_rp FROM guilds WHERE id = $1`, guild.ID).Scan(¤tRP); err != nil {
|
||||
s.logger.Error("Failed to get guild room RP", zap.Error(err))
|
||||
}
|
||||
if currentRP+amount >= 30 {
|
||||
amount = 30 - currentRP
|
||||
resetRoom = true
|
||||
@@ -1593,7 +1597,9 @@ func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) {
|
||||
func guildGetItems(s *Session, guildID uint32) []mhfitem.MHFItemStack {
|
||||
var data []byte
|
||||
var items []mhfitem.MHFItemStack
|
||||
s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data)
|
||||
if err := s.server.db.QueryRow(`SELECT item_box FROM guilds WHERE id=$1`, guildID).Scan(&data); err != nil {
|
||||
s.logger.Error("Failed to get guild item box", zap.Error(err))
|
||||
}
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
|
||||
@@ -95,11 +95,15 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
houseQuery = `SELECT c.id, hr, gr, name, COALESCE(ub.house_state, 2) as house_state, COALESCE(ub.house_password, '') as house_password
|
||||
FROM characters c LEFT JOIN user_binary ub ON ub.id = c.id WHERE name ILIKE $1`
|
||||
house := HouseData{}
|
||||
rows, _ := s.server.db.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name))
|
||||
for rows.Next() {
|
||||
err := rows.StructScan(&house)
|
||||
if err == nil {
|
||||
houses = append(houses, house)
|
||||
rows, err := s.server.db.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name))
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query houses by name", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
if err := rows.StructScan(&house); err == nil {
|
||||
houses = append(houses, house)
|
||||
}
|
||||
}
|
||||
}
|
||||
case 4:
|
||||
|
||||
@@ -217,18 +217,22 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) {
|
||||
if pkt.Op != 2 && pkt.Op != 5 {
|
||||
var loans uint8
|
||||
temp := byteframe.NewByteFrame()
|
||||
rows, _ := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID)
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&name, &cid, &pactID)
|
||||
if err != nil {
|
||||
continue
|
||||
rows, err := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query mercenary loans", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
if err := rows.Scan(&name, &cid, &pactID); err != nil {
|
||||
continue
|
||||
}
|
||||
loans++
|
||||
temp.WriteUint32(pactID)
|
||||
temp.WriteUint32(cid)
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Unix()))
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * 7).Unix()))
|
||||
temp.WriteBytes(stringsupport.PaddedString(name, 18, true))
|
||||
}
|
||||
loans++
|
||||
temp.WriteUint32(pactID)
|
||||
temp.WriteUint32(cid)
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Unix()))
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * 7).Unix()))
|
||||
temp.WriteBytes(stringsupport.PaddedString(name, 18, true))
|
||||
}
|
||||
bf.WriteUint8(loans)
|
||||
bf.WriteBytes(temp.Data())
|
||||
|
||||
@@ -131,24 +131,31 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
scoreData := byteframe.NewByteFrame()
|
||||
|
||||
var rows *sqlx.Rows
|
||||
var err error
|
||||
switch pkt.Leaderboard {
|
||||
case 0:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery))
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery))
|
||||
case 1:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s ORDER BY max_points_mp DESC", rengokuScoreQuery))
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s ORDER BY max_points_mp DESC", rengokuScoreQuery))
|
||||
case 2:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID)
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID)
|
||||
case 3:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID)
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID)
|
||||
case 4:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s ORDER BY max_stages_sp DESC", rengokuScoreQuery))
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s ORDER BY max_stages_sp DESC", rengokuScoreQuery))
|
||||
case 5:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s ORDER BY max_points_sp DESC", rengokuScoreQuery))
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s ORDER BY max_points_sp DESC", rengokuScoreQuery))
|
||||
case 6:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID)
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID)
|
||||
case 7:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID)
|
||||
rows, err = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID)
|
||||
}
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query rengoku ranking", zap.Error(err))
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 11))
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
rows.StructScan(&score)
|
||||
|
||||
@@ -317,11 +317,16 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt.Unk3 = 3
|
||||
}
|
||||
}
|
||||
rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID)
|
||||
for rows.Next() {
|
||||
temp := TenrouiraiCharScore{}
|
||||
rows.Scan(&temp.Name, &temp.Score)
|
||||
tenrouirai.CharScore = append(tenrouirai.CharScore, temp)
|
||||
rows, err := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query tower mission scores", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
temp := TenrouiraiCharScore{}
|
||||
rows.Scan(&temp.Name, &temp.Score)
|
||||
tenrouirai.CharScore = append(tenrouirai.CharScore, temp)
|
||||
}
|
||||
}
|
||||
for _, charScore := range tenrouirai.CharScore {
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
@@ -416,10 +416,15 @@ func (s *Server) FindSessionByCharID(charID uint32) *Session {
|
||||
func (s *Server) DisconnectUser(uid uint32) {
|
||||
var cid uint32
|
||||
var cids []uint32
|
||||
rows, _ := s.db.Query(`SELECT id FROM characters WHERE user_id=$1`, uid)
|
||||
for rows.Next() {
|
||||
rows.Scan(&cid)
|
||||
cids = append(cids, cid)
|
||||
rows, err := s.db.Query(`SELECT id FROM characters WHERE user_id=$1`, uid)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to query characters for disconnect", zap.Error(err))
|
||||
} else {
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
rows.Scan(&cid)
|
||||
cids = append(cids, cid)
|
||||
}
|
||||
}
|
||||
for _, c := range s.Channels {
|
||||
for _, session := range c.sessions {
|
||||
|
||||
Reference in New Issue
Block a user