diff --git a/Erupe/server/channelserver/handlers_discord.go b/Erupe/server/channelserver/handlers_discord.go index 94c92c58f..38619e079 100644 --- a/Erupe/server/channelserver/handlers_discord.go +++ b/Erupe/server/channelserver/handlers_discord.go @@ -263,7 +263,7 @@ func getCharInfo(server *Server, charName string) string { objInfo := "" - obj := server.FindStageObjectByChar(c.charID) + obj := server.FindObjectByChar(c.charID) // server.logger.Info("Found object: %+v", zap.Object("obj", obj)) if obj != nil { diff --git a/Erupe/server/channelserver/handlers_object.go b/Erupe/server/channelserver/handlers_object.go index 548d891fe..0b24c0f66 100644 --- a/Erupe/server/channelserver/handlers_object.go +++ b/Erupe/server/channelserver/handlers_object.go @@ -10,44 +10,31 @@ import ( func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCreateObject) - // Lock the stage. - s.server.Lock() - - // Make a new stage object and insert it into the stage. - objID := s.stage.GetNewObjectID(s.charID) - newObj := &StageObject{ - id: objID, + s.stage.Lock() + newObj := &Object{ + id: s.stage.NextObjectID(), ownerCharID: s.charID, x: pkt.X, y: pkt.Y, z: pkt.Z, } - s.stage.objects[s.charID] = newObj + s.stage.Unlock() - // Unlock the stage. - s.server.Unlock() // Response to our requesting client. resp := byteframe.NewByteFrame() - resp.WriteUint32(objID) // New local obj handle. + resp.WriteUint32(newObj.id) // New local obj handle. doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) // Duplicate the object creation to all sessions in the same stage. dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{ - ObjID: objID, - X: pkt.X, - Y: pkt.Y, - Z: pkt.Z, - OwnerCharID: s.charID, + ObjID: newObj.id, + X: newObj.x, + Y: newObj.y, + Z: newObj.z, + OwnerCharID: newObj.ownerCharID, } - for i := 1; i <= 3; i++ { - s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{ - CharID: s.charID, - BinaryType: uint8(i), - }, s) - } - - s.logger.Info("Duplicate a new characters to others clients") + s.logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, s.charID)) s.stage.BroadcastMHF(dupObjUpdate, s) } @@ -74,7 +61,14 @@ func handleMsgSysRotateObject(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysSetObjectBinary) + for _, object := range s.stage.objects { + if object.id == pkt.ObjID { + object.binary = pkt.RawDataPayload + } + } +} func handleMsgSysGetObjectBinary(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_stage.go b/Erupe/server/channelserver/handlers_stage.go index d7891ba7b..ae0830846 100644 --- a/Erupe/server/channelserver/handlers_stage.go +++ b/Erupe/server/channelserver/handlers_stage.go @@ -108,29 +108,10 @@ func removeSessionFromStage(s *Session) { // Delete old stage objects owned by the client. s.logger.Info("Sending notification to old stage clients") - for objID, stageObject := range s.stage.objects { - if stageObject.ownerCharID == s.charID { - clientNotif := byteframe.NewByteFrame() - var pkt mhfpacket.MHFPacket - pkt = &mhfpacket.MsgSysDeleteObject{ - ObjID: stageObject.id, - } - clientNotif.WriteUint16(uint16(pkt.Opcode())) - pkt.Build(clientNotif, s.clientContext) - clientNotif.WriteUint16(0x0010) - for client, _ := range s.stage.clients { - client.QueueSend(clientNotif.Data()) - } - // TODO(Andoryuuta): Should this be sent to the owner's client as well? it currently isn't. - // Actually delete it from the objects map. - delete(s.stage.objects, objID) - } - } - for objListID, stageObjectList := range s.stage.objectList { - if stageObjectList.charid == s.charID { - // Added to prevent duplicates from flooding ObjectMap and causing server hangs - s.stage.objectList[objListID].status = false - s.stage.objectList[objListID].charid = 0 + for _, object := range s.stage.objects { + if object.ownerCharID == s.charID { + s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.id}, s) + delete(s.stage.objects, object.ownerCharID) } } s.stage.Unlock() @@ -149,34 +130,6 @@ func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) { s.reservationStage = nil } - if pkt.StageID == "sl1Ns200p0a0u0" { // First entry - var temp mhfpacket.MHFPacket - loginNotif := byteframe.NewByteFrame() - s.server.Lock() - for _, session := range s.server.sessions { - if s == session || !session.binariesDone { - continue - } - temp = &mhfpacket.MsgSysInsertUser{ - CharID: session.charID, - } - loginNotif.WriteUint16(uint16(temp.Opcode())) - temp.Build(loginNotif, s.clientContext) - for i := 1; i <= 3; i++ { - temp = &mhfpacket.MsgSysNotifyUserBinary{ - CharID: session.charID, - BinaryType: uint8(i), - } - loginNotif.WriteUint16(uint16(temp.Opcode())) - temp.Build(loginNotif, s.clientContext) - } - } - s.server.Unlock() - loginNotif.WriteUint16(0x0010) // End it. - if len(loginNotif.Data()) > 2 { - s.QueueSend(loginNotif.Data()) - } - } doStageTransfer(s, pkt.AckHandle, pkt.StageID) } @@ -218,11 +171,9 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) { s.reservationStage.RLock() defer s.reservationStage.RUnlock() - destructMessage := &mhfpacket.MsgSysStageDestruct{} - for charID := range s.reservationStage.reservedClientSlots { session := s.server.FindSessionByCharID(charID) - session.QueueSendMHF(destructMessage) + session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{}) } s.server.Lock() diff --git a/Erupe/server/channelserver/handlers_users.go b/Erupe/server/channelserver/handlers_users.go index 623beced5..10272865d 100644 --- a/Erupe/server/channelserver/handlers_users.go +++ b/Erupe/server/channelserver/handlers_users.go @@ -12,6 +12,49 @@ func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {} +func broadcastNewUser(s *Session) { + s.logger.Debug(fmt.Sprintf("Broadcasting new user: %s (%d)", s.Name, s.charID)) + + clientNotif := byteframe.NewByteFrame() + var temp mhfpacket.MHFPacket + for _, session := range s.server.sessions { + if session == s || !s.binariesDone { + continue + } + temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID} + clientNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(clientNotif, s.clientContext) + for i := 0; i < 3; i++ { + temp = &mhfpacket.MsgSysNotifyUserBinary{ + CharID: session.charID, + BinaryType: uint8(i + 1), + } + clientNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(clientNotif, s.clientContext) + } + } + s.QueueSend(clientNotif.Data()) + + serverNotif := byteframe.NewByteFrame() + temp = &mhfpacket.MsgSysInsertUser{CharID: s.charID} + serverNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(serverNotif, s.clientContext) + for i := 0; i < 3; i++ { + temp = &mhfpacket.MsgSysNotifyUserBinary{ + CharID: s.charID, + BinaryType: uint8(i + 1), + } + serverNotif.WriteUint16(uint16(temp.Opcode())) + temp.Build(serverNotif, s.clientContext) + } + for _, session := range s.server.sessions { + if session == s || !session.binariesDone { + continue + } + session.QueueSend(serverNotif.Data()) + } +} + func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysSetUserBinary) s.server.userBinaryPartsLock.Lock() @@ -27,9 +70,7 @@ func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) { } } s.binariesDone = true - s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{ - CharID: s.charID, - }, s) + broadcastNewUser(s) return } diff --git a/Erupe/server/channelserver/sys_channel_server.go b/Erupe/server/channelserver/sys_channel_server.go index 89bfa2584..a6e22106d 100644 --- a/Erupe/server/channelserver/sys_channel_server.go +++ b/Erupe/server/channelserver/sys_channel_server.go @@ -277,7 +277,7 @@ func (s *Server) manageSessions() { func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { // Broadcast the data. for _, session := range s.sessions { - if session == ignoredSession { + if session == ignoredSession || !session.binariesDone { continue } @@ -295,14 +295,14 @@ func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) func (s *Server) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { for _, c := range s.Channels { - for _, s := range c.sessions { - if s == ignoredSession { + for _, session := range c.sessions { + if session == ignoredSession || !session.binariesDone { continue } bf := byteframe.NewByteFrame() bf.WriteUint16(uint16(pkt.Opcode())) - pkt.Build(bf, s.clientContext) - s.QueueSendNonBlocking(bf.Data()) + pkt.Build(bf, session.clientContext) + session.QueueSendNonBlocking(bf.Data()) } } } @@ -384,7 +384,7 @@ func (s *Server) FindSessionByCharID(charID uint32) *Session { return nil } -func (s *Server) FindStageObjectByChar(charID uint32) *StageObject { +func (s *Server) FindObjectByChar(charID uint32) *Object { s.stagesLock.RLock() defer s.stagesLock.RUnlock() for _, stage := range s.stages { diff --git a/Erupe/server/channelserver/sys_stage.go b/Erupe/server/channelserver/sys_stage.go index 8c0a19568..3d0d68d28 100644 --- a/Erupe/server/channelserver/sys_stage.go +++ b/Erupe/server/channelserver/sys_stage.go @@ -9,18 +9,13 @@ import ( "erupe-ce/network/mhfpacket" ) -// StageObject holds infomation about a specific stage object. -type StageObject struct { +// Object holds infomation about a specific object. +type Object struct { sync.RWMutex id uint32 ownerCharID uint32 x, y, z float32 -} - -type ObjectMap struct { - id uint8 - charid uint32 - status bool + binary []byte } // stageBinaryKey is a struct used as a map key for identifying a stage binary part. @@ -36,13 +31,10 @@ type Stage struct { // Stage ID string id string - // Total count of objects ever created for this stage. Used for ObjID generation. - gameObjectCount uint32 + // Objects + objects map[uint32]*Object + objectIndex uint32 - // Save all object in stage - objects map[uint32]*StageObject - - objectList map[uint8]*ObjectMap // Map of session -> charID. // These are clients that are CURRENTLY in the stage clients map[*Session]uint32 @@ -66,14 +58,12 @@ func NewStage(ID string) *Stage { id: ID, clients: make(map[*Session]uint32), reservedClientSlots: make(map[uint32]bool), - objects: make(map[uint32]*StageObject), + objects: make(map[uint32]*Object), + objectIndex: 0, rawBinaryData: make(map[stageBinaryKey][]byte), maxPlayers: 4, - gameObjectCount: 1, - objectList: make(map[uint8]*ObjectMap), createdAt: time.Now().Format("01-02-2006 15:04:05"), } - s.InitObjectList() return s } @@ -81,7 +71,7 @@ func NewStage(ID string) *Stage { func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { // Broadcast the data. for session := range s.clients { - if session == ignoredSession { + if session == ignoredSession || !session.binariesDone { continue } @@ -97,17 +87,6 @@ func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { } } -func (s *Stage) InitObjectList() { - for seq := uint8(0x7f); seq > uint8(0); seq-- { - newObj := &ObjectMap{ - id: seq, - charid: uint32(0), - status: false, - } - s.objectList[seq] = newObj - } -} - func (s *Stage) isCharInQuestByID(charID uint32) bool { if _, exists := s.reservedClientSlots[charID]; exists { return exists @@ -120,8 +99,8 @@ func (s *Stage) isQuest() bool { return len(s.reservedClientSlots) > 0 } -func (stage *Stage) GetName() string { - switch stage.id { +func (s *Stage) GetName() string { + switch s.id { case MezeportaStageId: return "Mezeporta" case GuildHallLv1StageId: @@ -149,20 +128,7 @@ func (stage *Stage) GetName() string { } } -func (s *Stage) GetNewObjectID(CharID uint32) uint32 { - ObjId := uint8(0) - for seq := uint8(0x7f); seq > uint8(0); seq-- { - if s.objectList[seq].status == false { - ObjId = seq - break - } - } - s.objectList[ObjId].status = true - s.objectList[ObjId].charid = CharID - bf := byteframe.NewByteFrame() - bf.WriteUint8(uint8(0)) - bf.WriteUint8(ObjId) - bf.WriteUint16(uint16(0)) - obj := uint32(bf.Data()[3]) | uint32(bf.Data()[2])<<8 | uint32(bf.Data()[1])<<16 | uint32(bf.Data()[0])<<32 - return obj +func (s *Stage) NextObjectID() uint32 { + s.objectIndex = s.objectIndex + 1 + return s.objectIndex }