mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-25 09:03:10 +01:00
Merge pull request #7 from ZeruLight/feature/obj-indexing
rewrite object indexing, stringstack and bug fixes
This commit is contained in:
@@ -2,33 +2,45 @@ package stringstack
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// StringStack is a basic LIFO "stack" for storing strings.
|
// StringStack is a basic LIFO "stack" for storing strings.
|
||||||
type StringStack struct {
|
type StringStack struct {
|
||||||
sync.Mutex
|
Locked bool
|
||||||
stack []string
|
stack []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new instance of StringStack
|
// New creates a new instance of StringStack
|
||||||
func New() *StringStack {
|
func New() *StringStack {
|
||||||
return &StringStack{}
|
return &StringStack{Locked: false}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets up a new StringStack
|
||||||
|
func (s *StringStack) Set(v string) {
|
||||||
|
s.stack = []string{v}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock freezes the StringStack
|
||||||
|
func (s *StringStack) Lock() {
|
||||||
|
if !s.Locked {
|
||||||
|
s.Locked = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock unfreezes the StringStack
|
||||||
|
func (s *StringStack) Unlock() {
|
||||||
|
if s.Locked {
|
||||||
|
s.Locked = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push pushes a string onto the stack.
|
// Push pushes a string onto the stack.
|
||||||
func (s *StringStack) Push(v string) {
|
func (s *StringStack) Push(v string) {
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.stack = append(s.stack, v)
|
s.stack = append(s.stack, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop pops a string from the stack.
|
// Pop pops a string from the stack.
|
||||||
func (s *StringStack) Pop() (string, error) {
|
func (s *StringStack) Pop() (string, error) {
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
if len(s.stack) == 0 {
|
if len(s.stack) == 0 {
|
||||||
return "", errors.New("no items on stack")
|
return "", errors.New("no items on stack")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"maxlauncherhr": true,
|
"maxlauncherhr": true,
|
||||||
"LogInboundMessages": false,
|
"LogInboundMessages": false,
|
||||||
"LogOutboundMessages": false,
|
"LogOutboundMessages": false,
|
||||||
|
"MaxHexdumpLength": 256,
|
||||||
"Event": 0,
|
"Event": 0,
|
||||||
"DivaEvent": 0,
|
"DivaEvent": 0,
|
||||||
"FestaEvent": 0,
|
"FestaEvent": 0,
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ type DevModeOptions struct {
|
|||||||
FixedStageID bool // Causes all move_stage to use the ID sl1Ns200p0a0u0 to get you into all stages
|
FixedStageID bool // Causes all move_stage to use the ID sl1Ns200p0a0u0 to get you into all stages
|
||||||
LogInboundMessages bool // Log all messages sent to the server
|
LogInboundMessages bool // Log all messages sent to the server
|
||||||
LogOutboundMessages bool // Log all messages sent to the clients
|
LogOutboundMessages bool // Log all messages sent to the clients
|
||||||
|
MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled
|
||||||
DivaEvent int // Diva Defense event status
|
DivaEvent int // Diva Defense event status
|
||||||
FestaEvent int // Hunter's Festa event status
|
FestaEvent int // Hunter's Festa event status
|
||||||
TournamentEvent int // VS Tournament event status
|
TournamentEvent int // VS Tournament event status
|
||||||
|
|||||||
@@ -181,6 +181,8 @@ func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
|
|
||||||
|
updateRights(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ func getCharInfo(server *Server, charName string) string {
|
|||||||
|
|
||||||
objInfo := ""
|
objInfo := ""
|
||||||
|
|
||||||
obj := server.FindStageObjectByChar(c.charID)
|
obj := server.FindObjectByChar(c.charID)
|
||||||
// server.logger.Info("Found object: %+v", zap.Object("obj", obj))
|
// server.logger.Info("Found object: %+v", zap.Object("obj", obj))
|
||||||
|
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
|
|||||||
@@ -10,44 +10,31 @@ import (
|
|||||||
func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysCreateObject)
|
pkt := p.(*mhfpacket.MsgSysCreateObject)
|
||||||
|
|
||||||
// Lock the stage.
|
s.stage.Lock()
|
||||||
s.server.Lock()
|
newObj := &Object{
|
||||||
|
id: s.stage.NextObjectID(),
|
||||||
// Make a new stage object and insert it into the stage.
|
|
||||||
objID := s.stage.GetNewObjectID(s.charID)
|
|
||||||
newObj := &StageObject{
|
|
||||||
id: objID,
|
|
||||||
ownerCharID: s.charID,
|
ownerCharID: s.charID,
|
||||||
x: pkt.X,
|
x: pkt.X,
|
||||||
y: pkt.Y,
|
y: pkt.Y,
|
||||||
z: pkt.Z,
|
z: pkt.Z,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.stage.objects[s.charID] = newObj
|
s.stage.objects[s.charID] = newObj
|
||||||
|
s.stage.Unlock()
|
||||||
|
|
||||||
// Unlock the stage.
|
|
||||||
s.server.Unlock()
|
|
||||||
// Response to our requesting client.
|
// Response to our requesting client.
|
||||||
resp := byteframe.NewByteFrame()
|
resp := byteframe.NewByteFrame()
|
||||||
resp.WriteUint32(objID) // New local obj handle.
|
resp.WriteUint32(newObj.id) // New local obj handle.
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
// Duplicate the object creation to all sessions in the same stage.
|
// Duplicate the object creation to all sessions in the same stage.
|
||||||
dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{
|
dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{
|
||||||
ObjID: objID,
|
ObjID: newObj.id,
|
||||||
X: pkt.X,
|
X: newObj.x,
|
||||||
Y: pkt.Y,
|
Y: newObj.y,
|
||||||
Z: pkt.Z,
|
Z: newObj.z,
|
||||||
OwnerCharID: s.charID,
|
OwnerCharID: newObj.ownerCharID,
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 1; i <= 3; i++ {
|
s.logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, s.charID))
|
||||||
s.server.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{
|
|
||||||
CharID: s.charID,
|
|
||||||
BinaryType: uint8(i),
|
|
||||||
}, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.logger.Info("Duplicate a new characters to others clients")
|
|
||||||
s.stage.BroadcastMHF(dupObjUpdate, s)
|
s.stage.BroadcastMHF(dupObjUpdate, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +61,14 @@ func handleMsgSysRotateObject(s *Session, p mhfpacket.MHFPacket) {}
|
|||||||
|
|
||||||
func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
pkt := p.(*mhfpacket.MsgSysSetObjectBinary)
|
||||||
|
for _, object := range s.stage.objects {
|
||||||
|
if object.id == pkt.ObjID {
|
||||||
|
object.binary = pkt.RawDataPayload
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysGetObjectBinary(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysGetObjectBinary(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
// Get quest file.
|
// Get quest file.
|
||||||
data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename)))
|
data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
s.logger.Fatal(fmt.Sprintf("Failed to open quest file: quests/%s.bin", pkt.Filename))
|
||||||
}
|
}
|
||||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest)
|
pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest)
|
||||||
var data []byte
|
var data []byte
|
||||||
err := s.server.db.QueryRow("SELECT savefavoritequest FROM characters WHERE id = $1", s.charID).Scan(&data)
|
err := s.server.db.QueryRow("SELECT savefavoritequest FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||||
if err == nil {
|
if err == nil && len(data) > 0 {
|
||||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||||
} else {
|
} else {
|
||||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
doAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
@@ -68,8 +68,6 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
} else {
|
} else {
|
||||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||||
}
|
}
|
||||||
// Update the client's rights as well:
|
|
||||||
updateRights(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfEnterTournamentQuest(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfEnterTournamentQuest(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|||||||
@@ -108,29 +108,10 @@ func removeSessionFromStage(s *Session) {
|
|||||||
|
|
||||||
// Delete old stage objects owned by the client.
|
// Delete old stage objects owned by the client.
|
||||||
s.logger.Info("Sending notification to old stage clients")
|
s.logger.Info("Sending notification to old stage clients")
|
||||||
for objID, stageObject := range s.stage.objects {
|
for _, object := range s.stage.objects {
|
||||||
if stageObject.ownerCharID == s.charID {
|
if object.ownerCharID == s.charID {
|
||||||
clientNotif := byteframe.NewByteFrame()
|
s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.id}, s)
|
||||||
var pkt mhfpacket.MHFPacket
|
delete(s.stage.objects, object.ownerCharID)
|
||||||
pkt = &mhfpacket.MsgSysDeleteObject{
|
|
||||||
ObjID: stageObject.id,
|
|
||||||
}
|
|
||||||
clientNotif.WriteUint16(uint16(pkt.Opcode()))
|
|
||||||
pkt.Build(clientNotif, s.clientContext)
|
|
||||||
clientNotif.WriteUint16(0x0010)
|
|
||||||
for client, _ := range s.stage.clients {
|
|
||||||
client.QueueSend(clientNotif.Data())
|
|
||||||
}
|
|
||||||
// TODO(Andoryuuta): Should this be sent to the owner's client as well? it currently isn't.
|
|
||||||
// Actually delete it from the objects map.
|
|
||||||
delete(s.stage.objects, objID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for objListID, stageObjectList := range s.stage.objectList {
|
|
||||||
if stageObjectList.charid == s.charID {
|
|
||||||
// Added to prevent duplicates from flooding ObjectMap and causing server hangs
|
|
||||||
s.stage.objectList[objListID].status = false
|
|
||||||
s.stage.objectList[objListID].charid = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.stage.Unlock()
|
s.stage.Unlock()
|
||||||
@@ -140,44 +121,20 @@ func removeSessionFromStage(s *Session) {
|
|||||||
|
|
||||||
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
||||||
|
|
||||||
// Push our current stage ID to the movement stack before entering another one.
|
// Push our current stage ID to the movement stack before entering another one.
|
||||||
s.Lock()
|
if s.stageID == "" {
|
||||||
s.stageMoveStack.Push(s.stageID)
|
s.stageMoveStack.Set(pkt.StageID)
|
||||||
s.Unlock()
|
} else {
|
||||||
|
s.stageMoveStack.Push(s.stageID)
|
||||||
|
s.stageMoveStack.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
s.QueueSendMHF(&mhfpacket.MsgSysCleanupObject{})
|
s.QueueSendMHF(&mhfpacket.MsgSysCleanupObject{})
|
||||||
if s.reservationStage != nil {
|
if s.reservationStage != nil {
|
||||||
s.reservationStage = nil
|
s.reservationStage = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if pkt.StageID == "sl1Ns200p0a0u0" { // First entry
|
|
||||||
var temp mhfpacket.MHFPacket
|
|
||||||
loginNotif := byteframe.NewByteFrame()
|
|
||||||
s.server.Lock()
|
|
||||||
for _, session := range s.server.sessions {
|
|
||||||
if s == session || !session.binariesDone {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
temp = &mhfpacket.MsgSysInsertUser{
|
|
||||||
CharID: session.charID,
|
|
||||||
}
|
|
||||||
loginNotif.WriteUint16(uint16(temp.Opcode()))
|
|
||||||
temp.Build(loginNotif, s.clientContext)
|
|
||||||
for i := 1; i <= 3; i++ {
|
|
||||||
temp = &mhfpacket.MsgSysNotifyUserBinary{
|
|
||||||
CharID: session.charID,
|
|
||||||
BinaryType: uint8(i),
|
|
||||||
}
|
|
||||||
loginNotif.WriteUint16(uint16(temp.Opcode()))
|
|
||||||
temp.Build(loginNotif, s.clientContext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.server.Unlock()
|
|
||||||
loginNotif.WriteUint16(0x0010) // End it.
|
|
||||||
if len(loginNotif.Data()) > 2 {
|
|
||||||
s.QueueSend(loginNotif.Data())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,9 +142,8 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysBackStage)
|
pkt := p.(*mhfpacket.MsgSysBackStage)
|
||||||
|
|
||||||
// Transfer back to the saved stage ID before the previous move or enter.
|
// Transfer back to the saved stage ID before the previous move or enter.
|
||||||
s.Lock()
|
s.stageMoveStack.Unlock()
|
||||||
backStage, err := s.stageMoveStack.Pop()
|
backStage, err := s.stageMoveStack.Pop()
|
||||||
s.Unlock()
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -199,10 +155,10 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysMoveStage)
|
pkt := p.(*mhfpacket.MsgSysMoveStage)
|
||||||
|
|
||||||
// Push our current stage ID to the movement stack before entering another one.
|
// Set a new move stack from the given stage ID if unlocked
|
||||||
s.Lock()
|
if !s.stageMoveStack.Locked {
|
||||||
s.stageMoveStack.Push(s.stageID)
|
s.stageMoveStack.Set(pkt.StageID)
|
||||||
s.Unlock()
|
}
|
||||||
|
|
||||||
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
doStageTransfer(s, pkt.AckHandle, pkt.StageID)
|
||||||
}
|
}
|
||||||
@@ -219,11 +175,9 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.reservationStage.RLock()
|
s.reservationStage.RLock()
|
||||||
defer s.reservationStage.RUnlock()
|
defer s.reservationStage.RUnlock()
|
||||||
|
|
||||||
destructMessage := &mhfpacket.MsgSysStageDestruct{}
|
|
||||||
|
|
||||||
for charID := range s.reservationStage.reservedClientSlots {
|
for charID := range s.reservationStage.reservedClientSlots {
|
||||||
session := s.server.FindSessionByCharID(charID)
|
session := s.server.FindSessionByCharID(charID)
|
||||||
session.QueueSendMHF(destructMessage)
|
session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
||||||
}
|
}
|
||||||
|
|
||||||
s.server.Lock()
|
s.server.Lock()
|
||||||
|
|||||||
@@ -12,6 +12,49 @@ func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {}
|
|||||||
|
|
||||||
func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
|
func broadcastNewUser(s *Session) {
|
||||||
|
s.logger.Debug(fmt.Sprintf("Broadcasting new user: %s (%d)", s.Name, s.charID))
|
||||||
|
|
||||||
|
clientNotif := byteframe.NewByteFrame()
|
||||||
|
var temp mhfpacket.MHFPacket
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session == s || !session.binariesDone {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID}
|
||||||
|
clientNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(clientNotif, s.clientContext)
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
temp = &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
CharID: session.charID,
|
||||||
|
BinaryType: uint8(i + 1),
|
||||||
|
}
|
||||||
|
clientNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(clientNotif, s.clientContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.QueueSend(clientNotif.Data())
|
||||||
|
|
||||||
|
serverNotif := byteframe.NewByteFrame()
|
||||||
|
temp = &mhfpacket.MsgSysInsertUser{CharID: s.charID}
|
||||||
|
serverNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(serverNotif, s.clientContext)
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
temp = &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
CharID: s.charID,
|
||||||
|
BinaryType: uint8(i + 1),
|
||||||
|
}
|
||||||
|
serverNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(serverNotif, s.clientContext)
|
||||||
|
}
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session == s || !session.binariesDone {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
session.QueueSend(serverNotif.Data())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysSetUserBinary)
|
pkt := p.(*mhfpacket.MsgSysSetUserBinary)
|
||||||
s.server.userBinaryPartsLock.Lock()
|
s.server.userBinaryPartsLock.Lock()
|
||||||
@@ -27,9 +70,7 @@ func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.binariesDone = true
|
s.binariesDone = true
|
||||||
s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{
|
broadcastNewUser(s)
|
||||||
CharID: s.charID,
|
|
||||||
}, s)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ func (s *Server) manageSessions() {
|
|||||||
func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||||
// Broadcast the data.
|
// Broadcast the data.
|
||||||
for _, session := range s.sessions {
|
for _, session := range s.sessions {
|
||||||
if session == ignoredSession {
|
if session == ignoredSession || !session.binariesDone {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,14 +300,14 @@ func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session)
|
|||||||
|
|
||||||
func (s *Server) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
func (s *Server) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||||
for _, c := range s.Channels {
|
for _, c := range s.Channels {
|
||||||
for _, s := range c.sessions {
|
for _, session := range c.sessions {
|
||||||
if s == ignoredSession {
|
if session == ignoredSession || !session.binariesDone {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteUint16(uint16(pkt.Opcode()))
|
bf.WriteUint16(uint16(pkt.Opcode()))
|
||||||
pkt.Build(bf, s.clientContext)
|
pkt.Build(bf, session.clientContext)
|
||||||
s.QueueSendNonBlocking(bf.Data())
|
session.QueueSendNonBlocking(bf.Data())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,7 +389,7 @@ func (s *Server) FindSessionByCharID(charID uint32) *Session {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) FindStageObjectByChar(charID uint32) *StageObject {
|
func (s *Server) FindObjectByChar(charID uint32) *Object {
|
||||||
s.stagesLock.RLock()
|
s.stagesLock.RLock()
|
||||||
defer s.stagesLock.RUnlock()
|
defer s.stagesLock.RUnlock()
|
||||||
for _, stage := range s.stages {
|
for _, stage := range s.stages {
|
||||||
|
|||||||
@@ -251,5 +251,9 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien
|
|||||||
}
|
}
|
||||||
fmt.Printf("[%s] -> [%s]\n", sender, recipient)
|
fmt.Printf("[%s] -> [%s]\n", sender, recipient)
|
||||||
fmt.Printf("Opcode: %s\n", opcodePID)
|
fmt.Printf("Opcode: %s\n", opcodePID)
|
||||||
fmt.Printf("Data [%d bytes]:\n%s\n", len(data), hex.Dump(data))
|
if len(data) <= s.server.erupeConfig.DevModeOptions.MaxHexdumpLength {
|
||||||
|
fmt.Printf("Data [%d bytes]:\n%s\n", len(data), hex.Dump(data))
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Data [%d bytes]:\n(Too long!)\n\n", len(data))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,18 +9,13 @@ import (
|
|||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StageObject holds infomation about a specific stage object.
|
// Object holds infomation about a specific object.
|
||||||
type StageObject struct {
|
type Object struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
id uint32
|
id uint32
|
||||||
ownerCharID uint32
|
ownerCharID uint32
|
||||||
x, y, z float32
|
x, y, z float32
|
||||||
}
|
binary []byte
|
||||||
|
|
||||||
type ObjectMap struct {
|
|
||||||
id uint8
|
|
||||||
charid uint32
|
|
||||||
status bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// stageBinaryKey is a struct used as a map key for identifying a stage binary part.
|
// stageBinaryKey is a struct used as a map key for identifying a stage binary part.
|
||||||
@@ -36,13 +31,10 @@ type Stage struct {
|
|||||||
// Stage ID string
|
// Stage ID string
|
||||||
id string
|
id string
|
||||||
|
|
||||||
// Total count of objects ever created for this stage. Used for ObjID generation.
|
// Objects
|
||||||
gameObjectCount uint32
|
objects map[uint32]*Object
|
||||||
|
objectIndex uint32
|
||||||
|
|
||||||
// Save all object in stage
|
|
||||||
objects map[uint32]*StageObject
|
|
||||||
|
|
||||||
objectList map[uint8]*ObjectMap
|
|
||||||
// Map of session -> charID.
|
// Map of session -> charID.
|
||||||
// These are clients that are CURRENTLY in the stage
|
// These are clients that are CURRENTLY in the stage
|
||||||
clients map[*Session]uint32
|
clients map[*Session]uint32
|
||||||
@@ -66,14 +58,12 @@ func NewStage(ID string) *Stage {
|
|||||||
id: ID,
|
id: ID,
|
||||||
clients: make(map[*Session]uint32),
|
clients: make(map[*Session]uint32),
|
||||||
reservedClientSlots: make(map[uint32]bool),
|
reservedClientSlots: make(map[uint32]bool),
|
||||||
objects: make(map[uint32]*StageObject),
|
objects: make(map[uint32]*Object),
|
||||||
|
objectIndex: 0,
|
||||||
rawBinaryData: make(map[stageBinaryKey][]byte),
|
rawBinaryData: make(map[stageBinaryKey][]byte),
|
||||||
maxPlayers: 4,
|
maxPlayers: 4,
|
||||||
gameObjectCount: 1,
|
|
||||||
objectList: make(map[uint8]*ObjectMap),
|
|
||||||
createdAt: time.Now().Format("01-02-2006 15:04:05"),
|
createdAt: time.Now().Format("01-02-2006 15:04:05"),
|
||||||
}
|
}
|
||||||
s.InitObjectList()
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +71,7 @@ func NewStage(ID string) *Stage {
|
|||||||
func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||||
// Broadcast the data.
|
// Broadcast the data.
|
||||||
for session := range s.clients {
|
for session := range s.clients {
|
||||||
if session == ignoredSession {
|
if session == ignoredSession || !session.binariesDone {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,17 +87,6 @@ func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stage) InitObjectList() {
|
|
||||||
for seq := uint8(0x7f); seq > uint8(0); seq-- {
|
|
||||||
newObj := &ObjectMap{
|
|
||||||
id: seq,
|
|
||||||
charid: uint32(0),
|
|
||||||
status: false,
|
|
||||||
}
|
|
||||||
s.objectList[seq] = newObj
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Stage) isCharInQuestByID(charID uint32) bool {
|
func (s *Stage) isCharInQuestByID(charID uint32) bool {
|
||||||
if _, exists := s.reservedClientSlots[charID]; exists {
|
if _, exists := s.reservedClientSlots[charID]; exists {
|
||||||
return exists
|
return exists
|
||||||
@@ -120,8 +99,8 @@ func (s *Stage) isQuest() bool {
|
|||||||
return len(s.reservedClientSlots) > 0
|
return len(s.reservedClientSlots) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stage *Stage) GetName() string {
|
func (s *Stage) GetName() string {
|
||||||
switch stage.id {
|
switch s.id {
|
||||||
case MezeportaStageId:
|
case MezeportaStageId:
|
||||||
return "Mezeporta"
|
return "Mezeporta"
|
||||||
case GuildHallLv1StageId:
|
case GuildHallLv1StageId:
|
||||||
@@ -149,20 +128,7 @@ func (stage *Stage) GetName() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stage) GetNewObjectID(CharID uint32) uint32 {
|
func (s *Stage) NextObjectID() uint32 {
|
||||||
ObjId := uint8(0)
|
s.objectIndex = s.objectIndex + 1
|
||||||
for seq := uint8(0x7f); seq > uint8(0); seq-- {
|
return s.objectIndex
|
||||||
if s.objectList[seq].status == false {
|
|
||||||
ObjId = seq
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.objectList[ObjId].status = true
|
|
||||||
s.objectList[ObjId].charid = CharID
|
|
||||||
bf := byteframe.NewByteFrame()
|
|
||||||
bf.WriteUint8(uint8(0))
|
|
||||||
bf.WriteUint8(ObjId)
|
|
||||||
bf.WriteUint16(uint16(0))
|
|
||||||
obj := uint32(bf.Data()[3]) | uint32(bf.Data()[2])<<8 | uint32(bf.Data()[1])<<16 | uint32(bf.Data()[0])<<32
|
|
||||||
return obj
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user