mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
refactor: extract gametime package, replace fmt.Printf with zap logging
Move time utilities (TimeAdjusted, TimeMidnight, TimeWeekStart, TimeWeekNext, TimeGameAbsolute) from channelserver into common/gametime to break the inappropriate dependency where signserver, entranceserver, and api imported the 38K-line channelserver package just for time functions. Replace all fmt.Printf debug logging in sys_session.go and handlers_object.go with structured zap logging for consistent observability.
This commit is contained in:
@@ -2,8 +2,8 @@ package deltacomp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
func checkReadUint8(r *bytes.Reader) (uint8, error) {
|
||||
@@ -77,7 +77,7 @@ func ApplyDataDiff(diff []byte, baseData []byte) []byte {
|
||||
|
||||
// Grow slice if it's required
|
||||
if len(baseCopy) < dataOffset {
|
||||
fmt.Printf("Slice smaller than data offset, growing slice...")
|
||||
log.Printf("Slice smaller than data offset, growing slice...")
|
||||
baseCopy = append(baseCopy, make([]byte, (dataOffset+differentCount)-len(baseData))...)
|
||||
} else {
|
||||
length := len(baseCopy[dataOffset:])
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -34,7 +34,7 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
||||
OwnerCharID: newObj.ownerCharID,
|
||||
}
|
||||
|
||||
s.logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.id))
|
||||
s.logger.Info("Broadcasting new object", zap.String("name", s.Name), zap.Uint32("objectID", newObj.id))
|
||||
s.stage.BroadcastMHF(dupObjUpdate, s)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,13 @@ func handleMsgSysDeleteObject(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgSysPositionObject(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysPositionObject)
|
||||
if s.server.erupeConfig.DebugOptions.LogInboundMessages {
|
||||
fmt.Printf("[%s] with objectID [%d] move to (%f,%f,%f)\n\n", s.Name, pkt.ObjID, pkt.X, pkt.Y, pkt.Z)
|
||||
s.logger.Debug("Object position update",
|
||||
zap.String("name", s.Name),
|
||||
zap.Uint32("objectID", pkt.ObjID),
|
||||
zap.Float32("x", pkt.X),
|
||||
zap.Float32("y", pkt.Y),
|
||||
zap.Float32("z", pkt.Z),
|
||||
)
|
||||
}
|
||||
s.stage.Lock()
|
||||
object, ok := s.stage.objects[s.charID]
|
||||
|
||||
@@ -84,7 +84,7 @@ func NewSession(server *Server, conn net.Conn) *Session {
|
||||
rawConn: conn,
|
||||
cryptConn: network.NewCryptConn(conn),
|
||||
sendPackets: make(chan packet, 20),
|
||||
clientContext: &clientctx.ClientContext{}, // Unused
|
||||
clientContext: &clientctx.ClientContext{},
|
||||
lastPacket: time.Now(),
|
||||
objectID: server.getObjectId(),
|
||||
sessionStart: TimeAdjusted().Unix(),
|
||||
@@ -232,8 +232,7 @@ func (s *Session) handlePacketGroup(pktGroup []byte) {
|
||||
// This shouldn't be needed, but it's better to recover and let the connection die than to panic the server.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Printf("[%s]", s.Name)
|
||||
fmt.Println("Recovered from panic", r)
|
||||
s.logger.Error("Recovered from panic", zap.String("name", s.Name), zap.Any("panic", r))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -246,13 +245,16 @@ func (s *Session) handlePacketGroup(pktGroup []byte) {
|
||||
// Get the packet parser and handler for this opcode.
|
||||
mhfPkt := mhfpacket.FromOpcode(opcode)
|
||||
if mhfPkt == nil {
|
||||
fmt.Println("Got opcode which we don't know how to parse, can't parse anymore for this group")
|
||||
s.logger.Warn("Got opcode which we don't know how to parse, can't parse anymore for this group")
|
||||
return
|
||||
}
|
||||
// Parse the packet.
|
||||
err := mhfPkt.Parse(bf, s.clientContext)
|
||||
if err != nil {
|
||||
fmt.Printf("\n!!! [%s] %s NOT IMPLEMENTED !!! \n\n\n", s.Name, opcode)
|
||||
s.logger.Warn("Packet not implemented",
|
||||
zap.String("name", s.Name),
|
||||
zap.Stringer("opcode", opcode),
|
||||
)
|
||||
return
|
||||
}
|
||||
// Handle the packet.
|
||||
@@ -297,21 +299,23 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien
|
||||
if len(data) >= 6 {
|
||||
ackHandle = binary.BigEndian.Uint32(data[2:6])
|
||||
}
|
||||
if t, ok := s.ackStart[ackHandle]; ok {
|
||||
fmt.Printf("[%s] -> [%s] (%fs)\n", sender, recipient, float64(time.Now().UnixNano()-t.UnixNano())/1000000000)
|
||||
} else {
|
||||
fmt.Printf("[%s] -> [%s]\n", sender, recipient)
|
||||
fields := []zap.Field{
|
||||
zap.String("sender", sender),
|
||||
zap.String("recipient", recipient),
|
||||
zap.Uint16("opcode_dec", opcode),
|
||||
zap.String("opcode_hex", fmt.Sprintf("0x%04X", opcode)),
|
||||
zap.Stringer("opcode_name", opcodePID),
|
||||
zap.Int("data_bytes", len(data)),
|
||||
}
|
||||
if t, ok := s.ackStart[ackHandle]; ok {
|
||||
fields = append(fields, zap.Duration("ack_latency", time.Since(t)))
|
||||
}
|
||||
fmt.Printf("Opcode: (Dec: %d Hex: 0x%04X Name: %s) \n", opcode, opcode, opcodePID)
|
||||
if s.server.erupeConfig.DebugOptions.LogMessageData {
|
||||
if len(data) <= s.server.erupeConfig.DebugOptions.MaxHexdumpLength {
|
||||
fmt.Printf("Data [%d bytes]:\n%s\n", len(data), hex.Dump(data))
|
||||
} else {
|
||||
fmt.Printf("Data [%d bytes]: (Too long!)\n\n", len(data))
|
||||
fields = append(fields, zap.String("data", hex.Dump(data)))
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
s.logger.Debug("Packet", fields...)
|
||||
}
|
||||
|
||||
func (s *Session) getObjectId() uint32 {
|
||||
|
||||
@@ -1,32 +1,12 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/common/gametime"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TimeAdjusted() time.Time {
|
||||
baseTime := time.Now().In(time.FixedZone("UTC+9", 9*60*60))
|
||||
return time.Date(baseTime.Year(), baseTime.Month(), baseTime.Day(), baseTime.Hour(), baseTime.Minute(), baseTime.Second(), baseTime.Nanosecond(), baseTime.Location())
|
||||
}
|
||||
|
||||
func TimeMidnight() time.Time {
|
||||
baseTime := time.Now().In(time.FixedZone("UTC+9", 9*60*60))
|
||||
return time.Date(baseTime.Year(), baseTime.Month(), baseTime.Day(), 0, 0, 0, 0, baseTime.Location())
|
||||
}
|
||||
|
||||
func TimeWeekStart() time.Time {
|
||||
midnight := TimeMidnight()
|
||||
offset := int(midnight.Weekday()) - int(time.Monday)
|
||||
if offset < 0 {
|
||||
offset += 7
|
||||
}
|
||||
return midnight.Add(-time.Duration(offset) * 24 * time.Hour)
|
||||
}
|
||||
|
||||
func TimeWeekNext() time.Time {
|
||||
return TimeWeekStart().Add(time.Hour * 24 * 7)
|
||||
}
|
||||
|
||||
func TimeGameAbsolute() uint32 {
|
||||
return uint32((TimeAdjusted().Unix() - 2160) % 5760)
|
||||
}
|
||||
func TimeAdjusted() time.Time { return gametime.Adjusted() }
|
||||
func TimeMidnight() time.Time { return gametime.Midnight() }
|
||||
func TimeWeekStart() time.Time { return gametime.WeekStart() }
|
||||
func TimeWeekNext() time.Time { return gametime.WeekNext() }
|
||||
func TimeGameAbsolute() uint32 { return gametime.GameAbsolute() }
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestTimeAdjusted(t *testing.T) {
|
||||
result := TimeAdjusted()
|
||||
|
||||
// Should return a time in UTC+9 timezone
|
||||
_, offset := result.Zone()
|
||||
expectedOffset := 9 * 60 * 60 // 9 hours in seconds
|
||||
if offset != expectedOffset {
|
||||
t.Errorf("TimeAdjusted() zone offset = %d, want %d (UTC+9)", offset, expectedOffset)
|
||||
}
|
||||
|
||||
// The time should be close to current time (within a few seconds)
|
||||
now := time.Now()
|
||||
diff := result.Sub(now.In(time.FixedZone("UTC+9", 9*60*60)))
|
||||
if diff < -time.Second || diff > time.Second {
|
||||
t.Errorf("TimeAdjusted() time differs from expected by %v", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeMidnight(t *testing.T) {
|
||||
midnight := TimeMidnight()
|
||||
|
||||
// Should be at midnight (hour=0, minute=0, second=0, nanosecond=0)
|
||||
if midnight.Hour() != 0 {
|
||||
t.Errorf("TimeMidnight() hour = %d, want 0", midnight.Hour())
|
||||
}
|
||||
if midnight.Minute() != 0 {
|
||||
t.Errorf("TimeMidnight() minute = %d, want 0", midnight.Minute())
|
||||
}
|
||||
if midnight.Second() != 0 {
|
||||
t.Errorf("TimeMidnight() second = %d, want 0", midnight.Second())
|
||||
}
|
||||
if midnight.Nanosecond() != 0 {
|
||||
t.Errorf("TimeMidnight() nanosecond = %d, want 0", midnight.Nanosecond())
|
||||
}
|
||||
|
||||
// Should be in UTC+9 timezone
|
||||
_, offset := midnight.Zone()
|
||||
expectedOffset := 9 * 60 * 60
|
||||
if offset != expectedOffset {
|
||||
t.Errorf("TimeMidnight() zone offset = %d, want %d (UTC+9)", offset, expectedOffset)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeWeekStart(t *testing.T) {
|
||||
weekStart := TimeWeekStart()
|
||||
|
||||
// Should be on Monday (weekday = 1)
|
||||
if weekStart.Weekday() != time.Monday {
|
||||
t.Errorf("TimeWeekStart() weekday = %v, want Monday", weekStart.Weekday())
|
||||
}
|
||||
|
||||
// Should be at midnight
|
||||
if weekStart.Hour() != 0 || weekStart.Minute() != 0 || weekStart.Second() != 0 {
|
||||
t.Errorf("TimeWeekStart() should be at midnight, got %02d:%02d:%02d",
|
||||
weekStart.Hour(), weekStart.Minute(), weekStart.Second())
|
||||
}
|
||||
|
||||
// Should be in UTC+9 timezone
|
||||
_, offset := weekStart.Zone()
|
||||
expectedOffset := 9 * 60 * 60
|
||||
if offset != expectedOffset {
|
||||
t.Errorf("TimeWeekStart() zone offset = %d, want %d (UTC+9)", offset, expectedOffset)
|
||||
}
|
||||
|
||||
// Week start should be before or equal to current midnight
|
||||
midnight := TimeMidnight()
|
||||
if weekStart.After(midnight) {
|
||||
t.Errorf("TimeWeekStart() %v should be <= current midnight %v", weekStart, midnight)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeWeekNext(t *testing.T) {
|
||||
weekStart := TimeWeekStart()
|
||||
weekNext := TimeWeekNext()
|
||||
|
||||
// TimeWeekNext should be exactly 7 days after TimeWeekStart
|
||||
expectedNext := weekStart.Add(time.Hour * 24 * 7)
|
||||
if !weekNext.Equal(expectedNext) {
|
||||
t.Errorf("TimeWeekNext() = %v, want %v (7 days after WeekStart)", weekNext, expectedNext)
|
||||
}
|
||||
|
||||
// Should also be on Monday
|
||||
if weekNext.Weekday() != time.Monday {
|
||||
t.Errorf("TimeWeekNext() weekday = %v, want Monday", weekNext.Weekday())
|
||||
}
|
||||
|
||||
// Should be at midnight
|
||||
if weekNext.Hour() != 0 || weekNext.Minute() != 0 || weekNext.Second() != 0 {
|
||||
t.Errorf("TimeWeekNext() should be at midnight, got %02d:%02d:%02d",
|
||||
weekNext.Hour(), weekNext.Minute(), weekNext.Second())
|
||||
}
|
||||
|
||||
// Should be in the future relative to week start
|
||||
if !weekNext.After(weekStart) {
|
||||
t.Errorf("TimeWeekNext() %v should be after TimeWeekStart() %v", weekNext, weekStart)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeWeekStartSundayEdge(t *testing.T) {
|
||||
// When today is Sunday, the calculation should go back to last Monday
|
||||
// This is tested indirectly by verifying the weekday is always Monday
|
||||
weekStart := TimeWeekStart()
|
||||
|
||||
// Regardless of what day it is now, week start should be Monday
|
||||
if weekStart.Weekday() != time.Monday {
|
||||
t.Errorf("TimeWeekStart() on any day should return Monday, got %v", weekStart.Weekday())
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeMidnightSameDay(t *testing.T) {
|
||||
adjusted := TimeAdjusted()
|
||||
midnight := TimeMidnight()
|
||||
|
||||
// Midnight should be on the same day (year, month, day)
|
||||
if midnight.Year() != adjusted.Year() ||
|
||||
midnight.Month() != adjusted.Month() ||
|
||||
midnight.Day() != adjusted.Day() {
|
||||
t.Errorf("TimeMidnight() date = %v, want same day as TimeAdjusted() %v",
|
||||
midnight.Format("2006-01-02"), adjusted.Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeWeekDuration(t *testing.T) {
|
||||
weekStart := TimeWeekStart()
|
||||
weekNext := TimeWeekNext()
|
||||
|
||||
// Duration between week boundaries should be exactly 7 days
|
||||
duration := weekNext.Sub(weekStart)
|
||||
expectedDuration := time.Hour * 24 * 7
|
||||
|
||||
if duration != expectedDuration {
|
||||
t.Errorf("Duration between WeekStart and WeekNext = %v, want %v", duration, expectedDuration)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeZoneConsistency(t *testing.T) {
|
||||
adjusted := TimeAdjusted()
|
||||
midnight := TimeMidnight()
|
||||
weekStart := TimeWeekStart()
|
||||
weekNext := TimeWeekNext()
|
||||
|
||||
// All times should be in the same timezone (UTC+9)
|
||||
times := []struct {
|
||||
name string
|
||||
time time.Time
|
||||
}{
|
||||
{"TimeAdjusted", adjusted},
|
||||
{"TimeMidnight", midnight},
|
||||
{"TimeWeekStart", weekStart},
|
||||
{"TimeWeekNext", weekNext},
|
||||
}
|
||||
|
||||
expectedOffset := 9 * 60 * 60
|
||||
for _, tt := range times {
|
||||
_, offset := tt.time.Zone()
|
||||
if offset != expectedOffset {
|
||||
t.Errorf("%s() zone offset = %d, want %d (UTC+9)", tt.name, offset, expectedOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user