mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-02-06 01:57: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)
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user