mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-15 00:15:08 +01:00
stage and semaphore overhaul partial
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
package mhfpacket
|
package mhfpacket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/Solenataris/Erupe/network/clientctx"
|
"github.com/Solenataris/Erupe/network/clientctx"
|
||||||
"github.com/Solenataris/Erupe/network"
|
"github.com/Solenataris/Erupe/network"
|
||||||
@@ -9,7 +9,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// MsgMhfTransitMessage represents the MSG_MHF_TRANSIT_MESSAGE
|
// MsgMhfTransitMessage represents the MSG_MHF_TRANSIT_MESSAGE
|
||||||
type MsgMhfTransitMessage struct{}
|
type MsgMhfTransitMessage struct {
|
||||||
|
AckHandle uint32
|
||||||
|
Unk0 uint8
|
||||||
|
Unk1 uint8
|
||||||
|
Unk2 uint16
|
||||||
|
Unk3 uint16
|
||||||
|
TargetID uint32
|
||||||
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
func (m *MsgMhfTransitMessage) Opcode() network.PacketID {
|
func (m *MsgMhfTransitMessage) Opcode() network.PacketID {
|
||||||
@@ -18,7 +25,13 @@ func (m *MsgMhfTransitMessage) Opcode() network.PacketID {
|
|||||||
|
|
||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfTransitMessage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfTransitMessage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
return errors.New("NOT IMPLEMENTED")
|
m.AckHandle = bf.ReadUint32()
|
||||||
|
m.Unk0 = bf.ReadUint8()
|
||||||
|
m.Unk1 = bf.ReadUint8()
|
||||||
|
m.Unk2 = bf.ReadUint16()
|
||||||
|
m.Unk3 = bf.ReadUint16()
|
||||||
|
m.TargetID = bf.ReadUint32()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
|
|||||||
@@ -183,13 +183,12 @@ func logoutPlayer(s *Session) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.stage.RLock()
|
s.server.BroadcastMHF(&mhfpacket.MsgSysDeleteUser {
|
||||||
for client := range s.stage.clients {
|
CharID: s.charID,
|
||||||
client.QueueSendMHF(&mhfpacket.MsgSysDeleteUser{
|
}, s)
|
||||||
CharID: s.charID,
|
|
||||||
})
|
delete(s.server.sessions, s.rawConn)
|
||||||
}
|
s.rawConn.Close()
|
||||||
s.stage.RUnlock()
|
|
||||||
|
|
||||||
if s.server.erupeConfig.DevModeOptions.ServerName != "" {
|
if s.server.erupeConfig.DevModeOptions.ServerName != "" {
|
||||||
_, err := s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_name=$2", uint32(len(s.server.sessions)), s.server.erupeConfig.DevModeOptions.ServerName)
|
_, err := s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_name=$2", uint32(len(s.server.sessions)), s.server.erupeConfig.DevModeOptions.ServerName)
|
||||||
@@ -198,13 +197,16 @@ func logoutPlayer(s *Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeSessionFromStage(s)
|
s.server.Lock()
|
||||||
|
for _, stage := range s.server.stages {
|
||||||
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||||
if _, ok := s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots[s.charID]; ok {
|
delete(stage.reservedClientSlots, s.charID)
|
||||||
removeSessionFromSemaphore(s)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
s.server.Unlock()
|
||||||
|
|
||||||
|
removeSessionFromSemaphore(s)
|
||||||
|
removeSessionFromStage(s)
|
||||||
|
|
||||||
var timePlayed int
|
var timePlayed int
|
||||||
err := s.server.db.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.charID).Scan(&timePlayed)
|
err := s.server.db.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.charID).Scan(&timePlayed)
|
||||||
@@ -213,7 +215,7 @@ func logoutPlayer(s *Session) {
|
|||||||
|
|
||||||
var rpGained int
|
var rpGained int
|
||||||
|
|
||||||
if s.rights == 0x08091e4e || s.rights == 0x08091e0e { // N Course
|
if s.rights > 0x40000000 { // N Course
|
||||||
rpGained = timePlayed / 900
|
rpGained = timePlayed / 900
|
||||||
timePlayed = timePlayed % 900
|
timePlayed = timePlayed % 900
|
||||||
} else {
|
} else {
|
||||||
@@ -326,7 +328,13 @@ func handleMsgSysRightsReload(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
pkt := p.(*mhfpacket.MsgMhfTransitMessage)
|
||||||
|
// TODO: figure out what this is supposed to return
|
||||||
|
// probably what world+land the targeted character is on?
|
||||||
|
// stubbed response will just say user not found
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgCaExchangeItem(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgCaExchangeItem(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,10 +2,22 @@ package channelserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Solenataris/Erupe/network/mhfpacket"
|
"github.com/Solenataris/Erupe/network/mhfpacket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func removeSessionFromSemaphore(s *Session) {
|
||||||
|
s.server.semaphoreLock.Lock()
|
||||||
|
for _, semaphore := range s.server.semaphore {
|
||||||
|
if _, exists := semaphore.clients[s]; exists {
|
||||||
|
delete(semaphore.clients, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
releaseRaviSemaphore(s)
|
||||||
|
s.server.semaphoreLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysCreateSemaphore)
|
pkt := p.(*mhfpacket.MsgSysCreateSemaphore)
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d})
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d})
|
||||||
@@ -15,31 +27,53 @@ func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
|
pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
|
||||||
sem := pkt.AckHandle
|
sem := pkt.AckHandle
|
||||||
if s.server.semaphore != nil {
|
if s.server.semaphore != nil {
|
||||||
s.server.semaphoreLock.Lock()
|
s.server.semaphoreLock.Lock()
|
||||||
for id := range s.server.semaphore {
|
for id := range s.server.semaphore {
|
||||||
switch sem {
|
switch sem {
|
||||||
case 917533:
|
case 917533:
|
||||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k3" {
|
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k3" {
|
||||||
delete(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots, s.charID)
|
delete(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots, s.charID)
|
||||||
delete(s.server.semaphore["hs_l0u3B51J9k3"].clients, s)
|
delete(s.server.semaphore["hs_l0u3B51J9k3"].clients, s)
|
||||||
|
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B5129k3" {
|
||||||
|
delete(s.server.semaphore["hs_l0u3B5129k3"].reservedClientSlots, s.charID)
|
||||||
|
delete(s.server.semaphore["hs_l0u3B5129k3"].clients, s)
|
||||||
|
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B512Ak3" {
|
||||||
|
delete(s.server.semaphore["hs_l0u3B512Ak3"].reservedClientSlots, s.charID)
|
||||||
|
delete(s.server.semaphore["hs_l0u3B512Ak3"].clients, s)
|
||||||
}
|
}
|
||||||
case 851997:
|
case 851997:
|
||||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k4" {
|
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k4" {
|
||||||
delete(s.server.semaphore["hs_l0u3B51J9k4"].reservedClientSlots, s.charID)
|
delete(s.server.semaphore["hs_l0u3B51J9k4"].reservedClientSlots, s.charID)
|
||||||
|
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B5129k4" {
|
||||||
|
delete(s.server.semaphore["hs_l0u3B5129k4"].reservedClientSlots, s.charID)
|
||||||
|
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B512Ak4" {
|
||||||
|
delete(s.server.semaphore["hs_l0u3B512Ak4"].reservedClientSlots, s.charID)
|
||||||
}
|
}
|
||||||
case 786461:
|
case 786461:
|
||||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k5" {
|
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k5" {
|
||||||
delete(s.server.semaphore["hs_l0u3B51J9k5"].reservedClientSlots, s.charID)
|
delete(s.server.semaphore["hs_l0u3B51J9k5"].reservedClientSlots, s.charID)
|
||||||
|
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B5129k5" {
|
||||||
|
delete(s.server.semaphore["hs_l0u3B5129k5"].reservedClientSlots, s.charID)
|
||||||
|
} else if s.server.semaphore[id].id_semaphore == "hs_l0u3B512Ak5" {
|
||||||
|
delete(s.server.semaphore["hs_l0u3B512Ak5"].reservedClientSlots, s.charID)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if len(s.server.semaphore[id].reservedClientSlots) != 0 {
|
if len(s.server.semaphore[id].reservedClientSlots) != 0 {
|
||||||
if s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k3" && s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k4" && s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k5" {
|
if s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k3" &&
|
||||||
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k4" &&
|
||||||
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k5" &&
|
||||||
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B5129k3" &&
|
||||||
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B5129k4" &&
|
||||||
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B5129k5" &&
|
||||||
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B512Ak3" &&
|
||||||
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B512Ak4" &&
|
||||||
|
s.server.semaphore[id].id_semaphore != "hs_l0u3B512Ak5" {
|
||||||
|
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.server.semaphoreLock.Unlock()
|
s.server.semaphoreLock.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,11 +86,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID)
|
fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID)
|
||||||
if !gotNewStage {
|
if !gotNewStage {
|
||||||
s.server.semaphoreLock.Lock()
|
s.server.semaphoreLock.Lock()
|
||||||
if SemaphoreID == "hs_l0u3B51J9k1" ||
|
if strings.HasPrefix(SemaphoreID, "hs_l0u3B51") {
|
||||||
SemaphoreID == "hs_l0u3B51J9k2" ||
|
|
||||||
SemaphoreID == "hs_l0u3B51J9k3" ||
|
|
||||||
SemaphoreID == "hs_l0u3B51J9k4" ||
|
|
||||||
SemaphoreID == "hs_l0u3B51J9k5" {
|
|
||||||
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 32)
|
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 32)
|
||||||
} else {
|
} else {
|
||||||
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 1)
|
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 1)
|
||||||
@@ -68,24 +98,23 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
newSemaphore.Lock()
|
newSemaphore.Lock()
|
||||||
defer newSemaphore.Unlock()
|
defer newSemaphore.Unlock()
|
||||||
if _, exists := newSemaphore.reservedClientSlots[s.charID]; exists {
|
if _, exists := newSemaphore.reservedClientSlots[s.charID]; exists {
|
||||||
s.logger.Info("IS ALREADY EXIST !")
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D})
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D})
|
||||||
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
|
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
|
||||||
switch SemaphoreID {
|
switch SemaphoreID {
|
||||||
case "hs_l0u3B51J9k3":
|
case "hs_l0u3B51J9k3", "hs_l0u3B5129k3", "hs_l0u3B512Ak3":
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
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()
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0E, 0x00, 0x1D})
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0E, 0x00, 0x1D})
|
||||||
case "hs_l0u3B51J9k4":
|
case "hs_l0u3B51J9k4", "hs_l0u3B5129k4", "hs_l0u3B512Ak4":
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.semaphore = newSemaphore
|
s.semaphore = newSemaphore
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0D, 0x00, 0x1D})
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0D, 0x00, 0x1D})
|
||||||
case "hs_l0u3B51J9k5":
|
case "hs_l0u3B51J9k5", "hs_l0u3B5129k5", "hs_l0u3B512Ak5":
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.semaphore = newSemaphore
|
s.semaphore = newSemaphore
|
||||||
@@ -109,29 +138,16 @@ func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
//pkt := p.(*mhfpacket.MsgSysReleaseSemaphore)
|
//pkt := p.(*mhfpacket.MsgSysReleaseSemaphore)
|
||||||
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
releaseRaviSemaphore(s)
|
||||||
reset := len(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots)
|
|
||||||
if reset == 0 {
|
|
||||||
s.server.db.Exec("CALL ravireset($1)", 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeSessionFromSemaphore(s *Session) {
|
|
||||||
|
|
||||||
s.server.semaphoreLock.Lock()
|
|
||||||
for id := range s.server.semaphore {
|
|
||||||
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
|
|
||||||
if id == "hs_l0u3B51J9k3" {
|
|
||||||
delete(s.server.semaphore[id].clients, s)
|
|
||||||
} else {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.server.semaphoreLock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysCheckSemaphore)
|
pkt := p.(*mhfpacket.MsgSysCheckSemaphore)
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
resp := []byte{0x00, 0x00, 0x00, 0x00}
|
||||||
|
s.server.semaphoreLock.Lock()
|
||||||
|
if _, exists := s.server.semaphore[pkt.StageID]; exists {
|
||||||
|
resp = []byte{0x00, 0x00, 0x00, 0x01}
|
||||||
|
}
|
||||||
|
s.server.semaphoreLock.Unlock()
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, resp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package channelserver
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Solenataris/Erupe/network/mhfpacket"
|
"github.com/Solenataris/Erupe/network/mhfpacket"
|
||||||
"github.com/Andoryuuta/byteframe"
|
"github.com/Andoryuuta/byteframe"
|
||||||
@@ -11,13 +12,16 @@ import (
|
|||||||
|
|
||||||
func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysCreateStage)
|
pkt := p.(*mhfpacket.MsgSysCreateStage)
|
||||||
|
s.server.Lock()
|
||||||
s.server.stagesLock.Lock()
|
defer s.server.Unlock()
|
||||||
|
if _, exists := s.server.stages[pkt.StageID]; exists {
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
|
} else {
|
||||||
stage := NewStage(pkt.StageID)
|
stage := NewStage(pkt.StageID)
|
||||||
stage.maxPlayers = uint16(pkt.PlayerCount)
|
stage.maxPlayers = uint16(pkt.PlayerCount)
|
||||||
s.server.stages[stage.id] = stage
|
s.server.stages[stage.id] = stage
|
||||||
s.server.stagesLock.Unlock()
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
@@ -64,58 +68,65 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
// Notify existing stage clients that this new client has entered.
|
// Notify existing stage clients that this new client has entered.
|
||||||
s.logger.Info("Sending MsgSysInsertUser")
|
s.logger.Info("Sending MsgSysInsertUser")
|
||||||
if s.stage != nil { // avoids lock up when using bed for dream quests
|
if s.stage != nil { // avoids lock up when using bed for dream quests
|
||||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysInsertUser{
|
// Add character to everyone elses stage
|
||||||
|
s.stage.BroadcastMHF(&mhfpacket.MsgSysInsertUser {
|
||||||
CharID: s.charID,
|
CharID: s.charID,
|
||||||
}, s)
|
}, s)
|
||||||
|
|
||||||
// It seems to be acceptable to recast all MSG_SYS_SET_USER_BINARY messages so far,
|
// Update others binary of your session
|
||||||
// players are still notified when a new player has joined the stage.
|
s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary {
|
||||||
// These extra messages may not be needed
|
CharID: s.charID,
|
||||||
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
BinaryType: 1,
|
||||||
// CharID: s.charID,
|
}, s)
|
||||||
// BinaryType: 1,
|
s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary {
|
||||||
//}, s)
|
CharID: s.charID,
|
||||||
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
BinaryType: 2,
|
||||||
// CharID: s.charID,
|
}, s)
|
||||||
// BinaryType: 2,
|
s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary {
|
||||||
//}, s)
|
CharID: s.charID,
|
||||||
//s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
BinaryType: 3,
|
||||||
// CharID: s.charID,
|
}, s)
|
||||||
// BinaryType: 3,
|
|
||||||
//}, s)
|
|
||||||
|
|
||||||
//Notify the entree client about all of the existing clients in the stage.
|
// Notify the entree client about all of the existing clients in the stage.
|
||||||
s.logger.Info("Notifying entree about existing stage clients")
|
s.logger.Info("Notifying entree about existing stage clients")
|
||||||
s.stage.RLock()
|
s.stage.RLock()
|
||||||
clientNotif := byteframe.NewByteFrame()
|
clientNotif := byteframe.NewByteFrame()
|
||||||
|
|
||||||
|
// Get other players in the stage
|
||||||
for session := range s.stage.clients {
|
for session := range s.stage.clients {
|
||||||
var cur mhfpacket.MHFPacket
|
var cur mhfpacket.MHFPacket
|
||||||
cur = &mhfpacket.MsgSysInsertUser{
|
cur = &mhfpacket.MsgSysInsertUser{
|
||||||
CharID: session.charID,
|
CharID: session.charID,
|
||||||
}
|
}
|
||||||
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
||||||
cur.Build(clientNotif, session.clientContext)
|
cur.Build(clientNotif, session.clientContext)
|
||||||
|
}
|
||||||
|
|
||||||
cur = &mhfpacket.MsgSysNotifyUserBinary{
|
// Get every players binary
|
||||||
CharID: session.charID,
|
for session := range s.server.sessions {
|
||||||
BinaryType: 1,
|
var cur mhfpacket.MHFPacket
|
||||||
}
|
session := s.server.sessions[session]
|
||||||
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
|
||||||
cur.Build(clientNotif, session.clientContext)
|
|
||||||
|
|
||||||
cur = &mhfpacket.MsgSysNotifyUserBinary{
|
cur = &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
CharID: session.charID,
|
CharID: session.charID,
|
||||||
BinaryType: 2,
|
BinaryType: 1,
|
||||||
}
|
}
|
||||||
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
||||||
cur.Build(clientNotif, session.clientContext)
|
cur.Build(clientNotif, session.clientContext)
|
||||||
|
|
||||||
cur = &mhfpacket.MsgSysNotifyUserBinary{
|
cur = &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
CharID: session.charID,
|
CharID: session.charID,
|
||||||
BinaryType: 3,
|
BinaryType: 2,
|
||||||
}
|
}
|
||||||
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
||||||
cur.Build(clientNotif, session.clientContext)
|
cur.Build(clientNotif, session.clientContext)
|
||||||
|
|
||||||
|
cur = &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
CharID: session.charID,
|
||||||
|
BinaryType: 3,
|
||||||
|
}
|
||||||
|
clientNotif.WriteUint16(uint16(cur.Opcode()))
|
||||||
|
cur.Build(clientNotif, session.clientContext)
|
||||||
}
|
}
|
||||||
s.stage.RUnlock()
|
s.stage.RUnlock()
|
||||||
clientNotif.WriteUint16(0x0010) // End it.
|
clientNotif.WriteUint16(0x0010) // End it.
|
||||||
@@ -143,6 +154,18 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeEmptyStages(s *Session) {
|
||||||
|
s.server.Lock()
|
||||||
|
for sid, stage := range s.server.stages {
|
||||||
|
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
|
||||||
|
if strings.HasPrefix(sid, "sl1Qs") || strings.HasPrefix(sid, "sl2Qs") || strings.HasPrefix(sid, "sl3Qs") {
|
||||||
|
delete(s.server.stages, sid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.server.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
func removeSessionFromStage(s *Session) {
|
func removeSessionFromStage(s *Session) {
|
||||||
s.stage.Lock()
|
s.stage.Lock()
|
||||||
defer s.stage.Unlock()
|
defer s.stage.Unlock()
|
||||||
@@ -151,6 +174,15 @@ func removeSessionFromStage(s *Session) {
|
|||||||
delete(s.stage.clients, s)
|
delete(s.stage.clients, s)
|
||||||
delete(s.stage.reservedClientSlots, s.charID)
|
delete(s.stage.reservedClientSlots, s.charID)
|
||||||
|
|
||||||
|
// Remove client from all reservations
|
||||||
|
s.server.Lock()
|
||||||
|
for _, stage := range s.server.stages {
|
||||||
|
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||||
|
delete(stage.reservedClientSlots, s.charID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.server.Unlock()
|
||||||
|
|
||||||
// Delete old stage objects owned by the client.
|
// Delete old stage objects owned by the client.
|
||||||
s.logger.Info("Sending MsgSysDeleteObject to old stage clients")
|
s.logger.Info("Sending MsgSysDeleteObject to old stage clients")
|
||||||
for objID, stageObject := range s.stage.objects {
|
for objID, stageObject := range s.stage.objects {
|
||||||
@@ -163,14 +195,16 @@ func removeSessionFromStage(s *Session) {
|
|||||||
// Actually delete it form the objects map.
|
// Actually delete it form the objects map.
|
||||||
delete(s.stage.objects, objID)
|
delete(s.stage.objects, objID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for objListID, stageObjectList := range s.stage.objectList {
|
for objListID, stageObjectList := range s.stage.objectList {
|
||||||
if stageObjectList.charid == s.charID {
|
if stageObjectList.charid == s.charID {
|
||||||
//Added to prevent duplicates from flooding ObjectMap and causing server hangs
|
//Added to prevent duplicates from flooding ObjectMap and causing server hangs
|
||||||
s.stage.objectList[objListID].status=false
|
s.stage.objectList[objListID].status=false
|
||||||
s.stage.objectList[objListID].charid=0
|
s.stage.objectList[objListID].charid=0
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeEmptyStages(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -252,7 +286,9 @@ func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.server.stagesLock.Unlock()
|
s.server.stagesLock.Unlock()
|
||||||
|
|
||||||
if !gotStage {
|
if !gotStage {
|
||||||
s.logger.Fatal("Failed to get stage", zap.String("StageID", stageID))
|
s.logger.Error("Failed to get stage", zap.String("StageID", stageID))
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to reserve a slot, fail if full.
|
// Try to reserve a slot, fail if full.
|
||||||
@@ -427,16 +463,18 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
// Build the response
|
// Build the response
|
||||||
resp := byteframe.NewByteFrame()
|
resp := byteframe.NewByteFrame()
|
||||||
resp.WriteUint16(uint16(len(s.server.stages)))
|
bf := byteframe.NewByteFrame()
|
||||||
|
var joinable int
|
||||||
for sid, stage := range s.server.stages {
|
for sid, stage := range s.server.stages {
|
||||||
stage.RLock()
|
stage.RLock()
|
||||||
defer stage.RUnlock()
|
defer stage.RUnlock()
|
||||||
if len(stage.reservedClientSlots)+len(stage.clients) == 0 {
|
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
joinable++
|
||||||
|
|
||||||
resp.WriteUint16(uint16(len(stage.reservedClientSlots))) // Current players.
|
resp.WriteUint16(uint16(len(stage.reservedClientSlots))) // Reserved players.
|
||||||
resp.WriteUint16(0) // Unknown value
|
resp.WriteUint16(0) // Unknown value
|
||||||
|
|
||||||
var hasDeparted uint16
|
var hasDeparted uint16
|
||||||
if stage.hasDeparted {
|
if stage.hasDeparted {
|
||||||
@@ -448,6 +486,8 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
resp.WriteUint8(uint8(len(sid)))
|
resp.WriteUint8(uint8(len(sid)))
|
||||||
resp.WriteBytes([]byte(sid))
|
resp.WriteBytes([]byte(sid))
|
||||||
}
|
}
|
||||||
|
bf.WriteUint16(uint16(joinable))
|
||||||
|
bf.WriteBytes(resp.Data())
|
||||||
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,63 @@ type Server struct {
|
|||||||
|
|
||||||
// Discord chat integration
|
// Discord chat integration
|
||||||
discordSession *discordgo.Session
|
discordSession *discordgo.Session
|
||||||
|
|
||||||
|
raviente *Raviente
|
||||||
|
}
|
||||||
|
|
||||||
|
type Raviente struct {
|
||||||
|
sync.Mutex
|
||||||
|
|
||||||
|
register *RavienteRegister
|
||||||
|
state *RavienteState
|
||||||
|
support *RavienteSupport
|
||||||
|
}
|
||||||
|
|
||||||
|
type RavienteRegister struct {
|
||||||
|
nextTime uint32
|
||||||
|
startTime uint32
|
||||||
|
postTime uint32
|
||||||
|
killedTime uint32
|
||||||
|
ravienteType uint32
|
||||||
|
maxPlayers uint32
|
||||||
|
carveQuest uint32
|
||||||
|
register []uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type RavienteState struct {
|
||||||
|
damageMultiplier uint32
|
||||||
|
stateData []uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type RavienteSupport struct {
|
||||||
|
supportData []uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the Raviente variables for the server
|
||||||
|
func NewRaviente() *Raviente {
|
||||||
|
ravienteRegister := &RavienteRegister {
|
||||||
|
nextTime: 0,
|
||||||
|
startTime: 0,
|
||||||
|
killedTime: 0,
|
||||||
|
postTime: 0,
|
||||||
|
ravienteType: 0,
|
||||||
|
maxPlayers: 0,
|
||||||
|
carveQuest: 0,
|
||||||
|
}
|
||||||
|
ravienteState := &RavienteState {
|
||||||
|
damageMultiplier: 1,
|
||||||
|
}
|
||||||
|
ravienteSupport := &RavienteSupport { }
|
||||||
|
ravienteRegister.register = []uint32{0, 0, 0, 0, 0}
|
||||||
|
ravienteState.stateData = []uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
ravienteSupport.supportData = []uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
|
||||||
|
raviente := &Raviente {
|
||||||
|
register: ravienteRegister,
|
||||||
|
state: ravienteState,
|
||||||
|
support: ravienteSupport,
|
||||||
|
}
|
||||||
|
return raviente
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new Server type.
|
// NewServer creates a new Server type.
|
||||||
|
|||||||
Reference in New Issue
Block a user