mirror of
https://github.com/CPunch/gopenfusion.git
synced 2024-11-21 23:10:06 +00:00
server: started ShardServer
- protocol: added GenSerialKey() which securely generates an EnterSerialKey - login server accepts a shard via LoginServer.AddShard() - login server will pass LoginMetaData to the selected shard via ShardServer.QueueLogin() - misc. refactoring
This commit is contained in:
parent
7a26ffdcf7
commit
1357de99aa
@ -8,6 +8,10 @@ var (
|
|||||||
AEQUIP_COUNT = 9
|
AEQUIP_COUNT = 9
|
||||||
AINVEN_COUNT = 50
|
AINVEN_COUNT = 50
|
||||||
ABANK_COUNT = 119
|
ABANK_COUNT = 119
|
||||||
|
|
||||||
|
LOGIN_PORT = 23000
|
||||||
|
SHARD_PORT = 23001
|
||||||
|
SHARD_IP = "127.0.0.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetMaxHP(level int) int {
|
func GetMaxHP(level int) int {
|
||||||
|
@ -39,15 +39,14 @@ type Player struct {
|
|||||||
SkywayLocationFlag []byte
|
SkywayLocationFlag []byte
|
||||||
FirstUseFlag []byte
|
FirstUseFlag []byte
|
||||||
Quests []byte
|
Quests []byte
|
||||||
/* Appearance tbl */
|
Body int /* Appearance tbl start */
|
||||||
Body int `db:"Body"`
|
EyeColor int
|
||||||
EyeColor int `db:"EyeColor"`
|
FaceStyle int
|
||||||
FaceStyle int `db:"FaceStyle"`
|
Gender int
|
||||||
Gender int `db:"Gender"`
|
HairColor int
|
||||||
HairColor int `db:"HairColor"`
|
HairStyle int
|
||||||
HairStyle int `db:"HairStyle"`
|
Height int
|
||||||
Height int `db:"Height"`
|
SkinColor int /* Appearance tbl end */
|
||||||
SkinColor int `db:"SkinColor"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns PlayerID, error
|
// returns PlayerID, error
|
||||||
|
@ -20,10 +20,6 @@ type DBHandler struct {
|
|||||||
//go:embed migrations/new.sql
|
//go:embed migrations/new.sql
|
||||||
var createDBQuery string
|
var createDBQuery string
|
||||||
|
|
||||||
var (
|
|
||||||
DefaultDB *DBHandler
|
|
||||||
)
|
|
||||||
|
|
||||||
func OpenLiteDB(dbPath string) (*DBHandler, error) {
|
func OpenLiteDB(dbPath string) (*DBHandler, error) {
|
||||||
sqliteFmt := fmt.Sprintf("%s", dbPath)
|
sqliteFmt := fmt.Sprintf("%s", dbPath)
|
||||||
|
|
||||||
|
28
main.go
28
main.go
@ -1,14 +1,32 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/CPunch/gopenfusion/config"
|
||||||
"github.com/CPunch/gopenfusion/db"
|
"github.com/CPunch/gopenfusion/db"
|
||||||
"github.com/CPunch/gopenfusion/server"
|
"github.com/CPunch/gopenfusion/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
db.DefaultDB, _ = db.OpenLiteDB("test.db")
|
dbHndlr, err := db.OpenLiteDB("test.db")
|
||||||
db.DefaultDB.Setup()
|
if err != nil {
|
||||||
|
log.Panicf("failed to open db: %v", err)
|
||||||
server := server.NewLoginServer()
|
}
|
||||||
server.Start()
|
dbHndlr.Setup()
|
||||||
|
|
||||||
|
loginServer, err := server.NewLoginServer(dbHndlr, config.LOGIN_PORT)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("failed to create login server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
shardServer, err := server.NewShardServer(dbHndlr, config.SHARD_PORT)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("failed to create shard server: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
loginServer.AddShard(shardServer)
|
||||||
|
go loginServer.Start()
|
||||||
|
|
||||||
|
shardServer.Start()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -58,3 +59,13 @@ func CreateNewKey(uTime uint64, iv1, iv2 uint64) []byte {
|
|||||||
binary.LittleEndian.PutUint64(buf, uint64(key))
|
binary.LittleEndian.PutUint64(buf, uint64(key))
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenSerialKey() (int64, error) {
|
||||||
|
tmp := [8]byte{}
|
||||||
|
if _, err := rand.Read(tmp[:]); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to uint64 && return
|
||||||
|
return int64(binary.LittleEndian.Uint64(tmp[:])), nil
|
||||||
|
}
|
||||||
|
8
server/join.go
Normal file
8
server/join.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import "github.com/CPunch/gopenfusion/protocol"
|
||||||
|
|
||||||
|
func (server *ShardServer) RequestEnter(peer *Peer, pkt protocol.Packet) error {
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -79,10 +79,10 @@ func (server *LoginServer) Login(peer *Peer, pkt protocol.Packet) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// attempt login
|
// attempt login
|
||||||
account, err := db.DefaultDB.TryLogin(loginPkt.SzID, loginPkt.SzPassword)
|
account, err := server.dbHndlr.TryLogin(loginPkt.SzID, loginPkt.SzPassword)
|
||||||
if err == db.LoginErrorInvalidID {
|
if err == db.LoginErrorInvalidID {
|
||||||
// this is the default behavior, auto create the account if the ID isn't in use
|
// this is the default behavior, auto create the account if the ID isn't in use
|
||||||
account, err = db.DefaultDB.NewAccount(loginPkt.SzID, loginPkt.SzPassword)
|
account, err = server.dbHndlr.NewAccount(loginPkt.SzID, loginPkt.SzPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// respond with a dummy login error packet so the client doesn't get softlocked
|
// respond with a dummy login error packet so the client doesn't get softlocked
|
||||||
SendError(LOGIN_DATABASE_ERROR)
|
SendError(LOGIN_DATABASE_ERROR)
|
||||||
@ -99,7 +99,7 @@ func (server *LoginServer) Login(peer *Peer, pkt protocol.Packet) error {
|
|||||||
|
|
||||||
// grab player data
|
// grab player data
|
||||||
peer.AccountID = account.AccountID
|
peer.AccountID = account.AccountID
|
||||||
plrs, err := db.DefaultDB.GetPlayers(account.AccountID)
|
plrs, err := server.dbHndlr.GetPlayers(account.AccountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
SendError(LOGIN_DATABASE_ERROR)
|
SendError(LOGIN_DATABASE_ERROR)
|
||||||
return err
|
return err
|
||||||
@ -124,7 +124,7 @@ func (server *LoginServer) Login(peer *Peer, pkt protocol.Packet) error {
|
|||||||
IZ: int32(plr.ZCoordinate),
|
IZ: int32(plr.ZCoordinate),
|
||||||
}
|
}
|
||||||
|
|
||||||
AEquip, err := db.DefaultDB.GetPlayerInventorySlots(plr.PlayerID, 0, config.AEQUIP_COUNT-1)
|
AEquip, err := server.dbHndlr.GetPlayerInventorySlots(plr.PlayerID, 0, config.AEQUIP_COUNT-1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
SendError(LOGIN_DATABASE_ERROR)
|
SendError(LOGIN_DATABASE_ERROR)
|
||||||
return err
|
return err
|
||||||
@ -158,7 +158,7 @@ func (server *LoginServer) SaveCharacterName(peer *Peer, pkt protocol.Packet) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: sanity check SzFirstName && SzLastName
|
// TODO: sanity check SzFirstName && SzLastName
|
||||||
PlayerID, err := db.DefaultDB.NewPlayer(peer.AccountID, charPkt.SzFirstName, charPkt.SzLastName, int(charPkt.ISlotNum))
|
PlayerID, err := server.dbHndlr.NewPlayer(peer.AccountID, charPkt.SzFirstName, charPkt.SzLastName, int(charPkt.ISlotNum))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peer.Send(protocol.P_LS2CL_REP_SAVE_CHAR_NAME_FAIL, protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_FAIL{})
|
peer.Send(protocol.P_LS2CL_REP_SAVE_CHAR_NAME_FAIL, protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_FAIL{})
|
||||||
return err
|
return err
|
||||||
@ -218,11 +218,11 @@ func (server *LoginServer) CharacterCreate(peer *Peer, pkt protocol.Packet) erro
|
|||||||
return SendFail(peer)
|
return SendFail(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.DefaultDB.FinishPlayer(&charPkt, peer.AccountID); err != nil {
|
if err := server.dbHndlr.FinishPlayer(&charPkt, peer.AccountID); err != nil {
|
||||||
return SendFail(peer)
|
return SendFail(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
plr, err := db.DefaultDB.GetPlayer(int(charPkt.PCStyle.IPC_UID))
|
plr, err := server.dbHndlr.GetPlayer(int(charPkt.PCStyle.IPC_UID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SendFail(peer)
|
return SendFail(peer)
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ func (server *LoginServer) CharacterDelete(peer *Peer, pkt protocol.Packet) erro
|
|||||||
var charPkt protocol.SP_CL2LS_REQ_CHAR_DELETE
|
var charPkt protocol.SP_CL2LS_REQ_CHAR_DELETE
|
||||||
pkt.Decode(&charPkt)
|
pkt.Decode(&charPkt)
|
||||||
|
|
||||||
slot, err := db.DefaultDB.DeletePlayer(int(charPkt.IPC_UID), peer.AccountID)
|
slot, err := server.dbHndlr.DeletePlayer(int(charPkt.IPC_UID), peer.AccountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SendFail(peer)
|
return SendFail(peer)
|
||||||
}
|
}
|
||||||
@ -250,11 +250,43 @@ func (server *LoginServer) CharacterDelete(peer *Peer, pkt protocol.Packet) erro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (server *LoginServer) ShardSelect(peer *Peer, pkt protocol.Packet) error {
|
||||||
|
var selection protocol.SP_CL2LS_REQ_CHAR_SELECT
|
||||||
|
pkt.Decode(&selection)
|
||||||
|
|
||||||
|
if server.shard == nil {
|
||||||
|
return fmt.Errorf("LoginServer currently has no linked shard")
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := protocol.GenSerialKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: verify peer->AccountID and selection->IPC_UID are valid!!!!
|
||||||
|
|
||||||
|
resp := protocol.SP_LS2CL_REP_SHARD_SELECT_SUCC{
|
||||||
|
G_FE_ServerPort: int32(server.shard.port),
|
||||||
|
IEnterSerialKey: key,
|
||||||
|
}
|
||||||
|
|
||||||
|
// the rest of the bytes in G_FE_ServerIP will be zero'd, so there's no need to write the NULL byte
|
||||||
|
copy(resp.G_FE_ServerIP[:], []byte(config.SHARD_IP))
|
||||||
|
|
||||||
|
server.shard.QueueLogin(key, &LoginMetadata{
|
||||||
|
FEKey: peer.FE_key,
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
PlayerID: int32(selection.IPC_UID),
|
||||||
|
})
|
||||||
|
|
||||||
|
return peer.Send(protocol.P_LS2CL_REP_SHARD_SELECT_SUCC, resp)
|
||||||
|
}
|
||||||
|
|
||||||
func (server *LoginServer) FinishTutorial(peer *Peer, pkt protocol.Packet) error {
|
func (server *LoginServer) FinishTutorial(peer *Peer, pkt protocol.Packet) error {
|
||||||
var charPkt protocol.SP_CL2LS_REQ_SAVE_CHAR_TUTOR
|
var charPkt protocol.SP_CL2LS_REQ_SAVE_CHAR_TUTOR
|
||||||
pkt.Decode(&charPkt)
|
pkt.Decode(&charPkt)
|
||||||
|
|
||||||
if err := db.DefaultDB.FinishTutorial(int(charPkt.IPC_UID), peer.AccountID); err != nil {
|
if err := server.dbHndlr.FinishTutorial(int(charPkt.IPC_UID), peer.AccountID); err != nil {
|
||||||
return SendFail(peer)
|
return SendFail(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,61 +1,60 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/CPunch/gopenfusion/db"
|
||||||
"github.com/CPunch/gopenfusion/protocol"
|
"github.com/CPunch/gopenfusion/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PacketHandler func(peer *Peer, pkt protocol.Packet) error
|
|
||||||
|
|
||||||
type LoginServer struct {
|
type LoginServer struct {
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
|
port int
|
||||||
|
dbHndlr *db.DBHandler
|
||||||
packetHandlers map[uint32]PacketHandler
|
packetHandlers map[uint32]PacketHandler
|
||||||
peers map[*Peer]bool
|
peers map[*Peer]bool
|
||||||
peersLock sync.Mutex
|
peersLock sync.Mutex
|
||||||
|
shard *ShardServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func stubbedPacket(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }
|
func NewLoginServer(dbHndlr *db.DBHandler, port int) (*LoginServer, error) {
|
||||||
|
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||||
func NewLoginServer() *LoginServer {
|
|
||||||
listener, err := net.Listen("tcp", ":23000")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
loginServer := &LoginServer{
|
server := &LoginServer{
|
||||||
listener: listener,
|
listener: listener,
|
||||||
|
port: port,
|
||||||
|
dbHndlr: dbHndlr,
|
||||||
peers: make(map[*Peer]bool),
|
peers: make(map[*Peer]bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
loginServer.packetHandlers = map[uint32]PacketHandler{
|
server.packetHandlers = map[uint32]PacketHandler{
|
||||||
protocol.P_CL2LS_REQ_LOGIN: loginServer.Login,
|
protocol.P_CL2LS_REQ_LOGIN: server.Login,
|
||||||
protocol.P_CL2LS_REQ_CHECK_CHAR_NAME: loginServer.CheckCharacterName,
|
protocol.P_CL2LS_REQ_CHECK_CHAR_NAME: server.CheckCharacterName,
|
||||||
protocol.P_CL2LS_REQ_SAVE_CHAR_NAME: loginServer.SaveCharacterName,
|
protocol.P_CL2LS_REQ_SAVE_CHAR_NAME: server.SaveCharacterName,
|
||||||
protocol.P_CL2LS_REQ_CHAR_CREATE: loginServer.CharacterCreate,
|
protocol.P_CL2LS_REQ_CHAR_CREATE: server.CharacterCreate,
|
||||||
protocol.P_CL2LS_REQ_CHAR_SELECT: stubbedPacket,
|
protocol.P_CL2LS_REQ_CHAR_SELECT: server.ShardSelect,
|
||||||
protocol.P_CL2LS_REQ_CHAR_DELETE: loginServer.CharacterDelete,
|
protocol.P_CL2LS_REQ_CHAR_DELETE: server.CharacterDelete,
|
||||||
protocol.P_CL2LS_REQ_SHARD_SELECT: stubbedPacket,
|
protocol.P_CL2LS_REQ_SHARD_SELECT: stubbedPacket,
|
||||||
protocol.P_CL2LS_REQ_SHARD_LIST_INFO: stubbedPacket,
|
protocol.P_CL2LS_REQ_SHARD_LIST_INFO: stubbedPacket,
|
||||||
protocol.P_CL2LS_CHECK_NAME_LIST: stubbedPacket,
|
protocol.P_CL2LS_CHECK_NAME_LIST: stubbedPacket,
|
||||||
protocol.P_CL2LS_REQ_SAVE_CHAR_TUTOR: loginServer.FinishTutorial,
|
protocol.P_CL2LS_REQ_SAVE_CHAR_TUTOR: server.FinishTutorial,
|
||||||
protocol.P_CL2LS_REQ_PC_EXIT_DUPLICATE: stubbedPacket,
|
protocol.P_CL2LS_REQ_PC_EXIT_DUPLICATE: stubbedPacket,
|
||||||
protocol.P_CL2LS_REP_LIVE_CHECK: stubbedPacket,
|
protocol.P_CL2LS_REP_LIVE_CHECK: stubbedPacket,
|
||||||
protocol.P_CL2LS_REQ_CHANGE_CHAR_NAME: stubbedPacket,
|
protocol.P_CL2LS_REQ_CHANGE_CHAR_NAME: stubbedPacket,
|
||||||
protocol.P_CL2LS_REQ_SERVER_SELECT: stubbedPacket,
|
protocol.P_CL2LS_REQ_SERVER_SELECT: stubbedPacket,
|
||||||
}
|
}
|
||||||
|
|
||||||
return loginServer
|
return server, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (server *LoginServer) RegisterPacketHandler(typeID uint32, hndlr PacketHandler) {
|
|
||||||
server.packetHandlers[typeID] = hndlr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *LoginServer) Start() {
|
func (server *LoginServer) Start() {
|
||||||
log.Print("Server hosted on 127.0.0.1:23000")
|
log.Printf("Server hosted on 127.0.0.1:%d\n", server.port)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
conn, err := server.listener.Accept()
|
conn, err := server.listener.Accept()
|
||||||
@ -84,12 +83,18 @@ func (server *LoginServer) HandlePacket(peer *Peer, typeID uint32, pkt protocol.
|
|||||||
|
|
||||||
func (server *LoginServer) Disconnect(peer *Peer) {
|
func (server *LoginServer) Disconnect(peer *Peer) {
|
||||||
server.peersLock.Lock()
|
server.peersLock.Lock()
|
||||||
|
log.Printf("Peer %p disconnected from LOGIN\n", peer)
|
||||||
delete(server.peers, peer)
|
delete(server.peers, peer)
|
||||||
server.peersLock.Unlock()
|
server.peersLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (server *LoginServer) Connect(peer *Peer) {
|
func (server *LoginServer) Connect(peer *Peer) {
|
||||||
server.peersLock.Lock()
|
server.peersLock.Lock()
|
||||||
|
log.Printf("New peer %p connected to LOGIN\n", peer)
|
||||||
server.peers[peer] = true
|
server.peers[peer] = true
|
||||||
server.peersLock.Unlock()
|
server.peersLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (server *LoginServer) AddShard(shard *ShardServer) {
|
||||||
|
server.shard = shard
|
||||||
|
}
|
@ -7,7 +7,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/CPunch/gopenfusion/db"
|
|
||||||
"github.com/CPunch/gopenfusion/protocol"
|
"github.com/CPunch/gopenfusion/protocol"
|
||||||
"github.com/CPunch/gopenfusion/protocol/pool"
|
"github.com/CPunch/gopenfusion/protocol/pool"
|
||||||
)
|
)
|
||||||
@ -24,7 +23,6 @@ type PeerHandler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
Player *db.Player
|
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
handler PeerHandler
|
handler PeerHandler
|
||||||
SzID string
|
SzID string
|
||||||
@ -37,15 +35,14 @@ type Peer struct {
|
|||||||
|
|
||||||
func NewPeer(handler PeerHandler, conn net.Conn) *Peer {
|
func NewPeer(handler PeerHandler, conn net.Conn) *Peer {
|
||||||
return &Peer{
|
return &Peer{
|
||||||
|
conn: conn,
|
||||||
|
handler: handler,
|
||||||
|
SzID: "",
|
||||||
E_key: []byte(protocol.DEFAULT_KEY),
|
E_key: []byte(protocol.DEFAULT_KEY),
|
||||||
FE_key: nil,
|
FE_key: nil,
|
||||||
SzID: "",
|
|
||||||
AccountID: -1,
|
AccountID: -1,
|
||||||
Player: nil,
|
|
||||||
handler: handler,
|
|
||||||
conn: conn,
|
|
||||||
alive: true,
|
|
||||||
whichKey: USE_E,
|
whichKey: USE_E,
|
||||||
|
alive: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
126
server/shardServer.go
Normal file
126
server/shardServer.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/CPunch/gopenfusion/db"
|
||||||
|
"github.com/CPunch/gopenfusion/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoginMetadata struct {
|
||||||
|
FEKey []byte
|
||||||
|
Timestamp time.Time
|
||||||
|
PlayerID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShardServer struct {
|
||||||
|
listener net.Listener
|
||||||
|
port int
|
||||||
|
dbHndlr *db.DBHandler
|
||||||
|
packetHandlers map[uint32]PacketHandler
|
||||||
|
peers sync.Map // [*Peer]*db.Player
|
||||||
|
loginMetadataQueue sync.Map // [int64]*LoginMetadata w/ int64 = serialKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShardServer(dbHndlr *db.DBHandler, port int) (*ShardServer, error) {
|
||||||
|
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
server := &ShardServer{
|
||||||
|
listener: listener,
|
||||||
|
port: port,
|
||||||
|
dbHndlr: dbHndlr,
|
||||||
|
packetHandlers: make(map[uint32]PacketHandler),
|
||||||
|
}
|
||||||
|
|
||||||
|
server.packetHandlers = map[uint32]PacketHandler{}
|
||||||
|
|
||||||
|
return server, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) RegisterPacketHandler(typeID uint32, hndlr PacketHandler) {
|
||||||
|
server.packetHandlers[typeID] = hndlr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) Start() {
|
||||||
|
log.Printf("Server hosted on 127.0.0.1:%d\n", server.port)
|
||||||
|
|
||||||
|
for {
|
||||||
|
conn, err := server.listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Connection error: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client := NewPeer(server, conn)
|
||||||
|
server.Connect(client)
|
||||||
|
go client.Handler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) HandlePacket(peer *Peer, typeID uint32, pkt protocol.Packet) error {
|
||||||
|
if hndlr, ok := server.packetHandlers[typeID]; ok {
|
||||||
|
if err := hndlr(peer, pkt); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("[WARN] invalid packet ID: %x\n", typeID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) Disconnect(peer *Peer) {
|
||||||
|
log.Printf("Peer %p disconnected from SHARD\n", peer)
|
||||||
|
server.peers.Delete(peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) Connect(peer *Peer) {
|
||||||
|
log.Printf("New peer %p connected to SHARD\n", peer)
|
||||||
|
server.peers.Store(peer, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) JoinPlayer(peer *Peer, player *db.Player) {
|
||||||
|
server.peers.Store(peer, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple wrapper for server.peers.Range, if f returns false the iteration is stopped.
|
||||||
|
func (server *ShardServer) RangePeers(f func(peer *Peer, player *db.Player) bool) {
|
||||||
|
server.peers.Range(func(key, value any) bool { // simple wrapper to cast the datatypes
|
||||||
|
peer, ok := key.(*Peer)
|
||||||
|
if !ok { // this should never happen
|
||||||
|
panic(fmt.Errorf("ShardServer.peers has an invalid key: peers[%#v] = %#v", key, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
player, ok := value.(*db.Player)
|
||||||
|
if !ok { // this should also never happen
|
||||||
|
panic(fmt.Errorf("ShardServer.peers has an invalid value: peers[%#v] = %#v", key, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return f(peer, player)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) QueueLogin(serialKey int64, meta *LoginMetadata) {
|
||||||
|
server.loginMetadataQueue.Store(serialKey, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *ShardServer) CheckLogin(serialKey int64) (*LoginMetadata, error) {
|
||||||
|
value, ok := server.loginMetadataQueue.Load(serialKey)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("serialKey %x is not valid!", serialKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
meta, ok := value.(*LoginMetadata)
|
||||||
|
if !ok { // should never happen
|
||||||
|
panic(fmt.Errorf("ShardServer.loginMetadataQueue has an invalid value: loginMetadataQueue[%x] = %#v", serialKey, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta, nil
|
||||||
|
}
|
9
server/shared.go
Normal file
9
server/shared.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/CPunch/gopenfusion/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PacketHandler func(peer *Peer, pkt protocol.Packet) error
|
||||||
|
|
||||||
|
func stubbedPacket(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }
|
Loading…
Reference in New Issue
Block a user