rework Semaphores

This commit is contained in:
wish
2023-09-03 00:00:08 +10:00
parent 0bdd873336
commit 4a35be488c
4 changed files with 57 additions and 90 deletions

View File

@@ -99,11 +99,11 @@ func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) {
bf.WriteUint8(pkt.Values) bf.WriteUint8(pkt.Values)
for i := uint8(0); i < pkt.Values; i++ { for i := uint8(0); i < pkt.Values; i++ {
switch pkt.RegisterID { switch pkt.RegisterID {
case 4: case 0x40000:
bf.WriteUint32(s.server.raviente.state[i]) bf.WriteUint32(s.server.raviente.state[i])
case 5: case 0x50000:
bf.WriteUint32(s.server.raviente.support[i]) bf.WriteUint32(s.server.raviente.support[i])
case 6: case 0x60000:
bf.WriteUint32(s.server.raviente.register[i]) bf.WriteUint32(s.server.raviente.register[i])
} }
} }
@@ -117,13 +117,13 @@ func (s *Session) notifyRavi() {
} }
var temp mhfpacket.MHFPacket var temp mhfpacket.MHFPacket
raviNotif := byteframe.NewByteFrame() raviNotif := byteframe.NewByteFrame()
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 4} temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x40000}
raviNotif.WriteUint16(uint16(temp.Opcode())) raviNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(raviNotif, s.clientContext) temp.Build(raviNotif, s.clientContext)
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 5} temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x50000}
raviNotif.WriteUint16(uint16(temp.Opcode())) raviNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(raviNotif, s.clientContext) temp.Build(raviNotif, s.clientContext)
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 6} temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x60000}
raviNotif.WriteUint16(uint16(temp.Opcode())) raviNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(raviNotif, s.clientContext) temp.Build(raviNotif, s.clientContext)
raviNotif.WriteUint16(0x0010) // End it. raviNotif.WriteUint16(0x0010) // End it.
@@ -142,7 +142,7 @@ func (s *Session) notifyRavi() {
func (s *Server) getRaviSemaphore() *Semaphore { func (s *Server) getRaviSemaphore() *Semaphore {
for _, semaphore := range s.semaphore { for _, semaphore := range s.semaphore {
if strings.HasPrefix(semaphore.id_semaphore, "hs_l0") && strings.HasSuffix(semaphore.id_semaphore, "3") { if strings.HasPrefix(semaphore.name, "hs_l0") && strings.HasSuffix(semaphore.name, "3") {
return semaphore return semaphore
} }
} }

View File

@@ -2,7 +2,6 @@ package channelserver
import ( import (
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"fmt"
"go.uber.org/zap" "go.uber.org/zap"
"strconv" "strconv"
"strings" "strings"
@@ -13,9 +12,6 @@ import (
func removeSessionFromSemaphore(s *Session) { func removeSessionFromSemaphore(s *Session) {
s.server.semaphoreLock.Lock() s.server.semaphoreLock.Lock()
for _, semaphore := range s.server.semaphore { for _, semaphore := range s.server.semaphore {
if _, exists := semaphore.reservedClientSlots[s.charID]; exists {
delete(semaphore.reservedClientSlots, s.charID)
}
if _, exists := semaphore.clients[s]; exists { if _, exists := semaphore.clients[s]; exists {
delete(semaphore.clients, s) delete(semaphore.clients, s)
} }
@@ -31,48 +27,38 @@ func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
func destructEmptySemaphores(s *Session) { func destructEmptySemaphores(s *Session) {
s.server.semaphoreLock.Lock() s.server.semaphoreLock.Lock()
for id, sema := range s.server.semaphore { for id, sema := range s.server.semaphore {
if len(sema.reservedClientSlots) == 0 && len(sema.clients) == 0 { if len(sema.clients) == 0 {
s.server.semaphoreLock.Unlock()
delete(s.server.semaphore, id) delete(s.server.semaphore, id)
s.server.semaphoreLock.Lock()
if strings.HasPrefix(id, "hs_l0") { if strings.HasPrefix(id, "hs_l0") {
releaseRaviSemaphore(s, sema) s.server.resetRaviente()
} }
s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id)) s.logger.Debug("Destructed semaphore", zap.String("sema.name", id))
} }
} }
s.server.semaphoreLock.Unlock() s.server.semaphoreLock.Unlock()
} }
func releaseRaviSemaphore(s *Session, sema *Semaphore) {
delete(sema.reservedClientSlots, s.charID)
delete(sema.clients, s)
if strings.HasSuffix(sema.id_semaphore, "2") && len(sema.clients) == 0 {
s.logger.Debug("Main raviente semaphore is empty, resetting")
s.server.resetRaviente()
}
}
func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysDeleteSemaphore) pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
if s.server.semaphore != nil { destructEmptySemaphores(s)
destructEmptySemaphores(s) s.server.semaphoreLock.Lock()
s.server.semaphoreLock.Lock() for id, sema := range s.server.semaphore {
for id, sema := range s.server.semaphore { if sema.id == pkt.SemaphoreID {
if sema.id == pkt.SemaphoreID { for session := range sema.clients {
if strings.HasPrefix(id, "hs_l0") { if s == session {
releaseRaviSemaphore(s, sema) delete(sema.clients, s)
s.server.semaphoreLock.Unlock()
return
} }
s.server.semaphoreLock.Unlock() }
if len(sema.clients) == 0 {
delete(s.server.semaphore, id) delete(s.server.semaphore, id)
s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id)) if strings.HasPrefix(id, "hs_l0") {
return s.server.resetRaviente()
}
s.logger.Debug("Destructed semaphore", zap.String("sema.name", id))
} }
} }
s.server.semaphoreLock.Unlock()
} }
s.server.semaphoreLock.Unlock()
} }
func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
@@ -80,18 +66,15 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
SemaphoreID := pkt.SemaphoreID SemaphoreID := pkt.SemaphoreID
newSemaphore, exists := s.server.semaphore[SemaphoreID] newSemaphore, exists := s.server.semaphore[SemaphoreID]
fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID)
if !exists { if !exists {
s.server.semaphoreLock.Lock() s.server.semaphoreLock.Lock()
if strings.HasPrefix(SemaphoreID, "hs_l0") { if strings.HasPrefix(SemaphoreID, "hs_l0") {
suffix, _ := strconv.Atoi(pkt.SemaphoreID[len(pkt.SemaphoreID)-1:]) suffix, _ := strconv.Atoi(pkt.SemaphoreID[len(pkt.SemaphoreID)-1:])
s.server.semaphore[SemaphoreID] = &Semaphore{ s.server.semaphore[SemaphoreID] = &Semaphore{
id_semaphore: pkt.SemaphoreID, name: pkt.SemaphoreID,
id: uint32(suffix + 1), id: uint32((suffix + 1) * 0x10000),
clients: make(map[*Session]uint32), clients: make(map[*Session]uint32),
reservedClientSlots: make(map[uint32]interface{}), maxPlayers: 127,
maxPlayers: 127,
} }
} else { } else {
s.server.semaphore[SemaphoreID] = NewSemaphore(s.server, SemaphoreID, 1) s.server.semaphore[SemaphoreID] = NewSemaphore(s.server, SemaphoreID, 1)
@@ -102,22 +85,19 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
newSemaphore.Lock() newSemaphore.Lock()
defer newSemaphore.Unlock() defer newSemaphore.Unlock()
if _, exists := newSemaphore.reservedClientSlots[s.charID]; exists { bf := byteframe.NewByteFrame()
bf := byteframe.NewByteFrame() if _, exists := newSemaphore.clients[s]; exists {
bf.WriteUint32(newSemaphore.id) bf.WriteUint32(newSemaphore.id)
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) } else if uint16(len(newSemaphore.clients)) < newSemaphore.maxPlayers {
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
newSemaphore.reservedClientSlots[s.charID] = nil
newSemaphore.clients[s] = s.charID newSemaphore.clients[s] = s.charID
s.Lock() s.Lock()
s.semaphore = newSemaphore s.semaphore = newSemaphore
s.Unlock() s.Unlock()
bf := byteframe.NewByteFrame()
bf.WriteUint32(newSemaphore.id) bf.WriteUint32(newSemaphore.id)
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
} else { } else {
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) bf.WriteUint32(0)
} }
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
} }
func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
@@ -130,7 +110,6 @@ func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
} else { } else {
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
} }
} }
func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {

View File

@@ -3,6 +3,7 @@ package channelserver
import ( import (
"fmt" "fmt"
"net" "net"
"strings"
"sync" "sync"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
@@ -83,6 +84,12 @@ type Raviente struct {
} }
func (s *Server) resetRaviente() { func (s *Server) resetRaviente() {
for _, semaphore := range s.semaphore {
if strings.HasPrefix(semaphore.name, "hs_l0") {
return
}
}
s.logger.Debug("All Raviente Semaphores empty, resetting")
s.raviente.id = s.raviente.id + 1 s.raviente.id = s.raviente.id + 1
s.raviente.register = make([]uint32, 30) s.raviente.register = make([]uint32, 30)
s.raviente.state = make([]uint32, 30) s.raviente.state = make([]uint32, 30)
@@ -109,7 +116,7 @@ func (s *Server) GetRaviMultiplier() float64 {
func (s *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) { func (s *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) {
var prev uint32 var prev uint32
switch semaID { switch semaID {
case 4: case 0x40000:
switch index { switch index {
case 17, 28: // Ignore res and poison case 17, 28: // Ignore res and poison
break break
@@ -122,14 +129,14 @@ func (s *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update boo
} }
s.raviente.state[index] += value s.raviente.state[index] += value
return prev, s.raviente.state[index] return prev, s.raviente.state[index]
case 5: case 0x50000:
prev = s.raviente.support[index] prev = s.raviente.support[index]
if prev != 0 && !update { if prev != 0 && !update {
return prev, prev return prev, prev
} }
s.raviente.support[index] += value s.raviente.support[index] += value
return prev, s.raviente.support[index] return prev, s.raviente.support[index]
case 6: case 0x60000:
prev = s.raviente.register[index] prev = s.raviente.register[index]
if prev != 0 && !update { if prev != 0 && !update {
return prev, prev return prev, prev
@@ -395,15 +402,16 @@ func (s *Server) NextSemaphoreID() uint32 {
for { for {
exists := false exists := false
s.semaphoreIndex = s.semaphoreIndex + 1 s.semaphoreIndex = s.semaphoreIndex + 1
if s.semaphoreIndex == 0 { if s.semaphoreIndex > 0xFFFF {
s.semaphoreIndex = 7 // Skip reserved indexes s.semaphoreIndex = 1
} }
for _, semaphore := range s.semaphore { for _, semaphore := range s.semaphore {
if semaphore.id == s.semaphoreIndex { if semaphore.id == s.semaphoreIndex {
exists = true exists = true
break
} }
} }
if exists == false { if !exists {
break break
} }
} }

View File

@@ -7,55 +7,35 @@ import (
"sync" "sync"
) )
// Stage holds stage-specific information // Semaphore holds Semaphore-specific information
type Semaphore struct { type Semaphore struct {
sync.RWMutex sync.RWMutex
// Stage ID string // Semaphore ID string
id_semaphore string name string
id uint32 id uint32
// Map of session -> charID. // Map of session -> charID.
// These are clients that are CURRENTLY in the stage // These are clients that are registered to the Semaphore
clients map[*Session]uint32 clients map[*Session]uint32
// Map of charID -> interface{}, only the key is used, value is always nil.
reservedClientSlots map[uint32]interface{}
// Max Players for Semaphore // Max Players for Semaphore
maxPlayers uint16 maxPlayers uint16
} }
// NewStage creates a new stage with intialized values. // NewSemaphore creates a new Semaphore with intialized values
func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore { func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore {
sema := &Semaphore{ sema := &Semaphore{
id_semaphore: ID, name: ID,
id: s.NextSemaphoreID(), id: s.NextSemaphoreID(),
clients: make(map[*Session]uint32), clients: make(map[*Session]uint32),
reservedClientSlots: make(map[uint32]interface{}), maxPlayers: MaxPlayers,
maxPlayers: MaxPlayers,
} }
return sema return sema
} }
func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) { // BroadcastMHF queues a MHFPacket to be sent to all sessions in the Semaphore
// Broadcast the data.
for session := range s.clients {
// Make the header
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(pkt.Opcode()))
// Build the packet onto the byteframe.
pkt.Build(bf, session.clientContext)
// Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full.
session.QueueSendNonBlocking(bf.Data())
}
}
// BroadcastMHF queues a MHFPacket to be sent to all sessions in the stage.
func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
// Broadcast the data. // Broadcast the data.
for session := range s.clients { for session := range s.clients {