mirror of
https://github.com/CPunch/gopenfusion.git
synced 2024-12-04 22:46:32 +00:00
Compare commits
3 Commits
c09a6cfd25
...
c4325475ed
Author | SHA1 | Date | |
---|---|---|---|
c4325475ed | |||
fd41b32b70 | |||
80dc876517 |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "tdata"]
|
||||
path = tdata
|
||||
url = https://github.com/OpenFusionProject/tabledata.git
|
@ -35,6 +35,9 @@ services:
|
||||
- DB_PASS=gopenfusion
|
||||
- DB_NAME=gopenfusion
|
||||
- REDIS_ADDR=redis:6379
|
||||
- TDATA_PATH=/tdata
|
||||
volumes:
|
||||
- './tdata:/tdata'
|
||||
ports:
|
||||
- '23001:23001'
|
||||
links:
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
DB_USER
|
||||
DB_PASS
|
||||
ANNOUNCE_IP
|
||||
TDATA_PATH
|
||||
*/
|
||||
|
||||
const (
|
||||
@ -78,3 +79,7 @@ func GetDBPass() string {
|
||||
func GetAnnounceIP() string {
|
||||
return getEnv("ANNOUNCE_IP", "127.0.0.1")
|
||||
}
|
||||
|
||||
func GetTDataPath() string {
|
||||
return getEnv("TDATA_PATH", "./tdata")
|
||||
}
|
||||
|
84
core/entity/npc.go
Normal file
84
core/entity/npc.go
Normal file
@ -0,0 +1,84 @@
|
||||
package entity
|
||||
|
||||
import "github.com/CPunch/gopenfusion/core/protocol"
|
||||
|
||||
type NPC struct {
|
||||
ID int
|
||||
X int `json:"iX"`
|
||||
Y int `json:"iY"`
|
||||
Z int `json:"iZ"`
|
||||
Angle int `json:"iAngle"`
|
||||
NPCType int `json:"iNPCType"`
|
||||
Chunk ChunkPosition
|
||||
}
|
||||
|
||||
var nextNPCID = 0
|
||||
|
||||
func NewNPC(X, Y, Z, Angle int, npcType int) *NPC {
|
||||
nextNPCID++
|
||||
return &NPC{
|
||||
ID: nextNPCID,
|
||||
X: X,
|
||||
Y: Y,
|
||||
Z: Z,
|
||||
Angle: Angle,
|
||||
NPCType: npcType,
|
||||
Chunk: MakeChunkPosition(X, Y),
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Entity interface ====================
|
||||
|
||||
func (npc *NPC) GetKind() EntityKind {
|
||||
return ENTITY_KIND_NPC
|
||||
}
|
||||
|
||||
func (npc *NPC) GetChunk() ChunkPosition {
|
||||
return npc.Chunk
|
||||
}
|
||||
|
||||
func (npc *NPC) GetPosition() (x int, y int, z int) {
|
||||
return npc.X, npc.Y, npc.Z
|
||||
}
|
||||
|
||||
func (npc *NPC) GetAngle() int {
|
||||
return npc.Angle
|
||||
}
|
||||
|
||||
func (npc *NPC) SetChunk(chunk ChunkPosition) {
|
||||
npc.Chunk = chunk
|
||||
}
|
||||
|
||||
func (npc *NPC) SetPosition(x, y, z int) {
|
||||
npc.X = x
|
||||
npc.Y = y
|
||||
npc.Z = z
|
||||
}
|
||||
|
||||
func (npc *NPC) SetAngle(angle int) {
|
||||
npc.Angle = angle
|
||||
}
|
||||
|
||||
func (npc *NPC) DisappearFromViewOf(peer *protocol.CNPeer) {
|
||||
peer.Send(protocol.P_FE2CL_NPC_EXIT, protocol.SP_FE2CL_NPC_EXIT{
|
||||
INPC_ID: int32(npc.ID),
|
||||
})
|
||||
}
|
||||
|
||||
func (npc *NPC) EnterIntoViewOf(peer *protocol.CNPeer) {
|
||||
peer.Send(protocol.P_FE2CL_NPC_NEW, protocol.SP_FE2CL_NPC_NEW{
|
||||
NPCAppearanceData: npc.GetAppearanceData(),
|
||||
})
|
||||
}
|
||||
|
||||
func (npc *NPC) GetAppearanceData() protocol.SNPCAppearanceData {
|
||||
return protocol.SNPCAppearanceData{
|
||||
INPC_ID: int32(npc.ID),
|
||||
INPCType: int32(npc.NPCType),
|
||||
IHP: 100,
|
||||
IX: int32(npc.X),
|
||||
IY: int32(npc.Y),
|
||||
IZ: int32(npc.Z),
|
||||
IAngle: int32(npc.Angle),
|
||||
}
|
||||
}
|
@ -4,6 +4,18 @@ import (
|
||||
"github.com/CPunch/gopenfusion/core/entity"
|
||||
)
|
||||
|
||||
func (server *ShardServer) addEntity(e entity.Entity) {
|
||||
pos := e.GetChunk()
|
||||
server.addEntityToChunks(server.getViewableChunks(pos), e)
|
||||
server.getChunk(pos).AddEntity(e)
|
||||
}
|
||||
|
||||
func (server *ShardServer) removeEntity(e entity.Entity) {
|
||||
pos := e.GetChunk()
|
||||
server.removeEntityFromChunks(server.getViewableChunks(pos), e)
|
||||
server.getChunk(pos).RemoveEntity(e)
|
||||
}
|
||||
|
||||
func (server *ShardServer) getChunk(pos entity.ChunkPosition) *entity.Chunk {
|
||||
chunk, ok := server.chunks[pos]
|
||||
if !ok {
|
||||
@ -35,7 +47,7 @@ func (server *ShardServer) sendOthersPacket(plr *entity.Player, typeID uint32, p
|
||||
|
||||
func (server *ShardServer) removeEntityFromChunks(chunks []*entity.Chunk, this entity.Entity) {
|
||||
for _, chunk := range chunks {
|
||||
for e, _ := range chunk.Entities {
|
||||
for e := range chunk.Entities {
|
||||
if e == this {
|
||||
continue
|
||||
}
|
||||
@ -57,7 +69,7 @@ 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 {
|
||||
for e := range chunk.Entities {
|
||||
if e == this {
|
||||
continue
|
||||
}
|
@ -58,8 +58,13 @@ func (server *ShardServer) RequestEnter(peer *protocol.CNPeer, pkt protocol.Pack
|
||||
|
||||
log.Printf("Player %d (AccountID %d) entered\n", resp.IID, loginData.AccountID)
|
||||
|
||||
if err := peer.Send(protocol.P_FE2CL_REP_PC_ENTER_SUCC, resp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// we send the chunk updates (PC_NEW, NPC_NEW, etc.) after the enter packet
|
||||
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 nil
|
||||
}
|
||||
|
||||
func (server *ShardServer) LoadingComplete(peer *protocol.CNPeer, pkt protocol.Packet) error {
|
||||
|
@ -5,13 +5,12 @@ import (
|
||||
"github.com/CPunch/gopenfusion/core/protocol"
|
||||
)
|
||||
|
||||
func (server *ShardServer) updatePlayerPosition(plr *entity.Player, X, Y, Z, Angle int) error {
|
||||
func (server *ShardServer) updatePlayerPosition(plr *entity.Player, X, Y, Z, Angle int) {
|
||||
plr.X = X
|
||||
plr.Y = Y
|
||||
plr.Z = Z
|
||||
plr.Angle = Angle
|
||||
server.updateEntityChunk(plr, plr.GetChunk(), entity.MakeChunkPosition(X, Y))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *ShardServer) playerMove(peer *protocol.CNPeer, pkt protocol.Packet) error {
|
||||
@ -25,9 +24,7 @@ func (server *ShardServer) playerMove(peer *protocol.CNPeer, pkt protocol.Packet
|
||||
}
|
||||
|
||||
// update chunking
|
||||
if err := server.updatePlayerPosition(plr, int(move.IX), int(move.IY), int(move.IZ), int(move.IAngle)); err != nil {
|
||||
return err
|
||||
}
|
||||
server.updatePlayerPosition(plr, int(move.IX), int(move.IY), int(move.IZ), int(move.IAngle))
|
||||
|
||||
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_MOVE, protocol.SP_FE2CL_PC_MOVE{
|
||||
ICliTime: move.ICliTime,
|
||||
@ -56,9 +53,7 @@ func (server *ShardServer) playerStop(peer *protocol.CNPeer, pkt protocol.Packet
|
||||
}
|
||||
|
||||
// update chunking
|
||||
if err := server.updatePlayerPosition(plr, int(stop.IX), int(stop.IY), int(stop.IZ), plr.Angle); err != nil {
|
||||
return err
|
||||
}
|
||||
server.updatePlayerPosition(plr, int(stop.IX), int(stop.IY), int(stop.IZ), plr.Angle)
|
||||
|
||||
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_STOP, protocol.SP_FE2CL_PC_STOP{
|
||||
ICliTime: stop.ICliTime,
|
||||
@ -81,9 +76,7 @@ func (server *ShardServer) playerJump(peer *protocol.CNPeer, pkt protocol.Packet
|
||||
}
|
||||
|
||||
// update chunking
|
||||
if err := server.updatePlayerPosition(plr, int(jump.IX), int(jump.IY), int(jump.IZ), plr.Angle); err != nil {
|
||||
return err
|
||||
}
|
||||
server.updatePlayerPosition(plr, int(jump.IX), int(jump.IY), int(jump.IZ), plr.Angle)
|
||||
|
||||
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_JUMP, protocol.SP_FE2CL_PC_JUMP{
|
||||
ICliTime: jump.ICliTime,
|
||||
|
32
shard/npcloader.go
Normal file
32
shard/npcloader.go
Normal file
@ -0,0 +1,32 @@
|
||||
package shard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/CPunch/gopenfusion/config"
|
||||
"github.com/CPunch/gopenfusion/core/entity"
|
||||
)
|
||||
|
||||
type NPCData struct {
|
||||
NPCs map[string]entity.NPC `json:"NPCs"`
|
||||
}
|
||||
|
||||
func (server *ShardServer) LoadNPCs() {
|
||||
log.Print("Loading NPCs...")
|
||||
|
||||
data, err := os.ReadFile(config.GetTDataPath() + "/NPCs.json")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// yes, we have to do it this way so our NPCs IDs will be incremented and unique
|
||||
var NPCs NPCData
|
||||
json.Unmarshal(data, &NPCs)
|
||||
for _, npc := range NPCs.NPCs {
|
||||
server.addEntity(entity.NewNPC(npc.X, npc.Y, npc.Z, npc.Angle, npc.NPCType))
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d NPCs!", len(NPCs.NPCs))
|
||||
}
|
@ -72,7 +72,6 @@ func (server *ShardServer) handleEvents() {
|
||||
server.disconnect(event.Peer)
|
||||
case protocol.EVENT_CLIENT_PACKET:
|
||||
defer pool.Put(event.Pkt)
|
||||
log.Printf("Received packet %x from %p\n", event.PktID, event.Peer)
|
||||
if err := server.handlePacket(event.Peer, event.PktID, protocol.NewPacket(event.Pkt)); err != nil {
|
||||
event.Peer.Kill()
|
||||
}
|
||||
@ -82,8 +81,9 @@ func (server *ShardServer) handleEvents() {
|
||||
}
|
||||
|
||||
func (server *ShardServer) Start() {
|
||||
log.Printf("Shard service hosted on %s:%d\n", config.GetAnnounceIP(), server.port)
|
||||
server.LoadNPCs()
|
||||
|
||||
log.Printf("Shard service hosted on %s:%d\n", config.GetAnnounceIP(), server.port)
|
||||
go server.handleEvents()
|
||||
for {
|
||||
conn, err := server.listener.Accept()
|
||||
@ -122,8 +122,7 @@ func (server *ShardServer) disconnect(peer *protocol.CNPeer) {
|
||||
plr, ok := server.peers[peer]
|
||||
if ok {
|
||||
log.Printf("Player %d (AccountID %d) disconnected\n", plr.PlayerID, plr.AccountID)
|
||||
server.removeEntityFromChunks(server.getViewableChunks(plr.Chunk), plr)
|
||||
server.getChunk(plr.Chunk).RemoveEntity(plr)
|
||||
server.removeEntity(plr)
|
||||
}
|
||||
|
||||
log.Printf("Peer %p disconnected from SHARD\n", peer)
|
1
tdata
Submodule
1
tdata
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cc65dbb402b5baa2b604ed66132edd88cc82a52a
|
Loading…
Reference in New Issue
Block a user