diff --git a/server/channelserver/handlers_semaphore.go b/server/channelserver/handlers_semaphore.go index 19925c6d6..2088cabea 100644 --- a/server/channelserver/handlers_semaphore.go +++ b/server/channelserver/handlers_semaphore.go @@ -65,6 +65,15 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysCreateAcquireSemaphore) SemaphoreID := pkt.SemaphoreID + if s.server.HasSemaphore(s) { + s.semaphoreMode = !s.semaphoreMode + } + if s.semaphoreMode { + s.semaphoreID[1]++ + } else { + s.semaphoreID[0]++ + } + newSemaphore, exists := s.server.semaphore[SemaphoreID] if !exists { s.server.semaphoreLock.Lock() @@ -77,7 +86,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { maxPlayers: 127, } } else { - s.server.semaphore[SemaphoreID] = NewSemaphore(s.server, SemaphoreID, 1) + s.server.semaphore[SemaphoreID] = NewSemaphore(s, SemaphoreID, 1) } newSemaphore = s.server.semaphore[SemaphoreID] s.server.semaphoreLock.Unlock() @@ -103,7 +112,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysAcquireSemaphore) if sema, exists := s.server.semaphore[pkt.SemaphoreID]; exists { - sema.clients[s] = s.charID + sema.host = s bf := byteframe.NewByteFrame() bf.WriteUint32(sema.id) doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) diff --git a/server/channelserver/sys_channel_server.go b/server/channelserver/sys_channel_server.go index a0d1fe1b7..a1b2c093b 100644 --- a/server/channelserver/sys_channel_server.go +++ b/server/channelserver/sys_channel_server.go @@ -424,24 +424,13 @@ func (s *Server) FindObjectByChar(charID uint32) *Object { return nil } -func (s *Server) NextSemaphoreID() uint32 { - for { - exists := false - s.semaphoreIndex = s.semaphoreIndex + 1 - if s.semaphoreIndex > 0xFFFF { - s.semaphoreIndex = 1 - } - for _, semaphore := range s.semaphore { - if semaphore.id == s.semaphoreIndex { - exists = true - break - } - } - if !exists { - break +func (s *Server) HasSemaphore(ses *Session) bool { + for _, semaphore := range s.semaphore { + if semaphore.host == ses { + return true } } - return s.semaphoreIndex + return false } func (s *Server) Season() uint8 { diff --git a/server/channelserver/sys_semaphore.go b/server/channelserver/sys_semaphore.go index 78ff963b5..2200877ca 100644 --- a/server/channelserver/sys_semaphore.go +++ b/server/channelserver/sys_semaphore.go @@ -22,15 +22,18 @@ type Semaphore struct { // Max Players for Semaphore maxPlayers uint16 + + host *Session } // NewSemaphore creates a new Semaphore with intialized values -func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore { +func NewSemaphore(s *Session, ID string, MaxPlayers uint16) *Semaphore { sema := &Semaphore{ name: ID, - id: s.NextSemaphoreID(), + id: s.GetSemaphoreID(), clients: make(map[*Session]uint32), maxPlayers: MaxPlayers, + host: s, } return sema } diff --git a/server/channelserver/sys_session.go b/server/channelserver/sys_session.go index d7e55d621..ca9f5ff6c 100644 --- a/server/channelserver/sys_session.go +++ b/server/channelserver/sys_session.go @@ -48,7 +48,9 @@ type Session struct { kqf []byte kqfOverride bool - semaphore *Semaphore // Required for the stateful MsgSysUnreserveStage packet. + semaphore *Semaphore // Required for the stateful MsgSysUnreserveStage packet. + semaphoreMode bool + semaphoreID []uint16 // A stack containing the stage movement history (push on enter/move, pop on back) stageMoveStack *stringstack.StringStack @@ -79,6 +81,7 @@ func NewSession(server *Server, conn net.Conn) *Session { sessionStart: TimeAdjusted().Unix(), stageMoveStack: stringstack.New(), ackStart: make(map[uint32]time.Time), + semaphoreID: make([]uint16, 2), } s.SetObjectID() return s @@ -310,6 +313,14 @@ func (s *Session) NextObjectID() uint32 { return bf.ReadUint32() } +func (s *Session) GetSemaphoreID() uint32 { + if s.semaphoreMode { + return 0x000E0000 + uint32(s.semaphoreID[1]) + } else { + return 0x000F0000 + uint32(s.semaphoreID[0]) + } +} + func (s *Session) isOp() bool { var op bool err := s.server.db.QueryRow(`SELECT op FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&op)