mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-26 09:33:02 +01:00
Binary I/O (#5): all 12 remaining encoding/binary calls are legitimate (zero-alloc spot-reads, random-access into game blobs). Copy-paste handlers (#8): loadCharacterData/saveCharacterData helpers now cover standard blob patterns. Also upgrades saveCharacterData to send doAckSimpleFail on oversize payloads and DB errors, and migrates handleMsgMhfSaveScenarioData to the improved helper.
111 lines
3.4 KiB
Go
111 lines
3.4 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"erupe-ce/common/byteframe"
|
|
"erupe-ce/common/mhfcourse"
|
|
"erupe-ce/network/mhfpacket"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// Temporary function to just return no results for a MSG_MHF_ENUMERATE* packet
|
|
func stubEnumerateNoResults(s *Session, ackHandle uint32) {
|
|
enumBf := byteframe.NewByteFrame()
|
|
enumBf.WriteUint32(0) // Entry count (count for quests, rankings, events, etc.)
|
|
|
|
doAckBufSucceed(s, ackHandle, enumBf.Data())
|
|
}
|
|
|
|
func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteUint32(uint32(s.server.erupeConfig.EarthID))
|
|
bf.WriteUint32(0)
|
|
bf.WriteUint32(0)
|
|
bf.WriteUint32(uint32(len(data)))
|
|
for i := range data {
|
|
bf.WriteBytes(data[i].Data())
|
|
}
|
|
doAckBufSucceed(s, ackHandle, bf.Data())
|
|
}
|
|
|
|
func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) {
|
|
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
|
AckHandle: ackHandle,
|
|
IsBufferResponse: true,
|
|
ErrorCode: 0,
|
|
AckData: data,
|
|
})
|
|
}
|
|
|
|
func doAckBufFail(s *Session, ackHandle uint32, data []byte) {
|
|
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
|
AckHandle: ackHandle,
|
|
IsBufferResponse: true,
|
|
ErrorCode: 1,
|
|
AckData: data,
|
|
})
|
|
}
|
|
|
|
func doAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) {
|
|
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
|
AckHandle: ackHandle,
|
|
IsBufferResponse: false,
|
|
ErrorCode: 0,
|
|
AckData: data,
|
|
})
|
|
}
|
|
|
|
func doAckSimpleFail(s *Session, ackHandle uint32, data []byte) {
|
|
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
|
AckHandle: ackHandle,
|
|
IsBufferResponse: false,
|
|
ErrorCode: 1,
|
|
AckData: data,
|
|
})
|
|
}
|
|
|
|
// loadCharacterData loads a column from the characters table and sends it as
|
|
// a buffered ack response. If the data is empty/nil, defaultData is sent instead.
|
|
func loadCharacterData(s *Session, ackHandle uint32, column string, defaultData []byte) {
|
|
var data []byte
|
|
err := s.server.db.QueryRow("SELECT "+column+" FROM characters WHERE id = $1", s.charID).Scan(&data)
|
|
if err != nil {
|
|
s.logger.Error("Failed to load "+column, zap.Error(err))
|
|
}
|
|
if len(data) == 0 && defaultData != nil {
|
|
data = defaultData
|
|
}
|
|
doAckBufSucceed(s, ackHandle, data)
|
|
}
|
|
|
|
// saveCharacterData saves data to a column in the characters table with size
|
|
// validation, optional save dump, and a simple ack response.
|
|
func saveCharacterData(s *Session, ackHandle uint32, column string, data []byte, maxSize int) {
|
|
if maxSize > 0 && len(data) > maxSize {
|
|
s.logger.Warn("Payload too large for "+column, zap.Int("len", len(data)), zap.Int("max", maxSize))
|
|
doAckSimpleFail(s, ackHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
dumpSaveData(s, data, column)
|
|
_, err := s.server.db.Exec("UPDATE characters SET "+column+"=$1 WHERE id=$2", data, s.charID)
|
|
if err != nil {
|
|
s.logger.Error("Failed to save "+column, zap.Error(err))
|
|
doAckSimpleFail(s, ackHandle, make([]byte, 4))
|
|
return
|
|
}
|
|
doAckSimpleSucceed(s, ackHandle, make([]byte, 4))
|
|
}
|
|
|
|
func updateRights(s *Session) {
|
|
rightsInt := uint32(2)
|
|
_ = 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)
|
|
s.courses, rightsInt = mhfcourse.GetCourseStruct(rightsInt, s.server.erupeConfig.DefaultCourses)
|
|
update := &mhfpacket.MsgSysUpdateRight{
|
|
ClientRespAckHandle: 0,
|
|
Bitfield: rightsInt,
|
|
Rights: s.courses,
|
|
TokenLength: 0,
|
|
}
|
|
s.QueueSendMHFNonBlocking(update)
|
|
}
|