mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 15:34:38 +01:00
objects v3
This commit is contained in:
11
patch-schema/dbuserbinaries.sql
Normal file
11
patch-schema/dbuserbinaries.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE user_binaries
|
||||||
|
(
|
||||||
|
id int PRIMARY KEY,
|
||||||
|
type1 bytea,
|
||||||
|
type2 bytea,
|
||||||
|
type3 bytea
|
||||||
|
);
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -183,6 +183,8 @@ func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
|
|
||||||
updateRights(s)
|
updateRights(s)
|
||||||
|
|
||||||
|
s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{CharID: s.charID}, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
OwnerCharID: newObj.ownerCharID,
|
OwnerCharID: newObj.ownerCharID,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, s.charID))
|
s.logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.id))
|
||||||
s.stage.BroadcastMHF(dupObjUpdate, s)
|
s.stage.BroadcastMHF(dupObjUpdate, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,9 +63,16 @@ 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)
|
pkt := p.(*mhfpacket.MsgSysSetObjectBinary)
|
||||||
for _, object := range s.stage.objects {
|
for _, session := range s.server.sessions {
|
||||||
if object.id == pkt.ObjID {
|
if session.charID == s.charID {
|
||||||
object.binary = pkt.RawDataPayload
|
s.server.userBinaryPartsLock.Lock()
|
||||||
|
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: 3}] = pkt.RawDataPayload
|
||||||
|
s.server.userBinaryPartsLock.Unlock()
|
||||||
|
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
CharID: s.charID,
|
||||||
|
BinaryType: 3,
|
||||||
|
}
|
||||||
|
s.server.BroadcastMHF(msg, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package channelserver
|
package channelserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
@@ -51,7 +52,7 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
|
|
||||||
// Save our new stage ID and pointer to the new stage itself.
|
// Save our new stage ID and pointer to the new stage itself.
|
||||||
s.Lock()
|
s.Lock()
|
||||||
s.stageID = string(stageID)
|
s.stageID = stageID
|
||||||
s.stage = s.server.stages[stageID]
|
s.stage = s.server.stages[stageID]
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
@@ -61,13 +62,41 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
// Confirm the stage entry.
|
// Confirm the stage entry.
|
||||||
doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
|
|
||||||
|
var temp mhfpacket.MHFPacket
|
||||||
|
newNotif := byteframe.NewByteFrame()
|
||||||
|
|
||||||
|
// Cast existing user data to new user
|
||||||
|
if !s.userEnteredStage {
|
||||||
|
s.userEnteredStage = true
|
||||||
|
|
||||||
|
for _, session := range s.server.sessions {
|
||||||
|
if s == session {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID}
|
||||||
|
newNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(newNotif, s.clientContext)
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
temp = &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
|
CharID: session.charID,
|
||||||
|
BinaryType: uint8(i + 1),
|
||||||
|
}
|
||||||
|
newNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
|
temp.Build(newNotif, s.clientContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if s.stage != nil { // avoids lock up when using bed for dream quests
|
if s.stage != nil { // avoids lock up when using bed for dream quests
|
||||||
// Notify the client to duplicate the existing objects.
|
// Notify the client to duplicate the existing objects.
|
||||||
s.logger.Info("Sending existing stage objects")
|
s.logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name))
|
||||||
clientDupObjNotif := byteframe.NewByteFrame()
|
|
||||||
s.stage.RLock()
|
s.stage.RLock()
|
||||||
|
var temp mhfpacket.MHFPacket
|
||||||
for _, obj := range s.stage.objects {
|
for _, obj := range s.stage.objects {
|
||||||
cur := &mhfpacket.MsgSysDuplicateObject{
|
if obj.ownerCharID == s.charID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
temp = &mhfpacket.MsgSysDuplicateObject{
|
||||||
ObjID: obj.id,
|
ObjID: obj.id,
|
||||||
X: obj.x,
|
X: obj.x,
|
||||||
Y: obj.y,
|
Y: obj.y,
|
||||||
@@ -75,14 +104,15 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
|||||||
Unk0: 0,
|
Unk0: 0,
|
||||||
OwnerCharID: obj.ownerCharID,
|
OwnerCharID: obj.ownerCharID,
|
||||||
}
|
}
|
||||||
clientDupObjNotif.WriteUint16(uint16(cur.Opcode()))
|
newNotif.WriteUint16(uint16(temp.Opcode()))
|
||||||
cur.Build(clientDupObjNotif, s.clientContext)
|
temp.Build(newNotif, s.clientContext)
|
||||||
}
|
}
|
||||||
s.stage.RUnlock()
|
s.stage.RUnlock()
|
||||||
clientDupObjNotif.WriteUint16(0x0010) // End it.
|
}
|
||||||
if len(clientDupObjNotif.Data()) > 2 {
|
|
||||||
s.QueueSend(clientDupObjNotif.Data())
|
newNotif.WriteUint16(0x0010) // End it.
|
||||||
}
|
if len(newNotif.Data()) > 2 {
|
||||||
|
s.QueueSend(newNotif.Data())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,68 +12,19 @@ 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()
|
||||||
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload
|
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload
|
||||||
s.server.userBinaryPartsLock.Unlock()
|
s.server.userBinaryPartsLock.Unlock()
|
||||||
|
|
||||||
// Insert user once all binary parts exist
|
err := s.server.db.QueryRow("SELECT type1 FROM user_binaries WHERE id=$1", s.charID)
|
||||||
if !s.binariesDone {
|
if err != nil {
|
||||||
for i := 0; i < 3; i++ {
|
s.server.db.Exec("INSERT INTO user_binaries (id) VALUES ($1)", s.charID)
|
||||||
_, exists := s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: uint8(i + 1)}]
|
|
||||||
if !exists {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.binariesDone = true
|
|
||||||
broadcastNewUser(s)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.server.db.Exec(fmt.Sprintf("UPDATE user_binaries SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.charID)
|
||||||
|
|
||||||
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
||||||
CharID: s.charID,
|
CharID: s.charID,
|
||||||
BinaryType: pkt.BinaryType,
|
BinaryType: pkt.BinaryType,
|
||||||
@@ -91,25 +42,18 @@ func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
data, ok := s.server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}]
|
data, ok := s.server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}]
|
||||||
resp := byteframe.NewByteFrame()
|
resp := byteframe.NewByteFrame()
|
||||||
|
|
||||||
// If we can't get the real data, use a placeholder.
|
// If we can't get the real data, try to get it from the database.
|
||||||
if !ok {
|
if !ok {
|
||||||
if pkt.BinaryType == 1 {
|
var data []byte
|
||||||
// Stub name response with character ID
|
rows, _ := s.server.db.Queryx(fmt.Sprintf("SELECT type%d FROM user_binaries WHERE id=$1", pkt.BinaryType), pkt.CharID)
|
||||||
resp.WriteBytes([]byte(fmt.Sprintf("CID%d", s.charID)))
|
for rows.Next() {
|
||||||
resp.WriteUint8(0) // NULL terminator.
|
rows.Scan(&data)
|
||||||
} else if pkt.BinaryType == 2 {
|
|
||||||
data, err := base64.StdEncoding.DecodeString("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBn8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAwAAAAAAAAAAAAAABAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
resp.WriteBytes(data)
|
|
||||||
} else if pkt.BinaryType == 3 {
|
|
||||||
data, err := base64.StdEncoding.DecodeString("AQAAA2ea5P8ATgEA/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBn8AAAAAAAAAAAABAKAMAAAAAAAAAAAAACgAAAAAAAAAAAABAsQOAAAAAAAAAAABA6UMAAAAAAAAAAABBKAMAAAAAAAAAAABBToNAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
resp.WriteBytes(data)
|
resp.WriteBytes(data)
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
resp.WriteBytes(data)
|
resp.WriteBytes(data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,7 +279,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 || !session.binariesDone {
|
if session == ignoredSession {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ 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 _, session := range c.sessions {
|
for _, session := range c.sessions {
|
||||||
if session == ignoredSession || !session.binariesDone {
|
if session == ignoredSession {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ type Session struct {
|
|||||||
sendPackets chan []byte
|
sendPackets chan []byte
|
||||||
clientContext *clientctx.ClientContext
|
clientContext *clientctx.ClientContext
|
||||||
|
|
||||||
|
userEnteredStage bool // If the user has entered a stage before
|
||||||
myseries MySeries
|
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.
|
||||||
stagePass string // Temporary storage
|
stagePass string // Temporary storage
|
||||||
binariesDone bool
|
|
||||||
charID uint32
|
charID uint32
|
||||||
logKey []byte
|
logKey []byte
|
||||||
sessionStart int64
|
sessionStart int64
|
||||||
@@ -79,9 +79,9 @@ func NewSession(server *Server, conn net.Conn) *Session {
|
|||||||
Encoding: japanese.ShiftJIS,
|
Encoding: japanese.ShiftJIS,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
binariesDone: false,
|
userEnteredStage: false,
|
||||||
sessionStart: Time_Current_Adjusted().Unix(),
|
sessionStart: Time_Current_Adjusted().Unix(),
|
||||||
stageMoveStack: stringstack.New(),
|
stageMoveStack: stringstack.New(),
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ type Object struct {
|
|||||||
id uint32
|
id uint32
|
||||||
ownerCharID uint32
|
ownerCharID uint32
|
||||||
x, y, z float32
|
x, y, z float32
|
||||||
binary []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
@@ -33,7 +32,7 @@ type Stage struct {
|
|||||||
|
|
||||||
// Objects
|
// Objects
|
||||||
objects map[uint32]*Object
|
objects map[uint32]*Object
|
||||||
objectIndex uint32
|
objectIndex uint8
|
||||||
|
|
||||||
// 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
|
||||||
@@ -71,7 +70,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 || !session.binariesDone {
|
if session == ignoredSession {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,5 +129,10 @@ func (s *Stage) GetName() string {
|
|||||||
|
|
||||||
func (s *Stage) NextObjectID() uint32 {
|
func (s *Stage) NextObjectID() uint32 {
|
||||||
s.objectIndex = s.objectIndex + 1
|
s.objectIndex = s.objectIndex + 1
|
||||||
return s.objectIndex
|
bf := byteframe.NewByteFrame()
|
||||||
|
bf.WriteUint8(0)
|
||||||
|
bf.WriteUint8(s.objectIndex)
|
||||||
|
bf.WriteUint16(0)
|
||||||
|
obj := uint32(bf.Data()[3]) | uint32(bf.Data()[2])<<8 | uint32(bf.Data()[1])<<16 | uint32(bf.Data()[0])<<24
|
||||||
|
return obj
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user