mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 15:34:38 +01:00
rework Semaphores
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user