mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-16 17:05:03 +01:00
@@ -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
|
||||||
|
|||||||
26
Erupe/gook.sql
Normal file
26
Erupe/gook.sql
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.gook
|
||||||
|
DROP COLUMN IF EXISTS gook0status;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.gook
|
||||||
|
DROP COLUMN IF EXISTS gook1status;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.gook
|
||||||
|
DROP COLUMN IF EXISTS gook2status;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.gook
|
||||||
|
DROP COLUMN IF EXISTS gook3status;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.gook
|
||||||
|
DROP COLUMN IF EXISTS gook4status;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.gook
|
||||||
|
DROP COLUMN IF EXISTS gook5status;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.gook
|
||||||
|
DROP COLUMN IF EXISTS gook5;
|
||||||
|
|
||||||
|
UPDATE public.gook SET gook1=NULL, gook2=NULL, gook3=NULL, gook4=NULL;
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -2,6 +2,7 @@ package mhfpacket
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"erupe-ce/common/stringsupport"
|
||||||
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
"erupe-ce/network"
|
"erupe-ce/network"
|
||||||
@@ -14,7 +15,7 @@ type MsgMhfEnumerateHouse struct {
|
|||||||
CharID uint32
|
CharID uint32
|
||||||
Method uint8
|
Method uint8
|
||||||
Unk uint16
|
Unk uint16
|
||||||
Name []byte
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -29,7 +30,7 @@ func (m *MsgMhfEnumerateHouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cli
|
|||||||
m.Method = bf.ReadUint8()
|
m.Method = bf.ReadUint8()
|
||||||
m.Unk = bf.ReadUint16()
|
m.Unk = bf.ReadUint16()
|
||||||
_ = bf.ReadUint8() // len
|
_ = bf.ReadUint8() // len
|
||||||
m.Name = bf.ReadNullTerminatedBytes()
|
m.Name = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package mhfpacket
|
package mhfpacket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"erupe-ce/network/clientctx"
|
|
||||||
"erupe-ce/network"
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
|
"erupe-ce/network"
|
||||||
|
"erupe-ce/network/clientctx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgMhfEnumerateTitle represents the MSG_MHF_ENUMERATE_TITLE
|
// MsgMhfEnumerateTitle represents the MSG_MHF_ENUMERATE_TITLE
|
||||||
type MsgMhfEnumerateTitle struct {
|
type MsgMhfEnumerateTitle struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint32
|
CharID uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -21,9 +21,9 @@ func (m *MsgMhfEnumerateTitle) Opcode() network.PacketID {
|
|||||||
|
|
||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfEnumerateTitle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfEnumerateTitle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint32()
|
m.CharID = bf.ReadUint32()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
|
|||||||
@@ -1,29 +1,23 @@
|
|||||||
package mhfpacket
|
package mhfpacket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"erupe-ce/common/stringsupport"
|
||||||
|
|
||||||
"erupe-ce/network/clientctx"
|
|
||||||
"erupe-ce/network"
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
|
"erupe-ce/network"
|
||||||
|
"erupe-ce/network/clientctx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgMhfLoadHouse represents the MSG_MHF_LOAD_HOUSE
|
// MsgMhfLoadHouse represents the MSG_MHF_LOAD_HOUSE
|
||||||
type MsgMhfLoadHouse struct {
|
type MsgMhfLoadHouse struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
CharID uint32
|
CharID uint32
|
||||||
// dest?
|
Destination uint8
|
||||||
// 0x3 = house
|
// False if already in hosts My Series, in case host updates PW
|
||||||
// 0x4 = bookshelf
|
CheckPass bool
|
||||||
// 0x5 = gallery
|
Unk3 uint16 // Hardcoded 0 in binary
|
||||||
// 0x8 = tore
|
Password string
|
||||||
// 0x9 = own house
|
|
||||||
// 0xA = garden
|
|
||||||
Unk1 uint8
|
|
||||||
// bool inMezSquare?
|
|
||||||
Unk2 uint8
|
|
||||||
Unk3 uint16 // Hardcoded 0 in binary
|
|
||||||
Password []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -35,11 +29,11 @@ func (m *MsgMhfLoadHouse) Opcode() network.PacketID {
|
|||||||
func (m *MsgMhfLoadHouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfLoadHouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.CharID = bf.ReadUint32()
|
m.CharID = bf.ReadUint32()
|
||||||
m.Unk1 = bf.ReadUint8()
|
m.Destination = bf.ReadUint8()
|
||||||
m.Unk2 = bf.ReadUint8()
|
m.CheckPass = bf.ReadBool()
|
||||||
_ = bf.ReadUint16()
|
_ = bf.ReadUint16()
|
||||||
_ = bf.ReadUint8() // Password length
|
_ = bf.ReadUint8() // Password length
|
||||||
m.Password = bf.ReadNullTerminatedBytes()
|
m.Password = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,20 @@
|
|||||||
package mhfpacket
|
package mhfpacket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"erupe-ce/network/clientctx"
|
|
||||||
"erupe-ce/network"
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
|
"erupe-ce/network"
|
||||||
|
"erupe-ce/network/clientctx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GuacotUpdateEntry represents an entry inside the MsgMhfUpdateGuacot packet.
|
type Gook struct {
|
||||||
type GuacotUpdateEntry struct {
|
Exists bool
|
||||||
Unk0 uint32
|
Index uint32
|
||||||
Unk1 uint16
|
Type uint16
|
||||||
Unk2 uint16
|
Data []byte
|
||||||
Unk3 uint16
|
NameLen uint8
|
||||||
Unk4 uint16
|
Name []byte
|
||||||
Unk5 uint16
|
|
||||||
Unk6 uint16
|
|
||||||
Unk7 uint16
|
|
||||||
Unk8 uint16
|
|
||||||
Unk9 uint16
|
|
||||||
Unk10 uint16
|
|
||||||
Unk11 uint16
|
|
||||||
Unk12 uint16
|
|
||||||
Unk13 uint16
|
|
||||||
Unk14 uint16
|
|
||||||
Unk15 uint16
|
|
||||||
Unk16 uint16
|
|
||||||
Unk17 uint16
|
|
||||||
Unk18 uint16
|
|
||||||
Unk19 uint16
|
|
||||||
Unk20 uint16
|
|
||||||
Unk21 uint16
|
|
||||||
Unk22 uint16
|
|
||||||
Unk23 uint32
|
|
||||||
Unk24 uint32
|
|
||||||
DataSize uint8
|
|
||||||
RawDataPayload []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MsgMhfUpdateGuacot represents the MSG_MHF_UPDATE_GUACOT
|
// MsgMhfUpdateGuacot represents the MSG_MHF_UPDATE_GUACOT
|
||||||
@@ -44,7 +22,7 @@ type MsgMhfUpdateGuacot struct {
|
|||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
EntryCount uint16
|
EntryCount uint16
|
||||||
Unk0 uint16 // Hardcoded 0 in binary
|
Unk0 uint16 // Hardcoded 0 in binary
|
||||||
Entries []*GuacotUpdateEntry
|
Gooks []Gook
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -58,38 +36,18 @@ func (m *MsgMhfUpdateGuacot) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clien
|
|||||||
m.EntryCount = bf.ReadUint16()
|
m.EntryCount = bf.ReadUint16()
|
||||||
m.Unk0 = bf.ReadUint16()
|
m.Unk0 = bf.ReadUint16()
|
||||||
for i := 0; i < int(m.EntryCount); i++ {
|
for i := 0; i < int(m.EntryCount); i++ {
|
||||||
// Yikes.
|
e := Gook{}
|
||||||
e := &GuacotUpdateEntry{}
|
e.Index = bf.ReadUint32()
|
||||||
|
e.Type = bf.ReadUint16()
|
||||||
e.Unk0 = bf.ReadUint32()
|
e.Data = bf.ReadBytes(50)
|
||||||
e.Unk1 = bf.ReadUint16()
|
e.NameLen = bf.ReadUint8()
|
||||||
e.Unk2 = bf.ReadUint16()
|
e.Name = bf.ReadBytes(uint(e.NameLen))
|
||||||
e.Unk3 = bf.ReadUint16()
|
if e.Type > 0 {
|
||||||
e.Unk4 = bf.ReadUint16()
|
e.Exists = true
|
||||||
e.Unk5 = bf.ReadUint16()
|
} else {
|
||||||
e.Unk6 = bf.ReadUint16()
|
e.Exists = false
|
||||||
e.Unk7 = bf.ReadUint16()
|
}
|
||||||
e.Unk8 = bf.ReadUint16()
|
m.Gooks = append(m.Gooks, e)
|
||||||
e.Unk9 = bf.ReadUint16()
|
|
||||||
e.Unk10 = bf.ReadUint16()
|
|
||||||
e.Unk11 = bf.ReadUint16()
|
|
||||||
e.Unk12 = bf.ReadUint16()
|
|
||||||
e.Unk13 = bf.ReadUint16()
|
|
||||||
e.Unk14 = bf.ReadUint16()
|
|
||||||
e.Unk15 = bf.ReadUint16()
|
|
||||||
e.Unk16 = bf.ReadUint16()
|
|
||||||
e.Unk17 = bf.ReadUint16()
|
|
||||||
e.Unk18 = bf.ReadUint16()
|
|
||||||
e.Unk19 = bf.ReadUint16()
|
|
||||||
e.Unk20 = bf.ReadUint16()
|
|
||||||
e.Unk21 = bf.ReadUint16()
|
|
||||||
e.Unk22 = bf.ReadUint16()
|
|
||||||
e.Unk23 = bf.ReadUint32()
|
|
||||||
e.Unk24 = bf.ReadUint32()
|
|
||||||
e.DataSize = bf.ReadUint8()
|
|
||||||
e.RawDataPayload = bf.ReadBytes(uint(e.DataSize))
|
|
||||||
|
|
||||||
m.Entries = append(m.Entries, e)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -98,36 +56,3 @@ func (m *MsgMhfUpdateGuacot) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clien
|
|||||||
func (m *MsgMhfUpdateGuacot) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfUpdateGuacot) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
return errors.New("NOT IMPLEMENTED")
|
return errors.New("NOT IMPLEMENTED")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MsgMhfUpdateGuacot) GuacotUpdateEntryToBytes(Entry *GuacotUpdateEntry) []byte {
|
|
||||||
resp:= byteframe.NewByteFrame()
|
|
||||||
resp.WriteUint32(Entry.Unk0)
|
|
||||||
resp.WriteUint16(Entry.Unk1)
|
|
||||||
resp.WriteUint16(Entry.Unk1)
|
|
||||||
resp.WriteUint16(Entry.Unk2)
|
|
||||||
resp.WriteUint16(Entry.Unk3)
|
|
||||||
resp.WriteUint16(Entry.Unk4)
|
|
||||||
resp.WriteUint16(Entry.Unk5)
|
|
||||||
resp.WriteUint16(Entry.Unk6)
|
|
||||||
resp.WriteUint16(Entry.Unk7)
|
|
||||||
resp.WriteUint16(Entry.Unk8)
|
|
||||||
resp.WriteUint16(Entry.Unk9)
|
|
||||||
resp.WriteUint16(Entry.Unk10)
|
|
||||||
resp.WriteUint16(Entry.Unk11)
|
|
||||||
resp.WriteUint16(Entry.Unk12)
|
|
||||||
resp.WriteUint16(Entry.Unk13)
|
|
||||||
resp.WriteUint16(Entry.Unk14)
|
|
||||||
resp.WriteUint16(Entry.Unk15)
|
|
||||||
resp.WriteUint16(Entry.Unk16)
|
|
||||||
resp.WriteUint16(Entry.Unk17)
|
|
||||||
resp.WriteUint16(Entry.Unk18)
|
|
||||||
resp.WriteUint16(Entry.Unk19)
|
|
||||||
resp.WriteUint16(Entry.Unk20)
|
|
||||||
resp.WriteUint16(Entry.Unk21)
|
|
||||||
resp.WriteUint16(Entry.Unk22)
|
|
||||||
resp.WriteUint32(Entry.Unk23)
|
|
||||||
resp.WriteUint32(Entry.Unk24)
|
|
||||||
resp.WriteUint8(Entry.DataSize)
|
|
||||||
resp.WriteBytes(Entry.RawDataPayload)
|
|
||||||
return resp.Data()
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@ package mhfpacket
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"erupe-ce/common/stringsupport"
|
||||||
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
"erupe-ce/network"
|
"erupe-ce/network"
|
||||||
@@ -11,15 +12,10 @@ import (
|
|||||||
// MsgMhfUpdateHouse represents the MSG_MHF_UPDATE_HOUSE
|
// MsgMhfUpdateHouse represents the MSG_MHF_UPDATE_HOUSE
|
||||||
type MsgMhfUpdateHouse struct {
|
type MsgMhfUpdateHouse struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
// 01 = closed
|
State uint8
|
||||||
// 02 = open anyone
|
Unk1 uint8 // Always 0x01
|
||||||
// 03 = open friends
|
Unk2 uint16 // Always 0x0000
|
||||||
// 04 = open guild
|
Password string
|
||||||
// 05 = open friends guild
|
|
||||||
State uint8
|
|
||||||
Unk1 uint8 // Always 0x01
|
|
||||||
Unk2 uint16 // Always 0x0000
|
|
||||||
Password string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
@@ -33,8 +29,8 @@ func (m *MsgMhfUpdateHouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Client
|
|||||||
m.State = bf.ReadUint8()
|
m.State = bf.ReadUint8()
|
||||||
m.Unk1 = bf.ReadUint8()
|
m.Unk1 = bf.ReadUint8()
|
||||||
m.Unk2 = bf.ReadUint16()
|
m.Unk2 = bf.ReadUint16()
|
||||||
_ = bf.ReadUint8()
|
_ = bf.ReadUint8() // Password length
|
||||||
m.Password = string(bf.ReadNullTerminatedBytes())
|
m.Password = stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// MsgSysOperateRegister represents the MSG_SYS_OPERATE_REGISTER
|
// MsgSysOperateRegister represents the MSG_SYS_OPERATE_REGISTER
|
||||||
type MsgSysOperateRegister struct {
|
type MsgSysOperateRegister struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
RegisterID uint32
|
SemaphoreID uint32
|
||||||
fixedZero uint16
|
fixedZero uint16
|
||||||
RawDataPayload []byte
|
RawDataPayload []byte
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ func (m *MsgSysOperateRegister) Opcode() network.PacketID {
|
|||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgSysOperateRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgSysOperateRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.RegisterID = bf.ReadUint32()
|
m.SemaphoreID = bf.ReadUint32()
|
||||||
m.fixedZero = bf.ReadUint16()
|
m.fixedZero = bf.ReadUint16()
|
||||||
|
|
||||||
if m.fixedZero != 0 {
|
if m.fixedZero != 0 {
|
||||||
@@ -39,7 +39,7 @@ func (m *MsgSysOperateRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl
|
|||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
func (m *MsgSysOperateRegister) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgSysOperateRegister) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
bf.WriteUint32(m.AckHandle)
|
bf.WriteUint32(m.AckHandle)
|
||||||
bf.WriteUint32(m.RegisterID)
|
bf.WriteUint32(m.SemaphoreID)
|
||||||
bf.WriteUint16(0)
|
bf.WriteUint16(0)
|
||||||
bf.WriteUint16(uint16(len(m.RawDataPayload)))
|
bf.WriteUint16(uint16(len(m.RawDataPayload)))
|
||||||
bf.WriteBytes(m.RawDataPayload)
|
bf.WriteBytes(m.RawDataPayload)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
@@ -579,125 +579,51 @@ func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
|
func getGookData(s *Session, cid uint32) (uint16, []byte) {
|
||||||
|
var data []byte
|
||||||
|
var count uint16
|
||||||
|
bf := byteframe.NewByteFrame()
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
err := s.server.db.QueryRow(fmt.Sprintf("SELECT gook%d FROM gook WHERE id=$1", i), cid).Scan(&data)
|
||||||
|
if err == nil && data != nil {
|
||||||
|
count++
|
||||||
|
if s.charID == cid && count == 1 {
|
||||||
|
gook := byteframe.NewByteFrameFromBytes(data)
|
||||||
|
bf.WriteBytes(gook.ReadBytes(4))
|
||||||
|
d := gook.ReadBytes(2)
|
||||||
|
bf.WriteBytes(d)
|
||||||
|
bf.WriteBytes(d)
|
||||||
|
bf.WriteBytes(gook.DataFromCurrent())
|
||||||
|
} else {
|
||||||
|
bf.WriteBytes(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count, bf.Data()
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgMhfEnumerateGuacot(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfEnumerateGuacot(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuacot)
|
pkt := p.(*mhfpacket.MsgMhfEnumerateGuacot)
|
||||||
var data bool
|
bf := byteframe.NewByteFrame()
|
||||||
err := s.server.db.QueryRow("SELECT gook0status FROM gook WHERE id = $1", s.charID).Scan(&data)
|
count, data := getGookData(s, s.charID)
|
||||||
if err == nil {
|
bf.WriteUint16(count)
|
||||||
tempresp := byteframe.NewByteFrame()
|
bf.WriteBytes(data)
|
||||||
count := uint16(0)
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
var gook0 []byte
|
|
||||||
var gook1 []byte
|
|
||||||
var gook2 []byte
|
|
||||||
var gook3 []byte
|
|
||||||
var gook4 []byte
|
|
||||||
var gook5 []byte
|
|
||||||
var gook0status bool
|
|
||||||
var gook1status bool
|
|
||||||
var gook2status bool
|
|
||||||
var gook3status bool
|
|
||||||
var gook4status bool
|
|
||||||
var gook5status bool
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook0 FROM gook WHERE id = $1", s.charID).Scan(&gook0)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook1 FROM gook WHERE id = $1", s.charID).Scan(&gook1)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook2 FROM gook WHERE id = $1", s.charID).Scan(&gook2)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook3 FROM gook WHERE id = $1", s.charID).Scan(&gook3)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook4 FROM gook WHERE id = $1", s.charID).Scan(&gook4)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook5 FROM gook WHERE id = $1", s.charID).Scan(&gook5)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook0status FROM gook WHERE id = $1", s.charID).Scan(&gook0status)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook1status FROM gook WHERE id = $1", s.charID).Scan(&gook1status)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook2status FROM gook WHERE id = $1", s.charID).Scan(&gook2status)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook3status FROM gook WHERE id = $1", s.charID).Scan(&gook3status)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook4status FROM gook WHERE id = $1", s.charID).Scan(&gook4status)
|
|
||||||
_ = s.server.db.QueryRow("SELECT gook5status FROM gook WHERE id = $1", s.charID).Scan(&gook5status)
|
|
||||||
if gook0status == true {
|
|
||||||
count++
|
|
||||||
tempresp.WriteBytes(gook0)
|
|
||||||
}
|
|
||||||
if gook1status == true {
|
|
||||||
count++
|
|
||||||
tempresp.WriteBytes(gook1)
|
|
||||||
}
|
|
||||||
if gook2status == true {
|
|
||||||
count++
|
|
||||||
tempresp.WriteBytes(gook2)
|
|
||||||
}
|
|
||||||
if gook3status == true {
|
|
||||||
count++
|
|
||||||
tempresp.WriteBytes(gook3)
|
|
||||||
}
|
|
||||||
if gook4status == true {
|
|
||||||
count++
|
|
||||||
tempresp.WriteBytes(gook4)
|
|
||||||
}
|
|
||||||
if gook5status == true {
|
|
||||||
count++
|
|
||||||
tempresp.WriteBytes(gook5)
|
|
||||||
}
|
|
||||||
if count == uint16(0) {
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
|
||||||
} else {
|
|
||||||
resp := byteframe.NewByteFrame()
|
|
||||||
resp.WriteUint16(count)
|
|
||||||
resp.WriteBytes(tempresp.Data())
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfUpdateGuacot)
|
pkt := p.(*mhfpacket.MsgMhfUpdateGuacot)
|
||||||
count := int(pkt.EntryCount)
|
for _, gook := range pkt.Gooks {
|
||||||
fmt.Printf("handleMsgMhfUpdateGuacot:%d\n", count)
|
if !gook.Exists {
|
||||||
if count == 0 {
|
s.server.db.Exec(fmt.Sprintf("UPDATE gook SET gook%d=NULL WHERE id=$1", gook.Index), s.charID)
|
||||||
_, err := s.server.db.Exec("INSERT INTO gook(id,gook0status,gook1status,gook2status,gook3status,gook4status,gook5status) VALUES($1,bool(false),bool(false),bool(false),bool(false),bool(false),bool(false))", s.charID)
|
} else {
|
||||||
if err != nil {
|
bf := byteframe.NewByteFrame()
|
||||||
fmt.Printf("INSERT INTO gook failure\n")
|
bf.WriteUint32(gook.Index)
|
||||||
}
|
bf.WriteUint16(gook.Type)
|
||||||
} else {
|
bf.WriteBytes(gook.Data)
|
||||||
for i := 0; i < int(pkt.EntryCount); i++ {
|
bf.WriteUint8(gook.NameLen)
|
||||||
gookindex := int(pkt.Entries[i].Unk0)
|
bf.WriteBytes(gook.Name)
|
||||||
buf := pkt.GuacotUpdateEntryToBytes(pkt.Entries[i])
|
s.server.db.Exec(fmt.Sprintf("UPDATE gook SET gook%d=$1 WHERE id=$2", gook.Index), bf.Data(), s.charID)
|
||||||
//fmt.Printf("gookindex:%d\n", gookindex)
|
|
||||||
switch gookindex {
|
|
||||||
case 0:
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook0 = $1 WHERE id = $2", buf, s.charID)
|
|
||||||
if pkt.Entries[i].Unk1 != uint16(0) {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook0status = $1 WHERE id = $2", bool(true), s.charID)
|
|
||||||
} else {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook0status = $1 WHERE id = $2", bool(false), s.charID)
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook1 = $1 WHERE id = $2", buf, s.charID)
|
|
||||||
if pkt.Entries[i].Unk1 != uint16(0) {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook1status = $1 WHERE id = $2", bool(true), s.charID)
|
|
||||||
} else {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook1status = $1 WHERE id = $2", bool(false), s.charID)
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook2 = $1 WHERE id = $2", buf, s.charID)
|
|
||||||
if pkt.Entries[i].Unk1 != uint16(0) {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook2status = $1 WHERE id = $2", bool(true), s.charID)
|
|
||||||
} else {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook2status = $1 WHERE id = $2", bool(false), s.charID)
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook3 = $1 WHERE id = $2", buf, s.charID)
|
|
||||||
if pkt.Entries[i].Unk1 != uint16(0) {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook3status = $1 WHERE id = $2", bool(true), s.charID)
|
|
||||||
} else {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook3status = $1 WHERE id = $2", bool(false), s.charID)
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook4 = $1 WHERE id = $2", buf, s.charID)
|
|
||||||
if pkt.Entries[i].Unk1 != uint16(0) {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook4status = $1 WHERE id = $2", bool(true), s.charID)
|
|
||||||
} else {
|
|
||||||
s.server.db.Exec("UPDATE gook SET gook4status = $1 WHERE id = $2", bool(false), s.charID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package channelserver
|
package channelserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"erupe-ce/common/byteframe"
|
|
||||||
"erupe-ce/common/bfutil"
|
"erupe-ce/common/bfutil"
|
||||||
|
"erupe-ce/common/byteframe"
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
"erupe-ce/server/channelserver/compression/deltacomp"
|
"erupe-ce/server/channelserver/compression/deltacomp"
|
||||||
"erupe-ce/server/channelserver/compression/nullcomp"
|
"erupe-ce/server/channelserver/compression/nullcomp"
|
||||||
@@ -61,6 +61,14 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
s.logger.Fatal("Failed to character weapon type in db", zap.Error(err))
|
s.logger.Fatal("Failed to character weapon type in db", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.myseries.houseTier = decompressedData[129900:129905] // 0x1FB6C + 5
|
||||||
|
s.myseries.houseData = decompressedData[130561:130756] // 0x1FE01 + 195
|
||||||
|
s.myseries.bookshelfData = decompressedData[139928:145504] // 0x22298 + 5576
|
||||||
|
// Gallery data also exists at 0x21578, is this the contest submission?
|
||||||
|
s.myseries.galleryData = decompressedData[140064:141812] // 0x22320 + 1748
|
||||||
|
s.myseries.toreData = decompressedData[130228:130468] // 0x1FCB4 + 240
|
||||||
|
s.myseries.gardenData = decompressedData[142424:142492] // 0x22C58 + 68
|
||||||
|
|
||||||
isMale := uint8(decompressedData[80]) // 0x50
|
isMale := uint8(decompressedData[80]) // 0x50
|
||||||
if isMale == 1 {
|
if isMale == 1 {
|
||||||
_, err = s.server.db.Exec("UPDATE characters SET is_female=true WHERE id=$1", s.charID)
|
_, err = s.server.db.Exec("UPDATE characters SET is_female=true WHERE id=$1", s.charID)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package channelserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
|
ps "erupe-ce/common/pascalstring"
|
||||||
|
"erupe-ce/common/stringsupport"
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -15,29 +17,176 @@ func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
type HouseData struct {
|
||||||
pkt := p.(*mhfpacket.MsgMhfEnumerateHouse)
|
CharID uint32 `db:"id"`
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
HRP uint16 `db:"hrp"`
|
||||||
|
GR uint16 `db:"gr"`
|
||||||
|
Name string `db:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
pkt := p.(*mhfpacket.MsgMhfEnumerateHouse)
|
||||||
|
bf := byteframe.NewByteFrame()
|
||||||
|
var houses []HouseData
|
||||||
|
switch pkt.Method {
|
||||||
|
case 1:
|
||||||
|
var friendsList string
|
||||||
|
s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&friendsList)
|
||||||
|
cids := stringsupport.CSVElems(friendsList)
|
||||||
|
for _, cid := range cids {
|
||||||
|
house := HouseData{}
|
||||||
|
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE id=$1", cid)
|
||||||
|
err := row.StructScan(&house)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
houses = append(houses, house)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
guildMembers, err := GetGuildMembers(s, guild.ID, false)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for _, member := range guildMembers {
|
||||||
|
house := HouseData{}
|
||||||
|
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE id=$1", member.CharID)
|
||||||
|
err := row.StructScan(&house)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
houses = append(houses, house)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
house := HouseData{}
|
||||||
|
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE name=$1", pkt.Name)
|
||||||
|
err := row.StructScan(&house)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
houses = append(houses, house)
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
house := HouseData{}
|
||||||
|
row := s.server.db.QueryRowx("SELECT id, hrp, gr, name FROM characters WHERE id=$1", pkt.CharID)
|
||||||
|
err := row.StructScan(&house)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
} else {
|
||||||
|
houses = append(houses, house)
|
||||||
|
}
|
||||||
|
case 5: // Recent visitors
|
||||||
|
break
|
||||||
|
}
|
||||||
|
var exists int
|
||||||
|
for _, house := range houses {
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session.charID == house.CharID {
|
||||||
|
exists++
|
||||||
|
bf.WriteUint32(house.CharID)
|
||||||
|
bf.WriteUint8(session.myseries.state)
|
||||||
|
if len(session.myseries.password) > 0 {
|
||||||
|
bf.WriteUint8(3)
|
||||||
|
} else {
|
||||||
|
bf.WriteUint8(0)
|
||||||
|
}
|
||||||
|
bf.WriteUint16(house.HRP)
|
||||||
|
bf.WriteUint16(house.GR)
|
||||||
|
ps.Uint8(bf, house.Name, true)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp := byteframe.NewByteFrame()
|
||||||
|
resp.WriteUint16(uint16(exists))
|
||||||
|
resp.WriteBytes(bf.Data())
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
pkt := p.(*mhfpacket.MsgMhfUpdateHouse)
|
||||||
|
// 01 = closed
|
||||||
|
// 02 = open anyone
|
||||||
|
// 03 = open friends
|
||||||
|
// 04 = open guild
|
||||||
|
// 05 = open friends+guild
|
||||||
|
s.myseries.state = pkt.State
|
||||||
|
s.myseries.password = pkt.Password
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfLoadHouse)
|
pkt := p.(*mhfpacket.MsgMhfLoadHouse)
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
var data []byte
|
if pkt.Destination != 9 && len(pkt.Password) > 0 && pkt.CheckPass {
|
||||||
err := s.server.db.QueryRow("SELECT house FROM characters WHERE id=$1", s.charID).Scan(&data)
|
for _, session := range s.server.sessions {
|
||||||
|
if session.charID == pkt.CharID && pkt.Password != session.myseries.password {
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var furniture []byte
|
||||||
|
err := s.server.db.QueryRow("SELECT house FROM characters WHERE id=$1", pkt.CharID).Scan(&furniture)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if data == nil {
|
if furniture == nil {
|
||||||
data = make([]byte, 20)
|
furniture = make([]byte, 20)
|
||||||
}
|
}
|
||||||
if pkt.CharID != s.charID {
|
|
||||||
bf.WriteBytes(make([]byte, 219))
|
switch pkt.Destination {
|
||||||
|
case 3: // Others house
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session.charID == pkt.CharID {
|
||||||
|
bf.WriteBytes(session.myseries.houseTier)
|
||||||
|
bf.WriteBytes(session.myseries.houseData)
|
||||||
|
bf.WriteBytes(make([]byte, 19)) // Padding?
|
||||||
|
bf.WriteBytes(furniture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 4: // Bookshelf
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session.charID == pkt.CharID {
|
||||||
|
bf.WriteBytes(session.myseries.bookshelfData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 5: // Gallery
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session.charID == pkt.CharID {
|
||||||
|
bf.WriteBytes(session.myseries.galleryData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 8: // Tore
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session.charID == pkt.CharID {
|
||||||
|
bf.WriteBytes(session.myseries.toreData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 9: // Own house
|
||||||
|
bf.WriteBytes(furniture)
|
||||||
|
case 10: // Garden
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if session.charID == pkt.CharID {
|
||||||
|
bf.WriteBytes(session.myseries.gardenData)
|
||||||
|
c, d := getGookData(s, pkt.CharID)
|
||||||
|
bf.WriteUint16(c)
|
||||||
|
bf.WriteUint16(0)
|
||||||
|
bf.WriteBytes(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(bf.Data()) == 0 {
|
||||||
|
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
} else {
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
bf.WriteBytes(data)
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||||
@@ -145,14 +294,18 @@ func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfEnumerateTitle)
|
pkt := p.(*mhfpacket.MsgMhfEnumerateTitle)
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
titleCount := 114 // all titles unlocked
|
if pkt.CharID == s.charID {
|
||||||
bf.WriteUint16(uint16(titleCount)) // title count
|
titleCount := 114 // all titles unlocked
|
||||||
bf.WriteUint16(0) // unk
|
bf.WriteUint16(uint16(titleCount)) // title count
|
||||||
for i := 0; i < titleCount; i++ {
|
bf.WriteUint16(0) // unk
|
||||||
bf.WriteUint16(uint16(i))
|
for i := 0; i < titleCount; i++ {
|
||||||
bf.WriteUint16(0) // unk
|
bf.WriteUint16(uint16(i))
|
||||||
bf.WriteUint32(0) // timestamp acquired
|
bf.WriteUint16(0) // unk
|
||||||
bf.WriteUint32(0) // timestamp updated
|
bf.WriteUint32(0) // timestamp acquired
|
||||||
|
bf.WriteUint32(0) // timestamp updated
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bf.WriteUint16(0)
|
||||||
}
|
}
|
||||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package channelserver
|
package channelserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
)
|
)
|
||||||
@@ -10,129 +9,7 @@ func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysOperateRegister)
|
pkt := p.(*mhfpacket.MsgSysOperateRegister)
|
||||||
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
||||||
s.server.raviente.Lock()
|
s.server.raviente.Lock()
|
||||||
switch pkt.RegisterID {
|
if pkt.SemaphoreID == s.server.raviente.state.semaphoreID {
|
||||||
case 786461:
|
|
||||||
resp := byteframe.NewByteFrame()
|
|
||||||
size := 6
|
|
||||||
for i := 0; i < len(bf.Data())-1; i += size {
|
|
||||||
op := bf.ReadUint8()
|
|
||||||
dest := bf.ReadUint8()
|
|
||||||
data := bf.ReadUint32()
|
|
||||||
resp.WriteUint8(1)
|
|
||||||
resp.WriteUint8(dest)
|
|
||||||
switch dest {
|
|
||||||
case 0:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
s.server.raviente.register.nextTime = data
|
|
||||||
case 1:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
s.server.raviente.register.startTime = data
|
|
||||||
case 2:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
s.server.raviente.register.killedTime = data
|
|
||||||
case 3:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
s.server.raviente.register.postTime = data
|
|
||||||
case 4:
|
|
||||||
ref := &s.server.raviente.register.register[0]
|
|
||||||
switch op {
|
|
||||||
case 2:
|
|
||||||
resp.WriteUint32(*ref)
|
|
||||||
resp.WriteUint32(*ref + uint32(data))
|
|
||||||
*ref += data
|
|
||||||
case 13:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
*ref = data
|
|
||||||
case 14:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
}
|
|
||||||
case 5:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
s.server.raviente.register.carveQuest = data
|
|
||||||
case 6:
|
|
||||||
ref := &s.server.raviente.register.register[1]
|
|
||||||
switch op {
|
|
||||||
case 2:
|
|
||||||
resp.WriteUint32(*ref)
|
|
||||||
resp.WriteUint32(*ref + uint32(data))
|
|
||||||
*ref += data
|
|
||||||
case 13:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
*ref = data
|
|
||||||
case 14:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
}
|
|
||||||
case 7:
|
|
||||||
ref := &s.server.raviente.register.register[2]
|
|
||||||
switch op {
|
|
||||||
case 2:
|
|
||||||
resp.WriteUint32(*ref)
|
|
||||||
resp.WriteUint32(*ref + uint32(data))
|
|
||||||
*ref += data
|
|
||||||
case 13:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
*ref = data
|
|
||||||
case 14:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
}
|
|
||||||
case 8:
|
|
||||||
ref := &s.server.raviente.register.register[3]
|
|
||||||
switch op {
|
|
||||||
case 2:
|
|
||||||
resp.WriteUint32(*ref)
|
|
||||||
resp.WriteUint32(*ref + uint32(data))
|
|
||||||
*ref += data
|
|
||||||
case 13:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
*ref = data
|
|
||||||
case 14:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
}
|
|
||||||
case 9:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
s.server.raviente.register.maxPlayers = data
|
|
||||||
case 10:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
s.server.raviente.register.ravienteType = data
|
|
||||||
case 11:
|
|
||||||
ref := &s.server.raviente.register.register[4]
|
|
||||||
switch op {
|
|
||||||
case 2:
|
|
||||||
resp.WriteUint32(*ref)
|
|
||||||
resp.WriteUint32(*ref + uint32(data))
|
|
||||||
*ref += data
|
|
||||||
case 13:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
*ref = data
|
|
||||||
case 14:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(data)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
resp.WriteUint32(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resp.WriteUint8(0)
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
|
||||||
|
|
||||||
case 917533:
|
|
||||||
resp := byteframe.NewByteFrame()
|
resp := byteframe.NewByteFrame()
|
||||||
size := 6
|
size := 6
|
||||||
for i := 0; i < len(bf.Data())-1; i += size {
|
for i := 0; i < len(bf.Data())-1; i += size {
|
||||||
@@ -152,12 +29,12 @@ func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
} else if dest == 17 { // Berserk poison tracker
|
} else if dest == 17 { // Berserk poison tracker
|
||||||
if damageMultiplier == 1 {
|
if damageMultiplier == 1 {
|
||||||
resp.WriteUint32(*ref + data)
|
resp.WriteUint32(*ref + data)
|
||||||
|
*ref += data
|
||||||
} else {
|
} else {
|
||||||
resp.WriteUint32(*ref + data)
|
resp.WriteUint32(*ref + data)
|
||||||
*ref += data
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resp.WriteUint32(*ref + data * damageMultiplier)
|
resp.WriteUint32(*ref + data*damageMultiplier)
|
||||||
*ref += data * damageMultiplier
|
*ref += data * damageMultiplier
|
||||||
}
|
}
|
||||||
case 13:
|
case 13:
|
||||||
@@ -170,8 +47,7 @@ func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
resp.WriteUint8(0)
|
resp.WriteUint8(0)
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
|
} else if pkt.SemaphoreID == s.server.raviente.support.semaphoreID {
|
||||||
case 851997:
|
|
||||||
resp := byteframe.NewByteFrame()
|
resp := byteframe.NewByteFrame()
|
||||||
size := 6
|
size := 6
|
||||||
for i := 0; i < len(bf.Data())-1; i += size {
|
for i := 0; i < len(bf.Data())-1; i += size {
|
||||||
@@ -196,6 +72,126 @@ func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
resp.WriteUint8(0)
|
resp.WriteUint8(0)
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
|
} else if pkt.SemaphoreID == s.server.raviente.register.semaphoreID {
|
||||||
|
resp := byteframe.NewByteFrame()
|
||||||
|
size := 6
|
||||||
|
for i := 0; i < len(bf.Data())-1; i += size {
|
||||||
|
op := bf.ReadUint8()
|
||||||
|
dest := bf.ReadUint8()
|
||||||
|
data := bf.ReadUint32()
|
||||||
|
resp.WriteUint8(1)
|
||||||
|
resp.WriteUint8(dest)
|
||||||
|
switch dest {
|
||||||
|
case 0:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
s.server.raviente.register.nextTime = data
|
||||||
|
case 1:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
s.server.raviente.register.startTime = data
|
||||||
|
case 2:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
s.server.raviente.register.killedTime = data
|
||||||
|
case 3:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
s.server.raviente.register.postTime = data
|
||||||
|
case 4:
|
||||||
|
ref := &s.server.raviente.register.register[0]
|
||||||
|
switch op {
|
||||||
|
case 2:
|
||||||
|
resp.WriteUint32(*ref)
|
||||||
|
resp.WriteUint32(*ref + uint32(data))
|
||||||
|
*ref += data
|
||||||
|
case 13:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
*ref = data
|
||||||
|
case 14:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
s.server.raviente.register.carveQuest = data
|
||||||
|
case 6:
|
||||||
|
ref := &s.server.raviente.register.register[1]
|
||||||
|
switch op {
|
||||||
|
case 2:
|
||||||
|
resp.WriteUint32(*ref)
|
||||||
|
resp.WriteUint32(*ref + uint32(data))
|
||||||
|
*ref += data
|
||||||
|
case 13:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
*ref = data
|
||||||
|
case 14:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
ref := &s.server.raviente.register.register[2]
|
||||||
|
switch op {
|
||||||
|
case 2:
|
||||||
|
resp.WriteUint32(*ref)
|
||||||
|
resp.WriteUint32(*ref + uint32(data))
|
||||||
|
*ref += data
|
||||||
|
case 13:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
*ref = data
|
||||||
|
case 14:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
ref := &s.server.raviente.register.register[3]
|
||||||
|
switch op {
|
||||||
|
case 2:
|
||||||
|
resp.WriteUint32(*ref)
|
||||||
|
resp.WriteUint32(*ref + uint32(data))
|
||||||
|
*ref += data
|
||||||
|
case 13:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
*ref = data
|
||||||
|
case 14:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
}
|
||||||
|
case 9:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
s.server.raviente.register.maxPlayers = data
|
||||||
|
case 10:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
s.server.raviente.register.ravienteType = data
|
||||||
|
case 11:
|
||||||
|
ref := &s.server.raviente.register.register[4]
|
||||||
|
switch op {
|
||||||
|
case 2:
|
||||||
|
resp.WriteUint32(*ref)
|
||||||
|
resp.WriteUint32(*ref + uint32(data))
|
||||||
|
*ref += data
|
||||||
|
case 13:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
*ref = data
|
||||||
|
case 14:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(data)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
resp.WriteUint32(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp.WriteUint8(0)
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
}
|
}
|
||||||
s.notifyall()
|
s.notifyall()
|
||||||
s.server.raviente.Unlock()
|
s.server.raviente.Unlock()
|
||||||
@@ -205,74 +201,66 @@ func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysLoadRegister)
|
pkt := p.(*mhfpacket.MsgSysLoadRegister)
|
||||||
r := pkt.Unk1
|
r := pkt.Unk1
|
||||||
switch r {
|
switch r {
|
||||||
case 12:
|
case 12:
|
||||||
if pkt.RegisterID == 983077 {
|
resp := byteframe.NewByteFrame()
|
||||||
data, _ := hex.DecodeString("000C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
resp.WriteUint8(0)
|
||||||
doAckBufFail(s, pkt.AckHandle, data)
|
resp.WriteUint8(12)
|
||||||
} else if pkt.RegisterID == 983069 {
|
resp.WriteUint32(s.server.raviente.register.nextTime)
|
||||||
data, _ := hex.DecodeString("000C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
resp.WriteUint32(s.server.raviente.register.startTime)
|
||||||
doAckBufFail(s, pkt.AckHandle, data)
|
resp.WriteUint32(s.server.raviente.register.killedTime)
|
||||||
}
|
resp.WriteUint32(s.server.raviente.register.postTime)
|
||||||
resp := byteframe.NewByteFrame()
|
resp.WriteUint32(s.server.raviente.register.register[0])
|
||||||
resp.WriteUint8(0)
|
resp.WriteUint32(s.server.raviente.register.carveQuest)
|
||||||
resp.WriteUint8(12)
|
resp.WriteUint32(s.server.raviente.register.register[1])
|
||||||
resp.WriteUint32(s.server.raviente.register.nextTime)
|
resp.WriteUint32(s.server.raviente.register.register[2])
|
||||||
resp.WriteUint32(s.server.raviente.register.startTime)
|
resp.WriteUint32(s.server.raviente.register.register[3])
|
||||||
resp.WriteUint32(s.server.raviente.register.killedTime)
|
resp.WriteUint32(s.server.raviente.register.maxPlayers)
|
||||||
resp.WriteUint32(s.server.raviente.register.postTime)
|
resp.WriteUint32(s.server.raviente.register.ravienteType)
|
||||||
resp.WriteUint32(s.server.raviente.register.register[0])
|
resp.WriteUint32(s.server.raviente.register.register[4])
|
||||||
resp.WriteUint32(s.server.raviente.register.carveQuest)
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
resp.WriteUint32(s.server.raviente.register.register[1])
|
case 29:
|
||||||
resp.WriteUint32(s.server.raviente.register.register[2])
|
resp := byteframe.NewByteFrame()
|
||||||
resp.WriteUint32(s.server.raviente.register.register[3])
|
resp.WriteUint8(0)
|
||||||
resp.WriteUint32(s.server.raviente.register.maxPlayers)
|
resp.WriteUint8(29)
|
||||||
resp.WriteUint32(s.server.raviente.register.ravienteType)
|
for _, v := range s.server.raviente.state.stateData {
|
||||||
resp.WriteUint32(s.server.raviente.register.register[4])
|
resp.WriteUint32(v)
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
}
|
||||||
case 29:
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
resp := byteframe.NewByteFrame()
|
case 25:
|
||||||
resp.WriteUint8(0)
|
resp := byteframe.NewByteFrame()
|
||||||
resp.WriteUint8(29)
|
resp.WriteUint8(0)
|
||||||
for _, v := range s.server.raviente.state.stateData {
|
resp.WriteUint8(25)
|
||||||
resp.WriteUint32(v)
|
for _, v := range s.server.raviente.support.supportData {
|
||||||
}
|
resp.WriteUint32(v)
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
}
|
||||||
case 25:
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
resp := byteframe.NewByteFrame()
|
|
||||||
resp.WriteUint8(0)
|
|
||||||
resp.WriteUint8(25)
|
|
||||||
for _, v := range s.server.raviente.support.supportData {
|
|
||||||
resp.WriteUint32(v)
|
|
||||||
}
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unused
|
|
||||||
func (s *Session) notifyplayer() {
|
|
||||||
s.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0E, 0x00, 0x1D})
|
|
||||||
s.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0D, 0x00, 0x1D})
|
|
||||||
s.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0C, 0x00, 0x1D})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Session) notifyall() {
|
func (s *Session) notifyall() {
|
||||||
|
var temp mhfpacket.MHFPacket
|
||||||
|
raviNotif := byteframe.NewByteFrame()
|
||||||
|
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: s.server.raviente.support.semaphoreID}
|
||||||
|
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(raviNotif, s.clientContext)
|
||||||
|
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: s.server.raviente.state.semaphoreID}
|
||||||
|
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(raviNotif, s.clientContext)
|
||||||
|
temp = &mhfpacket.MsgSysNotifyRegister{RegisterID: s.server.raviente.register.semaphoreID}
|
||||||
|
raviNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(raviNotif, s.clientContext)
|
||||||
|
raviNotif.WriteUint16(0x0010) // End it.
|
||||||
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
||||||
for session := range s.server.semaphore["hs_l0u3B51J9k3"].clients {
|
for session := range s.server.semaphore["hs_l0u3B51J9k3"].clients {
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0C, 0x00, 0x1D})
|
session.QueueSend(raviNotif.Data())
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0D, 0x00, 0x1D})
|
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0E, 0x00, 0x1D})
|
|
||||||
}
|
}
|
||||||
} else if _, exists := s.server.semaphore["hs_l0u3B5129k3"]; exists {
|
} else if _, exists := s.server.semaphore["hs_l0u3B5129k3"]; exists {
|
||||||
for session := range s.server.semaphore["hs_l0u3B5129k3"].clients {
|
for session := range s.server.semaphore["hs_l0u3B5129k3"].clients {
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0C, 0x00, 0x1D})
|
session.QueueSend(raviNotif.Data())
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0D, 0x00, 0x1D})
|
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0E, 0x00, 0x1D})
|
|
||||||
}
|
}
|
||||||
} else if _, exists := s.server.semaphore["hs_l0u3B512Ak3"]; exists {
|
} else if _, exists := s.server.semaphore["hs_l0u3B512Ak3"]; exists {
|
||||||
for session := range s.server.semaphore["hs_l0u3B512Ak3"].clients {
|
for session := range s.server.semaphore["hs_l0u3B512Ak3"].clients {
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0C, 0x00, 0x1D})
|
session.QueueSend(raviNotif.Data())
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0D, 0x00, 0x1D})
|
|
||||||
session.QueueSendNonBlocking([]byte{0x00, 0x3F, 0x00, 0x0E, 0x00, 0x1D})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,27 +276,28 @@ func checkRaviSemaphore(s *Session) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func releaseRaviSemaphore(s *Session) {
|
//func releaseRaviSemaphore(s *Session) {
|
||||||
s.server.raviente.Lock()
|
// s.server.raviente.Lock()
|
||||||
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
// if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
||||||
if len(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots) == 0 {
|
// if len(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots) == 0 {
|
||||||
resetRavi(s)
|
// resetRavi(s)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if _, exists := s.server.semaphore["hs_l0u3B5129k3"]; exists {
|
// if _, exists := s.server.semaphore["hs_l0u3B5129k3"]; exists {
|
||||||
if len(s.server.semaphore["hs_l0u3B5129k3"].reservedClientSlots) == 0 {
|
// if len(s.server.semaphore["hs_l0u3B5129k3"].reservedClientSlots) == 0 {
|
||||||
resetRavi(s)
|
// resetRavi(s)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if _, exists := s.server.semaphore["hs_l0u3B512Ak3"]; exists {
|
// if _, exists := s.server.semaphore["hs_l0u3B512Ak3"]; exists {
|
||||||
if len(s.server.semaphore["hs_l0u3B512Ak3"].reservedClientSlots) == 0 {
|
// if len(s.server.semaphore["hs_l0u3B512Ak3"].reservedClientSlots) == 0 {
|
||||||
resetRavi(s)
|
// resetRavi(s)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
s.server.raviente.Unlock()
|
// s.server.raviente.Unlock()
|
||||||
}
|
//}
|
||||||
|
|
||||||
func resetRavi(s *Session) {
|
func resetRavi(s *Session) {
|
||||||
|
s.server.raviente.Lock()
|
||||||
s.server.raviente.register.nextTime = 0
|
s.server.raviente.register.nextTime = 0
|
||||||
s.server.raviente.register.startTime = 0
|
s.server.raviente.register.startTime = 0
|
||||||
s.server.raviente.register.killedTime = 0
|
s.server.raviente.register.killedTime = 0
|
||||||
@@ -320,6 +309,7 @@ func resetRavi(s *Session) {
|
|||||||
s.server.raviente.register.register = []uint32{0, 0, 0, 0, 0}
|
s.server.raviente.register.register = []uint32{0, 0, 0, 0, 0}
|
||||||
s.server.raviente.state.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}
|
s.server.raviente.state.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}
|
||||||
s.server.raviente.support.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}
|
s.server.raviente.support.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}
|
||||||
|
s.server.raviente.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unused
|
// Unused
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package channelserver
|
package channelserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"erupe-ce/common/byteframe"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go.uber.org/zap"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
@@ -10,11 +12,13 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
releaseRaviSemaphore(s)
|
|
||||||
s.server.semaphoreLock.Unlock()
|
s.server.semaphoreLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,54 +27,50 @@ func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d})
|
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
delete(s.server.semaphore, id)
|
||||||
|
s.server.semaphoreLock.Lock()
|
||||||
|
if strings.HasPrefix(id, "hs_l0u3B51") {
|
||||||
|
releaseRaviSemaphore(s, sema)
|
||||||
|
}
|
||||||
|
s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.server.semaphoreLock.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func releaseRaviSemaphore(s *Session, sema *Semaphore) {
|
||||||
|
if !strings.HasSuffix(sema.id_semaphore, "5") {
|
||||||
|
delete(sema.reservedClientSlots, s.charID)
|
||||||
|
delete(sema.clients, s)
|
||||||
|
}
|
||||||
|
if len(sema.reservedClientSlots) == 0 && len(sema.clients) == 0 {
|
||||||
|
s.logger.Debug("Raviente semaphore is empty, resetting")
|
||||||
|
resetRavi(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
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 {
|
||||||
|
destructEmptySemaphores(s)
|
||||||
s.server.semaphoreLock.Lock()
|
s.server.semaphoreLock.Lock()
|
||||||
for id := range s.server.semaphore {
|
for id, sema := range s.server.semaphore {
|
||||||
switch sem {
|
if sema.id == sem {
|
||||||
case 917533:
|
if strings.HasPrefix(id, "hs_l0u3B51") {
|
||||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k3" {
|
releaseRaviSemaphore(s, sema)
|
||||||
delete(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots, s.charID)
|
s.server.semaphoreLock.Unlock()
|
||||||
delete(s.server.semaphore["hs_l0u3B51J9k3"].clients, s)
|
return
|
||||||
} 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:
|
|
||||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k4" {
|
|
||||||
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:
|
|
||||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k5" {
|
|
||||||
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:
|
|
||||||
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" &&
|
|
||||||
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()
|
||||||
|
delete(s.server.semaphore, id)
|
||||||
|
s.logger.Debug("Destructed semaphore", zap.String("sema.id_semaphore", id))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.server.semaphoreLock.Unlock()
|
s.server.semaphoreLock.Unlock()
|
||||||
@@ -81,15 +81,22 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgSysCreateAcquireSemaphore)
|
pkt := p.(*mhfpacket.MsgSysCreateAcquireSemaphore)
|
||||||
SemaphoreID := pkt.SemaphoreID
|
SemaphoreID := pkt.SemaphoreID
|
||||||
|
|
||||||
newSemaphore, gotNewStage := s.server.semaphore[SemaphoreID]
|
newSemaphore, exists := s.server.semaphore[SemaphoreID]
|
||||||
|
|
||||||
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 !exists {
|
||||||
s.server.semaphoreLock.Lock()
|
s.server.semaphoreLock.Lock()
|
||||||
if strings.HasPrefix(SemaphoreID, "hs_l0u3B51") {
|
if strings.HasPrefix(SemaphoreID, "hs_l0u3B51") {
|
||||||
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 32)
|
s.server.semaphore[SemaphoreID] = NewSemaphore(s.server, SemaphoreID, 32)
|
||||||
|
if strings.HasSuffix(SemaphoreID, "3") {
|
||||||
|
s.server.raviente.state.semaphoreID = s.server.semaphore[SemaphoreID].id
|
||||||
|
} else if strings.HasSuffix(SemaphoreID, "4") {
|
||||||
|
s.server.raviente.support.semaphoreID = s.server.semaphore[SemaphoreID].id
|
||||||
|
} else if strings.HasSuffix(SemaphoreID, "5") {
|
||||||
|
s.server.raviente.register.semaphoreID = s.server.semaphore[SemaphoreID].id
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 1)
|
s.server.semaphore[SemaphoreID] = NewSemaphore(s.server, SemaphoreID, 1)
|
||||||
}
|
}
|
||||||
newSemaphore = s.server.semaphore[SemaphoreID]
|
newSemaphore = s.server.semaphore[SemaphoreID]
|
||||||
s.server.semaphoreLock.Unlock()
|
s.server.semaphoreLock.Unlock()
|
||||||
@@ -98,35 +105,18 @@ 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 {
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D})
|
bf := byteframe.NewByteFrame()
|
||||||
|
bf.WriteUint32(newSemaphore.id)
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
|
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
|
||||||
switch SemaphoreID {
|
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||||
case "hs_l0u3B51J9k3", "hs_l0u3B5129k3", "hs_l0u3B512Ak3":
|
newSemaphore.clients[s] = s.charID
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
s.Lock()
|
||||||
newSemaphore.clients[s] = s.charID
|
s.semaphore = newSemaphore
|
||||||
s.Lock()
|
s.Unlock()
|
||||||
s.semaphore = newSemaphore
|
bf := byteframe.NewByteFrame()
|
||||||
s.Unlock()
|
bf.WriteUint32(newSemaphore.id)
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0E, 0x00, 0x1D})
|
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
case "hs_l0u3B51J9k4", "hs_l0u3B5129k4", "hs_l0u3B512Ak4":
|
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
|
||||||
s.Lock()
|
|
||||||
s.semaphore = newSemaphore
|
|
||||||
s.Unlock()
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0D, 0x00, 0x1D})
|
|
||||||
case "hs_l0u3B51J9k5", "hs_l0u3B5129k5", "hs_l0u3B512Ak5":
|
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
|
||||||
s.Lock()
|
|
||||||
s.semaphore = newSemaphore
|
|
||||||
s.Unlock()
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0C, 0x00, 0x1D})
|
|
||||||
default:
|
|
||||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
|
||||||
s.Lock()
|
|
||||||
s.semaphore = newSemaphore
|
|
||||||
s.Unlock()
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x25})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
}
|
}
|
||||||
@@ -138,7 +128,6 @@ 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)
|
||||||
releaseRaviSemaphore(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeEmptyStages(s *Session) {
|
func destructEmptyStages(s *Session) {
|
||||||
s.server.Lock()
|
s.server.Lock()
|
||||||
defer s.server.Unlock()
|
defer s.server.Unlock()
|
||||||
for _, stage := range s.server.stages {
|
for _, stage := range s.server.stages {
|
||||||
@@ -108,75 +108,33 @@ 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()
|
||||||
removeEmptyStages(s)
|
destructEmptyStages(s)
|
||||||
|
destructEmptySemaphores(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,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)
|
||||||
@@ -198,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)
|
||||||
}
|
}
|
||||||
@@ -218,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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,8 +71,9 @@ type Server struct {
|
|||||||
userBinaryParts map[userBinaryPartID][]byte
|
userBinaryParts map[userBinaryPartID][]byte
|
||||||
|
|
||||||
// Semaphore
|
// Semaphore
|
||||||
semaphoreLock sync.RWMutex
|
semaphoreLock sync.RWMutex
|
||||||
semaphore map[string]*Semaphore
|
semaphore map[string]*Semaphore
|
||||||
|
semaphoreIndex uint32
|
||||||
|
|
||||||
// Discord chat integration
|
// Discord chat integration
|
||||||
discordBot *discordbot.DiscordBot
|
discordBot *discordbot.DiscordBot
|
||||||
@@ -92,55 +93,58 @@ type Raviente struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RavienteRegister struct {
|
type RavienteRegister struct {
|
||||||
nextTime uint32
|
semaphoreID uint32
|
||||||
startTime uint32
|
nextTime uint32
|
||||||
postTime uint32
|
startTime uint32
|
||||||
killedTime uint32
|
postTime uint32
|
||||||
|
killedTime uint32
|
||||||
ravienteType uint32
|
ravienteType uint32
|
||||||
maxPlayers uint32
|
maxPlayers uint32
|
||||||
carveQuest uint32
|
carveQuest uint32
|
||||||
register []uint32
|
register []uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type RavienteState struct {
|
type RavienteState struct {
|
||||||
|
semaphoreID uint32
|
||||||
damageMultiplier uint32
|
damageMultiplier uint32
|
||||||
stateData []uint32
|
stateData []uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type RavienteSupport struct {
|
type RavienteSupport struct {
|
||||||
|
semaphoreID uint32
|
||||||
supportData []uint32
|
supportData []uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the Raviente variables for the server
|
// Set up the Raviente variables for the server
|
||||||
func NewRaviente() *Raviente {
|
func NewRaviente() *Raviente {
|
||||||
ravienteRegister := &RavienteRegister {
|
ravienteRegister := &RavienteRegister{
|
||||||
nextTime: 0,
|
nextTime: 0,
|
||||||
startTime: 0,
|
startTime: 0,
|
||||||
killedTime: 0,
|
killedTime: 0,
|
||||||
postTime: 0,
|
postTime: 0,
|
||||||
ravienteType: 0,
|
ravienteType: 0,
|
||||||
maxPlayers: 0,
|
maxPlayers: 0,
|
||||||
carveQuest: 0,
|
carveQuest: 0,
|
||||||
}
|
}
|
||||||
ravienteState := &RavienteState {
|
ravienteState := &RavienteState{
|
||||||
damageMultiplier: 1,
|
damageMultiplier: 1,
|
||||||
}
|
}
|
||||||
ravienteSupport := &RavienteSupport { }
|
ravienteSupport := &RavienteSupport{}
|
||||||
ravienteRegister.register = []uint32{0, 0, 0, 0, 0}
|
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}
|
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}
|
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 {
|
raviente := &Raviente{
|
||||||
register: ravienteRegister,
|
register: ravienteRegister,
|
||||||
state: ravienteState,
|
state: ravienteState,
|
||||||
support: ravienteSupport,
|
support: ravienteSupport,
|
||||||
}
|
}
|
||||||
return raviente
|
return raviente
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a new Server type.
|
// NewServer creates a new Server type.
|
||||||
func NewServer(config *Config) *Server {
|
func NewServer(config *Config) *Server {
|
||||||
s := &Server {
|
s := &Server{
|
||||||
ID: config.ID,
|
ID: config.ID,
|
||||||
logger: config.Logger,
|
logger: config.Logger,
|
||||||
db: config.DB,
|
db: config.DB,
|
||||||
@@ -151,6 +155,7 @@ func NewServer(config *Config) *Server {
|
|||||||
stages: make(map[string]*Stage),
|
stages: make(map[string]*Stage),
|
||||||
userBinaryParts: make(map[userBinaryPartID][]byte),
|
userBinaryParts: make(map[userBinaryPartID][]byte),
|
||||||
semaphore: make(map[string]*Semaphore),
|
semaphore: make(map[string]*Semaphore),
|
||||||
|
semaphoreIndex: 0,
|
||||||
discordBot: config.DiscordBot,
|
discordBot: config.DiscordBot,
|
||||||
name: config.Name,
|
name: config.Name,
|
||||||
enable: config.Enable,
|
enable: config.Enable,
|
||||||
@@ -277,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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,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 {
|
||||||
@@ -401,3 +406,8 @@ func (s *Server) FindStageObjectByChar(charID uint32) *StageObject {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) NextSemaphoreID() uint32 {
|
||||||
|
s.semaphoreIndex = s.semaphoreIndex + 1
|
||||||
|
return s.semaphoreIndex
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ type Semaphore struct {
|
|||||||
// Stage ID string
|
// Stage ID string
|
||||||
id_semaphore string
|
id_semaphore string
|
||||||
|
|
||||||
|
id uint32
|
||||||
|
|
||||||
// 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
|
||||||
@@ -26,21 +28,21 @@ type Semaphore struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewStage creates a new stage with intialized values.
|
// NewStage creates a new stage with intialized values.
|
||||||
func NewSemaphore(ID string, MaxPlayers uint16) *Semaphore {
|
func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore {
|
||||||
s := &Semaphore{
|
sema := &Semaphore{
|
||||||
id_semaphore: ID,
|
id_semaphore: ID,
|
||||||
|
id: s.NextSemaphoreID(),
|
||||||
clients: make(map[*Session]uint32),
|
clients: make(map[*Session]uint32),
|
||||||
reservedClientSlots: make(map[uint32]interface{}),
|
reservedClientSlots: make(map[uint32]interface{}),
|
||||||
maxPlayers: MaxPlayers,
|
maxPlayers: MaxPlayers,
|
||||||
}
|
}
|
||||||
return s
|
return sema
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) {
|
func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) {
|
||||||
// Broadcast the data.
|
// Broadcast the data.
|
||||||
for session := range s.clients {
|
for session := range s.clients {
|
||||||
|
|
||||||
|
|
||||||
// Make the header
|
// Make the header
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteUint16(uint16(pkt.Opcode()))
|
bf.WriteUint16(uint16(pkt.Opcode()))
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ type Session struct {
|
|||||||
sendPackets chan []byte
|
sendPackets chan []byte
|
||||||
clientContext *clientctx.ClientContext
|
clientContext *clientctx.ClientContext
|
||||||
|
|
||||||
|
myseries MySeries
|
||||||
stageID string
|
stageID string
|
||||||
stage *Stage
|
stage *Stage
|
||||||
reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet.
|
reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet.
|
||||||
@@ -54,6 +55,17 @@ type Session struct {
|
|||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MySeries struct {
|
||||||
|
houseTier []byte
|
||||||
|
houseData []byte
|
||||||
|
bookshelfData []byte
|
||||||
|
galleryData []byte
|
||||||
|
toreData []byte
|
||||||
|
gardenData []byte
|
||||||
|
state uint8
|
||||||
|
password string
|
||||||
|
}
|
||||||
|
|
||||||
// NewSession creates a new Session type.
|
// NewSession creates a new Session type.
|
||||||
func NewSession(server *Server, conn net.Conn) *Session {
|
func NewSession(server *Server, conn net.Conn) *Session {
|
||||||
s := &Session{
|
s := &Session{
|
||||||
@@ -239,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