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_PASS=gopenfusion
|
||||||
- DB_NAME=gopenfusion
|
- DB_NAME=gopenfusion
|
||||||
- REDIS_ADDR=redis:6379
|
- REDIS_ADDR=redis:6379
|
||||||
|
- TDATA_PATH=/tdata
|
||||||
|
volumes:
|
||||||
|
- './tdata:/tdata'
|
||||||
ports:
|
ports:
|
||||||
- '23001:23001'
|
- '23001:23001'
|
||||||
links:
|
links:
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
DB_USER
|
DB_USER
|
||||||
DB_PASS
|
DB_PASS
|
||||||
ANNOUNCE_IP
|
ANNOUNCE_IP
|
||||||
|
TDATA_PATH
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -78,3 +79,7 @@ func GetDBPass() string {
|
|||||||
func GetAnnounceIP() string {
|
func GetAnnounceIP() string {
|
||||||
return getEnv("ANNOUNCE_IP", "127.0.0.1")
|
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"
|
"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 {
|
func (server *ShardServer) getChunk(pos entity.ChunkPosition) *entity.Chunk {
|
||||||
chunk, ok := server.chunks[pos]
|
chunk, ok := server.chunks[pos]
|
||||||
if !ok {
|
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) {
|
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 {
|
if e == this {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -57,7 +69,7 @@ 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 {
|
if e == this {
|
||||||
continue
|
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)
|
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))
|
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 {
|
func (server *ShardServer) LoadingComplete(peer *protocol.CNPeer, pkt protocol.Packet) error {
|
||||||
|
@ -5,13 +5,12 @@ import (
|
|||||||
"github.com/CPunch/gopenfusion/core/protocol"
|
"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.X = X
|
||||||
plr.Y = Y
|
plr.Y = Y
|
||||||
plr.Z = Z
|
plr.Z = Z
|
||||||
plr.Angle = Angle
|
plr.Angle = Angle
|
||||||
server.updateEntityChunk(plr, plr.GetChunk(), entity.MakeChunkPosition(X, Y))
|
server.updateEntityChunk(plr, plr.GetChunk(), entity.MakeChunkPosition(X, Y))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *ShardServer) playerMove(peer *protocol.CNPeer, pkt protocol.Packet) error {
|
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
|
// update chunking
|
||||||
if err := server.updatePlayerPosition(plr, int(move.IX), int(move.IY), int(move.IZ), int(move.IAngle)); err != nil {
|
server.updatePlayerPosition(plr, int(move.IX), int(move.IY), int(move.IZ), int(move.IAngle))
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_MOVE, protocol.SP_FE2CL_PC_MOVE{
|
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_MOVE, protocol.SP_FE2CL_PC_MOVE{
|
||||||
ICliTime: move.ICliTime,
|
ICliTime: move.ICliTime,
|
||||||
@ -56,9 +53,7 @@ func (server *ShardServer) playerStop(peer *protocol.CNPeer, pkt protocol.Packet
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update chunking
|
// update chunking
|
||||||
if err := server.updatePlayerPosition(plr, int(stop.IX), int(stop.IY), int(stop.IZ), plr.Angle); err != nil {
|
server.updatePlayerPosition(plr, int(stop.IX), int(stop.IY), int(stop.IZ), plr.Angle)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_STOP, protocol.SP_FE2CL_PC_STOP{
|
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_STOP, protocol.SP_FE2CL_PC_STOP{
|
||||||
ICliTime: stop.ICliTime,
|
ICliTime: stop.ICliTime,
|
||||||
@ -81,9 +76,7 @@ func (server *ShardServer) playerJump(peer *protocol.CNPeer, pkt protocol.Packet
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update chunking
|
// update chunking
|
||||||
if err := server.updatePlayerPosition(plr, int(jump.IX), int(jump.IY), int(jump.IZ), plr.Angle); err != nil {
|
server.updatePlayerPosition(plr, int(jump.IX), int(jump.IY), int(jump.IZ), plr.Angle)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_JUMP, protocol.SP_FE2CL_PC_JUMP{
|
return server.sendOthersPacket(plr, protocol.P_FE2CL_PC_JUMP, protocol.SP_FE2CL_PC_JUMP{
|
||||||
ICliTime: jump.ICliTime,
|
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)
|
server.disconnect(event.Peer)
|
||||||
case protocol.EVENT_CLIENT_PACKET:
|
case protocol.EVENT_CLIENT_PACKET:
|
||||||
defer pool.Put(event.Pkt)
|
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 {
|
if err := server.handlePacket(event.Peer, event.PktID, protocol.NewPacket(event.Pkt)); err != nil {
|
||||||
event.Peer.Kill()
|
event.Peer.Kill()
|
||||||
}
|
}
|
||||||
@ -82,8 +81,9 @@ func (server *ShardServer) handleEvents() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (server *ShardServer) Start() {
|
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()
|
go server.handleEvents()
|
||||||
for {
|
for {
|
||||||
conn, err := server.listener.Accept()
|
conn, err := server.listener.Accept()
|
||||||
@ -122,8 +122,7 @@ func (server *ShardServer) disconnect(peer *protocol.CNPeer) {
|
|||||||
plr, ok := server.peers[peer]
|
plr, ok := server.peers[peer]
|
||||||
if ok {
|
if ok {
|
||||||
log.Printf("Player %d (AccountID %d) disconnected\n", plr.PlayerID, plr.AccountID)
|
log.Printf("Player %d (AccountID %d) disconnected\n", plr.PlayerID, plr.AccountID)
|
||||||
server.removeEntityFromChunks(server.getViewableChunks(plr.Chunk), plr)
|
server.removeEntity(plr)
|
||||||
server.getChunk(plr.Chunk).RemoveEntity(plr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Peer %p disconnected from SHARD\n", peer)
|
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