From 8f00a0c4929271168aa325bedaa9e8362edeb637 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 25 Jun 2023 04:27:42 -0500 Subject: [PATCH] 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 --- core/db/players.go | 2 +- core/entity/chunk.go | 7 +++- core/entity/player.go | 2 +- shard/chunks.go | 25 +++++++++-- shard/join.go | 2 +- shard/movement.go | 97 +++++++++++++++++++++++++++++++++++++------ shard/shardServer.go | 3 ++ 7 files changed, 119 insertions(+), 19 deletions(-) diff --git a/core/db/players.go b/core/db/players.go index 6d88a24..0e799b1 100644 --- a/core/db/players.go +++ b/core/db/players.go @@ -122,7 +122,7 @@ const ( ) func (db *DBHandler) readPlayer(rows *sql.Rows) (*entity.Player, error) { - plr := entity.Player{ActiveNanoSlotNum: -1} + plr := entity.Player{ActiveNanoSlotNum: 0} if err := rows.Scan( &plr.PlayerID, &plr.AccountID, &plr.Slot, &plr.PCStyle.SzFirstName, &plr.PCStyle.SzLastName, diff --git a/core/entity/chunk.go b/core/entity/chunk.go index 5549494..d33eead 100644 --- a/core/entity/chunk.go +++ b/core/entity/chunk.go @@ -28,11 +28,16 @@ func (c *Chunk) RemoveEntity(entity Entity) { // send packet to all peers in this chunk and kill each peer if error 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() defer c.lock.Unlock() 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 } diff --git a/core/entity/player.go b/core/entity/player.go index 95bfbc7..c610ebb 100644 --- a/core/entity/player.go +++ b/core/entity/player.go @@ -122,6 +122,6 @@ func (plr *Player) GetAppearanceData() protocol.SPCAppearanceData { PCStyle: plr.PCStyle, IPCState: plr.IPCState, ItemEquip: plr.Equip, - Nano: protocol.SNano{}, //plr.Nanos[plr.ActiveNanoSlotNum], + Nano: plr.Nanos[plr.ActiveNanoSlotNum], } } diff --git a/shard/chunks.go b/shard/chunks.go index dfa0efb..f3b1aa6 100644 --- a/shard/chunks.go +++ b/shard/chunks.go @@ -23,9 +23,11 @@ func (server *ShardServer) getViewableChunks(pos entity.ChunkPosition) []*entity return chunks } -func (server *ShardServer) sendPacketToViewableChunks(plr *entity.Player, typeID uint32, pkt ...interface{}) error { - for _, chunk := range server.getViewableChunks(plr.Chunk) { - chunk.SendPacket(typeID, pkt...) +// sends a packet to all peers in the given chunks, excluding the given peer +func (server *ShardServer) sendOthersPacket(plr *entity.Player, typeID uint32, pkt ...interface{}) error { + chunks := server.getViewableChunks(plr.Chunk) + for _, chunk := range chunks { + chunk.SendPacketExclude(plr, typeID, pkt...) } return nil @@ -34,11 +36,17 @@ func (server *ShardServer) sendPacketToViewableChunks(plr *entity.Player, typeID func (server *ShardServer) removeEntityFromChunks(chunks []*entity.Chunk, this entity.Entity) { for _, chunk := range chunks { for e, _ := range chunk.Entities { + if e == this { + continue + } + + // notify other players we're leaving if e.GetKind() == entity.ENTITY_KIND_PLAYER { otherPlr := e.(*entity.Player) this.DisappearFromViewOf(otherPlr.Peer) } + // notify us they're leaving if this.GetKind() == entity.ENTITY_KIND_PLAYER { thisPlr := this.(*entity.Player) 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) { for _, chunk := range chunks { for e, _ := range chunk.Entities { + if e == this { + continue + } + + // notify other players we're entering if e.GetKind() == entity.ENTITY_KIND_PLAYER { otherPlr := e.(*entity.Player) this.EnterIntoViewOf(otherPlr.Peer) } + // notify us they're entering if this.GetKind() == entity.ENTITY_KIND_PLAYER { thisPlr := this.(*entity.Player) 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) { + // no change needed + if from == to { + return + } + oldViewables := server.getViewableChunks(from) newViewables := server.getViewableChunks(to) diff --git a/shard/join.go b/shard/join.go index 85254ca..4faca25 100644 --- a/shard/join.go +++ b/shard/join.go @@ -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) - 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) } diff --git a/shard/movement.go b/shard/movement.go index 6ea302c..260e249 100644 --- a/shard/movement.go +++ b/shard/movement.go @@ -1,25 +1,18 @@ package shard import ( + "time" + "github.com/CPunch/gopenfusion/core/entity" "github.com/CPunch/gopenfusion/core/protocol" ) -func (server *ShardServer) updatePlayerPosition(peer *protocol.CNPeer, X, Y, Z, Angle int) error { - plr, err := server.getPlayer(peer) - if err != nil { - return err - } - newPos := entity.MakeChunkPosition(X, Y) - oldPos := plr.Chunk - +func (server *ShardServer) updatePlayerPosition(plr *entity.Player, X, Y, Z, Angle int) error { plr.X = X plr.Y = Y plr.Z = Z plr.Angle = Angle - if newPos != oldPos { - server.updateEntityChunk(plr, oldPos, newPos) - } + server.updateEntityChunk(plr, plr.GetChunk(), entity.MakeChunkPosition(X, Y)) return nil } @@ -27,5 +20,85 @@ func (server *ShardServer) playerMove(peer *protocol.CNPeer, pkt protocol.Packet var move protocol.SP_CL2FE_REQ_PC_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()), + }) } diff --git a/shard/shardServer.go b/shard/shardServer.go index db30c03..76c40db 100644 --- a/shard/shardServer.go +++ b/shard/shardServer.go @@ -50,6 +50,9 @@ func NewShardServer(dbHndlr *db.DBHandler, redisHndlr *redis.RedisHandler, port server.packetHandlers = map[uint32]PacketHandler{ protocol.P_CL2FE_REQ_PC_ENTER: server.RequestEnter, 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{