movement.go: added support for basic movement packets

you should be able to view other players and jump around together,
although while testing locally one of the clients would always trigger
the "Some irregularities have been found with your connection to the
server, so your game will be closed" speed check for some reason ???

really not sure, might just be my machine

chunking uhhh works ? kind of, not tested for more than a few seconds
before one of the clients disconnects
This commit is contained in:
unknown 2023-06-25 04:27:42 -05:00
parent f6ab7a9b5d
commit 8f00a0c492
7 changed files with 119 additions and 19 deletions

View File

@ -122,7 +122,7 @@ const (
) )
func (db *DBHandler) readPlayer(rows *sql.Rows) (*entity.Player, error) { func (db *DBHandler) readPlayer(rows *sql.Rows) (*entity.Player, error) {
plr := entity.Player{ActiveNanoSlotNum: -1} plr := entity.Player{ActiveNanoSlotNum: 0}
if err := rows.Scan( if err := rows.Scan(
&plr.PlayerID, &plr.AccountID, &plr.Slot, &plr.PCStyle.SzFirstName, &plr.PCStyle.SzLastName, &plr.PlayerID, &plr.AccountID, &plr.Slot, &plr.PCStyle.SzFirstName, &plr.PCStyle.SzLastName,

View File

@ -28,11 +28,16 @@ func (c *Chunk) RemoveEntity(entity Entity) {
// send packet to all peers in this chunk and kill each peer if error // send packet to all peers in this chunk and kill each peer if error
func (c *Chunk) SendPacket(typeID uint32, pkt ...interface{}) { func (c *Chunk) SendPacket(typeID uint32, pkt ...interface{}) {
c.SendPacketExclude(nil, typeID, pkt...)
}
func (c *Chunk) SendPacketExclude(exclude Entity, typeID uint32, pkt ...interface{}) {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
for entity := range c.Entities { for entity := range c.Entities {
if entity.GetKind() != ENTITY_KIND_PLAYER { // only send to players, and exclude the player that sent the packet
if entity.GetKind() != ENTITY_KIND_PLAYER || entity == exclude {
continue continue
} }

View File

@ -122,6 +122,6 @@ func (plr *Player) GetAppearanceData() protocol.SPCAppearanceData {
PCStyle: plr.PCStyle, PCStyle: plr.PCStyle,
IPCState: plr.IPCState, IPCState: plr.IPCState,
ItemEquip: plr.Equip, ItemEquip: plr.Equip,
Nano: protocol.SNano{}, //plr.Nanos[plr.ActiveNanoSlotNum], Nano: plr.Nanos[plr.ActiveNanoSlotNum],
} }
} }

View File

@ -23,9 +23,11 @@ func (server *ShardServer) getViewableChunks(pos entity.ChunkPosition) []*entity
return chunks return chunks
} }
func (server *ShardServer) sendPacketToViewableChunks(plr *entity.Player, typeID uint32, pkt ...interface{}) error { // sends a packet to all peers in the given chunks, excluding the given peer
for _, chunk := range server.getViewableChunks(plr.Chunk) { func (server *ShardServer) sendOthersPacket(plr *entity.Player, typeID uint32, pkt ...interface{}) error {
chunk.SendPacket(typeID, pkt...) chunks := server.getViewableChunks(plr.Chunk)
for _, chunk := range chunks {
chunk.SendPacketExclude(plr, typeID, pkt...)
} }
return nil return nil
@ -34,11 +36,17 @@ func (server *ShardServer) sendPacketToViewableChunks(plr *entity.Player, typeID
func (server *ShardServer) removeEntityFromChunks(chunks []*entity.Chunk, this entity.Entity) { func (server *ShardServer) removeEntityFromChunks(chunks []*entity.Chunk, this entity.Entity) {
for _, chunk := range chunks { for _, chunk := range chunks {
for e, _ := range chunk.Entities { for e, _ := range chunk.Entities {
if e == this {
continue
}
// notify other players we're leaving
if e.GetKind() == entity.ENTITY_KIND_PLAYER { if e.GetKind() == entity.ENTITY_KIND_PLAYER {
otherPlr := e.(*entity.Player) otherPlr := e.(*entity.Player)
this.DisappearFromViewOf(otherPlr.Peer) this.DisappearFromViewOf(otherPlr.Peer)
} }
// notify us they're leaving
if this.GetKind() == entity.ENTITY_KIND_PLAYER { if this.GetKind() == entity.ENTITY_KIND_PLAYER {
thisPlr := this.(*entity.Player) thisPlr := this.(*entity.Player)
e.DisappearFromViewOf(thisPlr.Peer) e.DisappearFromViewOf(thisPlr.Peer)
@ -50,11 +58,17 @@ func (server *ShardServer) removeEntityFromChunks(chunks []*entity.Chunk, this e
func (server *ShardServer) addEntityToChunks(chunks []*entity.Chunk, this entity.Entity) { func (server *ShardServer) addEntityToChunks(chunks []*entity.Chunk, this entity.Entity) {
for _, chunk := range chunks { for _, chunk := range chunks {
for e, _ := range chunk.Entities { for e, _ := range chunk.Entities {
if e == this {
continue
}
// notify other players we're entering
if e.GetKind() == entity.ENTITY_KIND_PLAYER { if e.GetKind() == entity.ENTITY_KIND_PLAYER {
otherPlr := e.(*entity.Player) otherPlr := e.(*entity.Player)
this.EnterIntoViewOf(otherPlr.Peer) this.EnterIntoViewOf(otherPlr.Peer)
} }
// notify us they're entering
if this.GetKind() == entity.ENTITY_KIND_PLAYER { if this.GetKind() == entity.ENTITY_KIND_PLAYER {
thisPlr := this.(*entity.Player) thisPlr := this.(*entity.Player)
e.EnterIntoViewOf(thisPlr.Peer) e.EnterIntoViewOf(thisPlr.Peer)
@ -64,6 +78,11 @@ func (server *ShardServer) addEntityToChunks(chunks []*entity.Chunk, this entity
} }
func (server *ShardServer) updateEntityChunk(e entity.Entity, from entity.ChunkPosition, to entity.ChunkPosition) { func (server *ShardServer) updateEntityChunk(e entity.Entity, from entity.ChunkPosition, to entity.ChunkPosition) {
// no change needed
if from == to {
return
}
oldViewables := server.getViewableChunks(from) oldViewables := server.getViewableChunks(from)
newViewables := server.getViewableChunks(to) newViewables := server.getViewableChunks(to)

View File

@ -59,7 +59,7 @@ func (server *ShardServer) RequestEnter(peer *protocol.CNPeer, pkt protocol.Pack
log.Printf("Player %d (AccountID %d) entered\n", resp.IID, loginData.AccountID) log.Printf("Player %d (AccountID %d) entered\n", resp.IID, loginData.AccountID)
server.updatePlayerPosition(peer, int(plr.X), int(plr.Y), int(plr.Z), int(plr.Angle)) server.updatePlayerPosition(plr, int(plr.X), int(plr.Y), int(plr.Z), int(plr.Angle))
return peer.Send(protocol.P_FE2CL_REP_PC_ENTER_SUCC, resp) return peer.Send(protocol.P_FE2CL_REP_PC_ENTER_SUCC, resp)
} }

View File

@ -1,25 +1,18 @@
package shard package shard
import ( import (
"time"
"github.com/CPunch/gopenfusion/core/entity" "github.com/CPunch/gopenfusion/core/entity"
"github.com/CPunch/gopenfusion/core/protocol" "github.com/CPunch/gopenfusion/core/protocol"
) )
func (server *ShardServer) updatePlayerPosition(peer *protocol.CNPeer, X, Y, Z, Angle int) error { func (server *ShardServer) updatePlayerPosition(plr *entity.Player, X, Y, Z, Angle int) error {
plr, err := server.getPlayer(peer)
if err != nil {
return err
}
newPos := entity.MakeChunkPosition(X, Y)
oldPos := plr.Chunk
plr.X = X plr.X = X
plr.Y = Y plr.Y = Y
plr.Z = Z plr.Z = Z
plr.Angle = Angle plr.Angle = Angle
if newPos != oldPos { server.updateEntityChunk(plr, plr.GetChunk(), entity.MakeChunkPosition(X, Y))
server.updateEntityChunk(plr, oldPos, newPos)
}
return nil return nil
} }
@ -27,5 +20,85 @@ func (server *ShardServer) playerMove(peer *protocol.CNPeer, pkt protocol.Packet
var move protocol.SP_CL2FE_REQ_PC_MOVE var move protocol.SP_CL2FE_REQ_PC_MOVE
pkt.Decode(&move) pkt.Decode(&move)
return server.updatePlayerPosition(peer, int(move.IX), int(move.IY), int(move.IZ), int(move.IAngle)) // sanity check
plr, err := server.getPlayer(peer)
if err != nil {
return err
}
// update chunking
if err := server.updatePlayerPosition(plr, int(move.IX), int(move.IY), int(move.IZ), int(move.IAngle)); err != nil {
return err
}
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_MOVE, protocol.SP_FE2CL_PC_MOVE{
ICliTime: uint64(time.Now().Unix()),
IX: move.IX,
IY: move.IY,
IZ: move.IZ,
FVX: move.FVX,
FVY: move.FVY,
FVZ: move.FVZ,
IAngle: move.IAngle,
CKeyValue: move.CKeyValue,
ISpeed: move.ISpeed,
IID: int32(plr.PlayerID),
ISvrTime: uint64(time.Now().Unix()),
})
}
func (server *ShardServer) playerStop(peer *protocol.CNPeer, pkt protocol.Packet) error {
var stop protocol.SP_CL2FE_REQ_PC_STOP
pkt.Decode(&stop)
// sanity check
plr, err := server.getPlayer(peer)
if err != nil {
return err
}
// update chunking
if err := server.updatePlayerPosition(plr, int(stop.IX), int(stop.IY), int(stop.IZ), plr.Angle); err != nil {
return err
}
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_STOP, protocol.SP_FE2CL_PC_STOP{
ICliTime: uint64(time.Now().Unix()),
IX: stop.IX,
IY: stop.IY,
IZ: stop.IZ,
IID: int32(plr.PlayerID),
ISvrTime: uint64(time.Now().Unix()),
})
}
func (server *ShardServer) playerJump(peer *protocol.CNPeer, pkt protocol.Packet) error {
var jump protocol.SP_CL2FE_REQ_PC_JUMP
pkt.Decode(&jump)
// sanity check
plr, err := server.getPlayer(peer)
if err != nil {
return err
}
// update chunking
if err := server.updatePlayerPosition(plr, int(jump.IX), int(jump.IY), int(jump.IZ), plr.Angle); err != nil {
return err
}
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_JUMP, protocol.SP_FE2CL_PC_JUMP{
ICliTime: uint64(time.Now().Unix()),
IX: jump.IX,
IY: jump.IY,
IZ: jump.IZ,
IVX: jump.IVX,
IVY: jump.IVY,
IVZ: jump.IVZ,
IAngle: jump.IAngle,
CKeyValue: jump.CKeyValue,
ISpeed: jump.ISpeed,
IID: int32(plr.PlayerID),
ISvrTime: uint64(time.Now().Unix()),
})
} }

View File

@ -50,6 +50,9 @@ func NewShardServer(dbHndlr *db.DBHandler, redisHndlr *redis.RedisHandler, port
server.packetHandlers = map[uint32]PacketHandler{ server.packetHandlers = map[uint32]PacketHandler{
protocol.P_CL2FE_REQ_PC_ENTER: server.RequestEnter, protocol.P_CL2FE_REQ_PC_ENTER: server.RequestEnter,
protocol.P_CL2FE_REQ_PC_LOADING_COMPLETE: server.LoadingComplete, protocol.P_CL2FE_REQ_PC_LOADING_COMPLETE: server.LoadingComplete,
protocol.P_CL2FE_REQ_PC_MOVE: server.playerMove,
protocol.P_CL2FE_REQ_PC_STOP: server.playerStop,
protocol.P_CL2FE_REQ_PC_JUMP: server.playerJump,
} }
redisHndlr.RegisterShard(redis.ShardMetadata{ redisHndlr.RegisterShard(redis.ShardMetadata{