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)
for i := uint8(0); i < pkt.Values; i++ {
switch pkt.RegisterID {
case 4:
case 0x40000:
bf.WriteUint32(s.server.raviente.state[i])
case 5:
case 0x50000:
bf.WriteUint32(s.server.raviente.support[i])
case 6:
case 0x60000:
bf.WriteUint32(s.server.raviente.register[i])
}
}
@@ -117,13 +117,13 @@ func (s *Session) notifyRavi() {
}
var temp mhfpacket.MHFPacket
raviNotif := byteframe.NewByteFrame()
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 4}
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x40000}
raviNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(raviNotif, s.clientContext)
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 5}
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x50000}
raviNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(raviNotif, s.clientContext)
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 6}
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: 0x60000}
raviNotif.WriteUint16(uint16(temp.Opcode()))
temp.Build(raviNotif, s.clientContext)
raviNotif.WriteUint16(0x0010) // End it.
@@ -142,7 +142,7 @@ func (s *Session) notifyRavi() {
func (s *Server) getRaviSemaphore() *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
}
}

View File

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

View File

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

View File

@@ -7,55 +7,35 @@ import (
"sync"
)
// Stage holds stage-specific information
// Semaphore holds Semaphore-specific information
type Semaphore struct {
sync.RWMutex
// Stage ID string
id_semaphore string
// Semaphore ID string
name string
id uint32
// 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
// Map of charID -> interface{}, only the key is used, value is always nil.
reservedClientSlots map[uint32]interface{}
// Max Players for Semaphore
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 {
sema := &Semaphore{
id_semaphore: ID,
id: s.NextSemaphoreID(),
clients: make(map[*Session]uint32),
reservedClientSlots: make(map[uint32]interface{}),
maxPlayers: MaxPlayers,
name: ID,
id: s.NextSemaphoreID(),
clients: make(map[*Session]uint32),
maxPlayers: MaxPlayers,
}
return sema
}
func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) {
// 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.
// BroadcastMHF queues a MHFPacket to be sent to all sessions in the Semaphore
func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
// Broadcast the data.
for session := range s.clients {