Files
Erupe/server/channelserver/handlers_cafe.go
2022-08-13 16:25:32 +10:00

179 lines
6.0 KiB
Go

package channelserver
import (
"erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring"
"erupe-ce/network/mhfpacket"
"go.uber.org/zap"
"time"
)
func handleMsgMhfAcquireCafeItem(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireCafeItem)
var netcafe_points int
err := s.server.db.QueryRow("UPDATE characters SET netcafe_points = netcafe_points - $1 WHERE id = $2 RETURNING netcafe_points", pkt.PointCost, s.charID).Scan(&netcafe_points)
if err != nil {
s.logger.Fatal("Failed to get plate data savedata from db", zap.Error(err))
}
resp := byteframe.NewByteFrame()
resp.WriteUint32(uint32(netcafe_points))
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
}
func handleMsgMhfUpdateCafepoint(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfUpdateCafepoint)
var netcafe_points int
err := s.server.db.QueryRow("SELECT COALESCE(netcafe_points, 0) FROM characters WHERE id = $1", s.charID).Scan(&netcafe_points)
if err != nil {
s.logger.Fatal("Failed to get plate data savedata from db", zap.Error(err))
}
resp := byteframe.NewByteFrame()
resp.WriteUint32(0)
resp.WriteUint32(uint32(netcafe_points))
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
}
func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfCheckDailyCafepoint)
// I am not sure exactly what this does, but all responses I have seen include this exact sequence of bytes
// 1 daily, 5 daily halk pots, 3 point boosted quests, also adds 5 netcafe points but not sent to client
// available once after midday every day
// get next midday
var t = Time_static()
year, month, day := t.Date()
midday := time.Date(year, month, day, 12, 0, 0, 0, t.Location())
if t.After(midday) {
midday = midday.Add(24 * time.Hour)
}
// get time after which daily claiming would be valid from db
var dailyTime time.Time
err := 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 err != nil {
s.logger.Fatal("Failed to get daily_time savedata from db", zap.Error(err))
}
if t.After(dailyTime) {
// +5 netcafe points and setting next valid window
_, err := s.server.db.Exec("UPDATE characters SET daily_time=$1, netcafe_points=netcafe_points::int + 5 WHERE id=$2", midday, s.charID)
if err != nil {
s.logger.Fatal("Failed to update daily_time and netcafe_points savedata in db", zap.Error(err))
}
doAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01})
} else {
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
}
}
func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetCafeDuration)
bf := byteframe.NewByteFrame()
var cafeTime uint32
err := s.server.db.QueryRow("SELECT cafe_time FROM characters WHERE id = $1", s.charID).Scan(&cafeTime)
if err != nil {
panic(err)
}
cafeTime = uint32(Time_Current_Adjusted().Unix()) - uint32(s.sessionStart) + cafeTime
bf.WriteUint32(cafeTime) // Total hours
bf.WriteUint16(0)
ps.Uint16(bf, "Resets at next maintenance", true)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
type CafeBonus struct {
ID uint32 `db:"id"`
Line uint32 `db:"line"`
ItemClass uint32 `db:"itemclass"`
ItemID uint32 `db:"itemid"`
TradeQuantity uint32 `db:"tradequantity"`
FlagCount uint8 `db:"flagcount"`
}
func handleMsgMhfGetCafeDurationBonusInfo(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetCafeDurationBonusInfo)
bf := byteframe.NewByteFrame()
var count uint32
rows, err := s.server.db.Queryx(`
SELECT cb.id, line, itemclass, itemid, tradequantity,
(
SELECT count(*)
FROM cafe_accepted ca
WHERE cb.id = ca.cafe_id AND ca.character_id = $1
) AS flagcount
FROM cafebonus cb ORDER BY id ASC;`, s.charID)
if err != nil {
s.logger.Error("Error getting cafebonus", zap.Error(err))
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
} else {
for rows.Next() {
count++
Cafes := &CafeBonus{}
err = rows.StructScan(&Cafes)
if err != nil {
s.logger.Error("Error scanning cafebonus", zap.Error(err))
}
bf.WriteUint32(Cafes.Line) // Time
bf.WriteUint32(0) // Unk
bf.WriteUint32(Cafes.ItemID)
bf.WriteUint32(Cafes.TradeQuantity)
bf.WriteUint8(Cafes.FlagCount)
}
resp := byteframe.NewByteFrame()
resp.WriteUint32(0)
resp.WriteUint32(uint32(time.Now().Unix())) //timestamp
resp.WriteUint32(count)
resp.WriteBytes(bf.Data())
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
}
func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfReceiveCafeDurationBonus)
bf := byteframe.NewByteFrame()
row := s.server.db.QueryRowx(`
SELECT c.id, c.line, itemclass, itemid, tradequantity
FROM cafebonus c
WHERE (
SELECT count(*)
FROM cafe_accepted ca
WHERE c.id = ca.cafe_id AND ca.character_id = $1
) < 1 AND (
SELECT ch.cafe_time + $2
FROM characters ch
WHERE ch.id = $1
) >= c.line LIMIT 1;`, s.charID, Time_Current_Adjusted().Unix()-s.sessionStart)
Cafe := &CafeBonus{}
err := row.StructScan(Cafe)
if err != nil {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 8))
return
}
bf.WriteUint32(1)
bf.WriteUint32(Cafe.ID)
bf.WriteUint32(Cafe.ItemClass)
bf.WriteUint32(Cafe.ItemID)
bf.WriteUint32(Cafe.TradeQuantity)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfPostCafeDurationBonusReceived)
_, err := s.server.db.Exec("INSERT INTO public.cafe_accepted VALUES ($1, $2)", pkt.CafeBonusID, s.charID)
if err != nil {
s.logger.Error("Error updating accepted CafeBonus count", zap.Error(err))
}
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfStartBoostTime)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}