From 1d8eec2280e7e4b3881afdcb8363a93e67b16c97 Mon Sep 17 00:00:00 2001 From: Andrew Gutekanst Date: Sat, 22 Feb 2020 22:20:29 -0500 Subject: [PATCH] Implement handlers for stage movement and quest completion --- common/stringstack/stringstack.go | 40 +++++++++++++++ server/channelserver/handlers.go | 81 ++++++++++++++++++++++++++++--- server/channelserver/session.go | 15 ++++-- 3 files changed, 124 insertions(+), 12 deletions(-) create mode 100644 common/stringstack/stringstack.go diff --git a/common/stringstack/stringstack.go b/common/stringstack/stringstack.go new file mode 100644 index 000000000..aff33842e --- /dev/null +++ b/common/stringstack/stringstack.go @@ -0,0 +1,40 @@ +package stringstack + +import ( + "errors" + "sync" +) + +// StringStack is a basic LIFO "stack" for storing strings. +type StringStack struct { + sync.Mutex + stack []string +} + +// New creates a new instance of StringStack +func New() *StringStack { + return &StringStack{} +} + +// Push pushes a string onto the stack. +func (s *StringStack) Push(v string) { + s.Lock() + defer s.Unlock() + + s.stack = append(s.stack, v) +} + +// Pop pops a string from the stack. +func (s *StringStack) Pop() (string, error) { + s.Lock() + defer s.Unlock() + + if len(s.stack) == 0 { + return "", errors.New("no items on stack") + } + + x := s.stack[len(s.stack)-1] + s.stack = s.stack[:len(s.stack)-1] + + return x, nil +} diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 0b68c15a6..8dc7b26c6 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -318,7 +318,11 @@ func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) { doSizedAckResp(s, pkt.AckHandle, resp.Data()) } -func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysRecordLog) + resp := make([]byte, 8) // Unk resp. + s.QueueAck(pkt.AckHandle, resp) +} func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {} @@ -464,13 +468,39 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) { func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysEnterStage) + + // Push our current stage ID to the movement stack before entering another one. + s.Lock() + s.stageMoveStack.Push(s.stageID) + s.Unlock() + doStageTransfer(s, pkt.AckHandle, pkt.StageID) } -func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysBackStage) + + // Transfer back to the saved stage ID before the previous move or enter. + s.Lock() + backStage, err := s.stageMoveStack.Pop() + s.Unlock() + + if err != nil { + panic(err) + } + + doStageTransfer(s, pkt.AckHandle, backStage) + +} func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysMoveStage) + + // Push our current stage ID to the movement stack before entering another one. + s.Lock() + s.stageMoveStack.Push(s.stageID) + s.Unlock() + doStageTransfer(s, pkt.AckHandle, pkt.StageID) } @@ -1613,7 +1643,9 @@ func handleMsgMhfGetBoostTime(s *Session, p mhfpacket.MHFPacket) { updateRights(s) } -func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) { + //pkt := p.(*mhfpacket.MsgMhfPostBoostTime) +} func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetBoostTimeLimit) @@ -1672,7 +1704,10 @@ func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfPostBoostTimeQuestReturn(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfPostBoostTimeQuestReturn(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostBoostTimeQuestReturn) + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfGetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) {} @@ -1680,7 +1715,10 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfResetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetSeibattle) + stubGetNoResults(s, pkt.AckHandle) +} func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {} @@ -1828,7 +1866,33 @@ func handleMsgMhfGetUdMyPoint(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetUdTotalPointInfo(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetUdBonusQuestInfo(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetUdBonusQuestInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdBonusQuestInfo) + + udBonusQuestInfos := []struct { + Unk0 uint8 + Unk1 uint8 + StartTime uint32 // Unix timestamp (seconds) + EndTime uint32 // Unix timestamp (seconds) + Unk4 uint32 + Unk5 uint8 + Unk6 uint8 + }{} // Blank stub array. + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(udBonusQuestInfos))) + for _, q := range udBonusQuestInfos { + resp.WriteUint8(q.Unk0) + resp.WriteUint8(q.Unk1) + resp.WriteUint32(q.StartTime) + resp.WriteUint32(q.EndTime) + resp.WriteUint32(q.Unk4) + resp.WriteUint8(q.Unk5) + resp.WriteUint8(q.Unk6) + } + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfGetUdSelectedColorInfo(s *Session, p mhfpacket.MHFPacket) {} @@ -2086,7 +2150,10 @@ func handleMsgSysReserve18F(s *Session, p mhfpacket.MHFPacket) {} 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) + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgSysReserve192(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/session.go b/server/channelserver/session.go index 1d6c62545..002d04c93 100644 --- a/server/channelserver/session.go +++ b/server/channelserver/session.go @@ -6,6 +6,7 @@ import ( "net" "sync" + "github.com/Andoryuuta/Erupe/common/stringstack" "github.com/Andoryuuta/Erupe/network" "github.com/Andoryuuta/Erupe/network/mhfpacket" "github.com/Andoryuuta/byteframe" @@ -25,16 +26,20 @@ type Session struct { stage *Stage charID uint32 logKey []byte + + // A stack containing the stage movement history (push on enter/move, pop on back) + stageMoveStack *stringstack.StringStack } // NewSession creates a new Session type. func NewSession(server *Server, conn net.Conn) *Session { s := &Session{ - logger: server.logger.Named(conn.RemoteAddr().String()), - server: server, - rawConn: conn, - cryptConn: network.NewCryptConn(conn), - sendPackets: make(chan []byte, 20), + logger: server.logger.Named(conn.RemoteAddr().String()), + server: server, + rawConn: conn, + cryptConn: network.NewCryptConn(conn), + sendPackets: make(chan []byte, 20), + stageMoveStack: stringstack.New(), } return s }