objects v3

This commit is contained in:
wish
2022-08-02 04:37:19 +10:00
parent a020ad88d0
commit ab51588e9e
8 changed files with 92 additions and 94 deletions

View File

@@ -0,0 +1,11 @@
BEGIN;
CREATE TABLE user_binaries
(
id int PRIMARY KEY,
type1 bytea,
type2 bytea,
type3 bytea
);
END;

View File

@@ -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) {

View File

@@ -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)
} }
} }
} }

View File

@@ -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())
} }
} }

View File

@@ -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)
} }

View File

@@ -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()

View File

@@ -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
} }

View File

@@ -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
} }