简单游戏demo实现

This commit is contained in:
kercylan98 2023-04-27 13:25:11 +08:00
parent a722ef46e2
commit 723e618df2
13 changed files with 216 additions and 67 deletions

View File

@ -0,0 +1 @@
简单游戏实现demo

View File

@ -0,0 +1,23 @@
package game
import (
"minotaur/game"
"minotaur/game/builtin"
"minotaur/server"
)
var (
Server *server.Server
Game *app
)
func init() {
Server = server.New(server.NetworkTCP)
Game = &app{
World: builtin.NewWorld[int64, *Player](0),
}
}
type app struct {
game.World[int64, *Player]
}

View File

@ -0,0 +1,43 @@
package game
import (
"log"
"minotaur/game"
"minotaur/game/builtin"
"minotaur/server"
"time"
)
func NewPlayer(id int64, conn *server.Conn) *Player {
player := &Player{
Player: builtin.NewPlayer[int64](id, conn),
}
gameplay := builtin.NewGameplay()
gameplayOver := builtin.NewGameplayOver()
gameplayTime := builtin.NewGameplayTime(gameplay, gameplayOver)
player.GameplayTime = gameplayTime
return player
}
type Player struct {
*builtin.Player[int64]
game.GameplayTime
}
func (slf *Player) Start() {
_ = slf.GameStart(func() error {
log.Println("game start, init map...")
return nil
})
}
func (slf *Player) onGameplayStart(t time.Time) {
slf.SetEndTime(t.Add(60 * time.Second))
log.Println("the game will end in 60 seconds")
}
func (slf *Player) onGameplayOver() {
log.Println("game over")
}

View File

@ -0,0 +1,39 @@
package game
import (
"minotaur/server"
"minotaur/utils/sole"
)
func init() {
Server.RegConnectionOpenedEvent(onConnectionOpened)
Game.RegPlayerLeaveWorldEvent(onConnectionClosed)
Server.RegConnectionReceivePacketEvent(onConnectionReceivePacket)
}
func onConnectionReceivePacket(conn *server.Conn, packet []byte) {
player := Game.World.GetPlayerWithConnID(conn.GetID())
if player == nil {
return
}
player.RegGameplayStartEvent(player.onGameplayStart)
player.RegGameplayOverEvent(player.onGameplayOver)
switch string(packet) {
case "start":
player.Start()
}
}
func onConnectionClosed(player *Player) {
Game.Leave(player.GetID())
player.Close()
}
func onConnectionOpened(conn *server.Conn) {
player := NewPlayer(sole.GetSync(), conn)
if err := Game.World.Join(player); err != nil {
panic(err)
}
}

View File

@ -0,0 +1,9 @@
package main
import "minotaur/game/builtin/examples/game/game"
func main() {
if err := game.Server.Run(":9999"); err != nil {
panic(err)
}
}

View File

@ -19,6 +19,10 @@ func (slf *Player[ID]) GetID() ID {
return slf.id return slf.id
} }
func (slf *Player[ID]) GetConnID() string {
return slf.conn.GetID()
}
// Send 向该玩家发送数据 // Send 向该玩家发送数据
func (slf *Player[ID]) Send(packet []byte) error { func (slf *Player[ID]) Send(packet []byte) error {
return slf.conn.Write(packet) return slf.conn.Write(packet)

View File

@ -6,10 +6,11 @@ import (
"sync/atomic" "sync/atomic"
) )
func NewWorld[PlayerID comparable](guid int64, options ...WorldOption[PlayerID]) *World[PlayerID] { func NewWorld[PlayerID comparable, Player game.Player[PlayerID]](guid int64, options ...WorldOption[PlayerID, Player]) *World[PlayerID, Player] {
world := &World[PlayerID]{ world := &World[PlayerID, Player]{
guid: guid, guid: guid,
players: synchronization.NewMap[PlayerID, game.Player[PlayerID]](), playersConn: synchronization.NewMap[string, Player](),
players: synchronization.NewMap[PlayerID, Player](),
playerActors: synchronization.NewMap[PlayerID, *synchronization.Map[int64, game.Actor]](), playerActors: synchronization.NewMap[PlayerID, *synchronization.Map[int64, game.Actor]](),
owners: synchronization.NewMap[int64, PlayerID](), owners: synchronization.NewMap[int64, PlayerID](),
actors: synchronization.NewMap[int64, game.Actor](), actors: synchronization.NewMap[int64, game.Actor](),
@ -20,70 +21,75 @@ func NewWorld[PlayerID comparable](guid int64, options ...WorldOption[PlayerID])
return world return world
} }
type World[PlayerID comparable] struct { type World[PlayerID comparable, Player game.Player[PlayerID]] struct {
guid int64 guid int64
actorGuid atomic.Int64 actorGuid atomic.Int64
playerLimit int playerLimit int
players *synchronization.Map[PlayerID, game.Player[PlayerID]] playersConn *synchronization.Map[string, Player]
players *synchronization.Map[PlayerID, Player]
playerActors *synchronization.Map[PlayerID, *synchronization.Map[int64, game.Actor]] playerActors *synchronization.Map[PlayerID, *synchronization.Map[int64, game.Actor]]
owners *synchronization.Map[int64, PlayerID] owners *synchronization.Map[int64, PlayerID]
actors *synchronization.Map[int64, game.Actor] actors *synchronization.Map[int64, game.Actor]
playerJoinWorldEventHandles []game.PlayerJoinWorldEventHandle[PlayerID] playerJoinWorldEventHandles []game.PlayerJoinWorldEventHandle[PlayerID, Player]
playerLeaveWorldEventHandles []game.PlayerLeaveWorldEventHandle[PlayerID] playerLeaveWorldEventHandles []game.PlayerLeaveWorldEventHandle[PlayerID, Player]
actorGeneratedEventHandles []game.ActorGeneratedEventHandle actorGeneratedEventHandles []game.ActorGeneratedEventHandle
actorAnnihilationEventHandles []game.ActorAnnihilationEventHandle actorAnnihilationEventHandles []game.ActorAnnihilationEventHandle
actorOwnerChangeEventHandles []game.ActorOwnerChangeEventHandle[PlayerID] actorOwnerChangeEventHandles []game.ActorOwnerChangeEventHandle[PlayerID]
worldResetEventHandles []game.WorldResetEventHandle[PlayerID] worldResetEventHandles []game.WorldResetEventHandle[PlayerID, Player]
worldReleasedEventHandles []game.WorldReleaseEventHandle[PlayerID] worldReleasedEventHandles []game.WorldReleaseEventHandle[PlayerID, Player]
released atomic.Bool released atomic.Bool
} }
func (slf *World[PlayerID]) GetGuid() int64 { func (slf *World[PlayerID, Player]) GetGuid() int64 {
return slf.guid return slf.guid
} }
func (slf *World[PlayerID]) GetPlayerLimit() int { func (slf *World[PlayerID, Player]) GetPlayerLimit() int {
return slf.playerLimit return slf.playerLimit
} }
func (slf *World[PlayerID]) GetPlayer(id PlayerID) game.Player[PlayerID] { func (slf *World[PlayerID, Player]) GetPlayerWithConnID(id string) Player {
return slf.playersConn.Get(id)
}
func (slf *World[PlayerID, Player]) GetPlayer(id PlayerID) Player {
return slf.players.Get(id) return slf.players.Get(id)
} }
func (slf *World[PlayerID]) GetPlayers() map[PlayerID]game.Player[PlayerID] { func (slf *World[PlayerID, Player]) GetPlayers() map[PlayerID]Player {
return slf.players.Map() return slf.players.Map()
} }
func (slf *World[PlayerID]) GetActor(guid int64) game.Actor { func (slf *World[PlayerID, Player]) GetActor(guid int64) game.Actor {
return slf.actors.Get(guid) return slf.actors.Get(guid)
} }
func (slf *World[PlayerID]) GetActors() map[int64]game.Actor { func (slf *World[PlayerID, Player]) GetActors() map[int64]game.Actor {
return slf.actors.Map() return slf.actors.Map()
} }
func (slf *World[PlayerID]) GetPlayerActor(id PlayerID, guid int64) game.Actor { func (slf *World[PlayerID, Player]) GetPlayerActor(id PlayerID, guid int64) game.Actor {
if actors := slf.playerActors.Get(id); actors != nil { if actors := slf.playerActors.Get(id); actors != nil {
return actors.Get(guid) return actors.Get(guid)
} }
return nil return nil
} }
func (slf *World[PlayerID]) GetPlayerActors(id PlayerID) map[int64]game.Actor { func (slf *World[PlayerID, Player]) GetPlayerActors(id PlayerID) map[int64]game.Actor {
return slf.playerActors.Get(id).Map() return slf.playerActors.Get(id).Map()
} }
func (slf *World[PlayerID]) IsExistPlayer(id PlayerID) bool { func (slf *World[PlayerID, Player]) IsExistPlayer(id PlayerID) bool {
return slf.players.Exist(id) return slf.players.Exist(id)
} }
func (slf *World[PlayerID]) IsExistActor(guid int64) bool { func (slf *World[PlayerID, Player]) IsExistActor(guid int64) bool {
return slf.actors.Exist(guid) return slf.actors.Exist(guid)
} }
func (slf *World[PlayerID]) IsOwner(id PlayerID, guid int64) bool { func (slf *World[PlayerID, Player]) IsOwner(id PlayerID, guid int64) bool {
actors := slf.playerActors.Get(id) actors := slf.playerActors.Get(id)
if actors != nil { if actors != nil {
return actors.Exist(guid) return actors.Exist(guid)
@ -91,7 +97,7 @@ func (slf *World[PlayerID]) IsOwner(id PlayerID, guid int64) bool {
return false return false
} }
func (slf *World[PlayerID]) Join(player game.Player[PlayerID]) error { func (slf *World[PlayerID, Player]) Join(player Player) error {
if slf.released.Load() { if slf.released.Load() {
return ErrWorldReleased return ErrWorldReleased
} }
@ -103,12 +109,14 @@ func (slf *World[PlayerID]) Join(player game.Player[PlayerID]) error {
actors = synchronization.NewMap[int64, game.Actor]() actors = synchronization.NewMap[int64, game.Actor]()
slf.playerActors.Set(player.GetID(), actors) slf.playerActors.Set(player.GetID(), actors)
} }
slf.playersConn.Set(player.GetConnID(), player)
slf.OnPlayerJoinWorldEvent(player) slf.OnPlayerJoinWorldEvent(player)
return nil return nil
} }
func (slf *World[PlayerID]) Leave(player game.Player[PlayerID]) { func (slf *World[PlayerID, Player]) Leave(id PlayerID) {
if !slf.players.Exist(player.GetID()) { player, exist := slf.players.GetExist(id)
if !exist {
return return
} }
slf.OnPlayerLeaveWorldEvent(player) slf.OnPlayerLeaveWorldEvent(player)
@ -118,16 +126,17 @@ func (slf *World[PlayerID]) Leave(player game.Player[PlayerID]) {
}) })
slf.playerActors.Delete(player.GetID()) slf.playerActors.Delete(player.GetID())
slf.players.Delete(player.GetID()) slf.players.Delete(player.GetID())
slf.playersConn.Delete(player.GetConnID())
} }
func (slf *World[PlayerID]) AddActor(actor game.Actor) { func (slf *World[PlayerID, Player]) AddActor(actor game.Actor) {
guid := slf.actorGuid.Add(1) guid := slf.actorGuid.Add(1)
actor.SetGuid(guid) actor.SetGuid(guid)
slf.actors.Set(actor.GetGuid(), actor) slf.actors.Set(actor.GetGuid(), actor)
slf.OnActorGeneratedEvent(actor) slf.OnActorGeneratedEvent(actor)
} }
func (slf *World[PlayerID]) RemoveActor(guid int64) { func (slf *World[PlayerID, Player]) RemoveActor(guid int64) {
if actor, exist := slf.actors.GetExist(guid); exist { if actor, exist := slf.actors.GetExist(guid); exist {
slf.OnActorAnnihilationEvent(actor) slf.OnActorAnnihilationEvent(actor)
if id, exist := slf.owners.DeleteGetExist(guid); exist { if id, exist := slf.owners.DeleteGetExist(guid); exist {
@ -137,7 +146,7 @@ func (slf *World[PlayerID]) RemoveActor(guid int64) {
} }
} }
func (slf *World[PlayerID]) SetActorOwner(guid int64, id PlayerID) { func (slf *World[PlayerID, Player]) SetActorOwner(guid int64, id PlayerID) {
oldId, exist := slf.owners.GetExist(guid) oldId, exist := slf.owners.GetExist(guid)
if exist && oldId == id { if exist && oldId == id {
return return
@ -151,7 +160,7 @@ func (slf *World[PlayerID]) SetActorOwner(guid int64, id PlayerID) {
slf.OnActorOwnerChangeEvent(actor, oldId, id, false) slf.OnActorOwnerChangeEvent(actor, oldId, id, false)
} }
func (slf *World[PlayerID]) RemoveActorOwner(guid int64) { func (slf *World[PlayerID, Player]) RemoveActorOwner(guid int64) {
id, exist := slf.owners.GetExist(guid) id, exist := slf.owners.GetExist(guid)
if !exist { if !exist {
return return
@ -161,7 +170,7 @@ func (slf *World[PlayerID]) RemoveActorOwner(guid int64) {
slf.OnActorOwnerChangeEvent(slf.GetActor(guid), id, id, true) slf.OnActorOwnerChangeEvent(slf.GetActor(guid), id, id, true)
} }
func (slf *World[PlayerID]) Reset() { func (slf *World[PlayerID, Player]) Reset() {
slf.players.Clear() slf.players.Clear()
slf.playerActors.Range(func(id PlayerID, actors *synchronization.Map[int64, game.Actor]) { slf.playerActors.Range(func(id PlayerID, actors *synchronization.Map[int64, game.Actor]) {
actors.Clear() actors.Clear()
@ -170,10 +179,11 @@ func (slf *World[PlayerID]) Reset() {
slf.owners.Clear() slf.owners.Clear()
slf.actors.Clear() slf.actors.Clear()
slf.actorGuid.Store(0) slf.actorGuid.Store(0)
slf.playersConn.Clear()
slf.OnWorldResetEvent() slf.OnWorldResetEvent()
} }
func (slf *World[PlayerID]) Release() { func (slf *World[PlayerID, Player]) Release() {
if !slf.released.Swap(true) { if !slf.released.Swap(true) {
slf.OnWorldReleaseEvent() slf.OnWorldReleaseEvent()
slf.Reset() slf.Reset()
@ -190,71 +200,71 @@ func (slf *World[PlayerID]) Release() {
} }
} }
func (slf *World[PlayerID]) RegWorldResetEvent(handle game.WorldResetEventHandle[PlayerID]) { func (slf *World[PlayerID, Player]) RegWorldResetEvent(handle game.WorldResetEventHandle[PlayerID, Player]) {
slf.worldResetEventHandles = append(slf.worldResetEventHandles, handle) slf.worldResetEventHandles = append(slf.worldResetEventHandles, handle)
} }
func (slf *World[PlayerID]) OnWorldResetEvent() { func (slf *World[PlayerID, Player]) OnWorldResetEvent() {
for _, handle := range slf.worldResetEventHandles { for _, handle := range slf.worldResetEventHandles {
handle(slf) handle(slf)
} }
} }
func (slf *World[PlayerID]) RegWorldReleaseEvent(handle game.WorldReleaseEventHandle[PlayerID]) { func (slf *World[PlayerID, Player]) RegWorldReleaseEvent(handle game.WorldReleaseEventHandle[PlayerID, Player]) {
slf.worldReleasedEventHandles = append(slf.worldReleasedEventHandles, handle) slf.worldReleasedEventHandles = append(slf.worldReleasedEventHandles, handle)
} }
func (slf *World[PlayerID]) OnWorldReleaseEvent() { func (slf *World[PlayerID, Player]) OnWorldReleaseEvent() {
for _, handle := range slf.worldReleasedEventHandles { for _, handle := range slf.worldReleasedEventHandles {
handle(slf) handle(slf)
} }
} }
func (slf *World[PlayerID]) RegPlayerJoinWorldEvent(handle game.PlayerJoinWorldEventHandle[PlayerID]) { func (slf *World[PlayerID, Player]) RegPlayerJoinWorldEvent(handle game.PlayerJoinWorldEventHandle[PlayerID, Player]) {
slf.playerJoinWorldEventHandles = append(slf.playerJoinWorldEventHandles, handle) slf.playerJoinWorldEventHandles = append(slf.playerJoinWorldEventHandles, handle)
} }
func (slf *World[PlayerID]) OnPlayerJoinWorldEvent(player game.Player[PlayerID]) { func (slf *World[PlayerID, Player]) OnPlayerJoinWorldEvent(player Player) {
for _, handle := range slf.playerJoinWorldEventHandles { for _, handle := range slf.playerJoinWorldEventHandles {
handle(player) handle(player)
} }
} }
func (slf *World[PlayerID]) RegPlayerLeaveWorldEvent(handle game.PlayerLeaveWorldEventHandle[PlayerID]) { func (slf *World[PlayerID, Player]) RegPlayerLeaveWorldEvent(handle game.PlayerLeaveWorldEventHandle[PlayerID, Player]) {
slf.playerLeaveWorldEventHandles = append(slf.playerLeaveWorldEventHandles, handle) slf.playerLeaveWorldEventHandles = append(slf.playerLeaveWorldEventHandles, handle)
} }
func (slf *World[PlayerID]) OnPlayerLeaveWorldEvent(player game.Player[PlayerID]) { func (slf *World[PlayerID, Player]) OnPlayerLeaveWorldEvent(player Player) {
for _, handle := range slf.playerLeaveWorldEventHandles { for _, handle := range slf.playerLeaveWorldEventHandles {
handle(player) handle(player)
} }
} }
func (slf *World[PlayerID]) RegActorGeneratedEvent(handle game.ActorGeneratedEventHandle) { func (slf *World[PlayerID, Player]) RegActorGeneratedEvent(handle game.ActorGeneratedEventHandle) {
slf.actorGeneratedEventHandles = append(slf.actorGeneratedEventHandles, handle) slf.actorGeneratedEventHandles = append(slf.actorGeneratedEventHandles, handle)
} }
func (slf *World[PlayerID]) OnActorGeneratedEvent(actor game.Actor) { func (slf *World[PlayerID, Player]) OnActorGeneratedEvent(actor game.Actor) {
for _, handle := range slf.actorGeneratedEventHandles { for _, handle := range slf.actorGeneratedEventHandles {
handle(actor) handle(actor)
} }
} }
func (slf *World[PlayerID]) RegActorAnnihilationEvent(handle game.ActorAnnihilationEventHandle) { func (slf *World[PlayerID, Player]) RegActorAnnihilationEvent(handle game.ActorAnnihilationEventHandle) {
slf.actorAnnihilationEventHandles = append(slf.actorAnnihilationEventHandles, handle) slf.actorAnnihilationEventHandles = append(slf.actorAnnihilationEventHandles, handle)
} }
func (slf *World[PlayerID]) OnActorAnnihilationEvent(actor game.Actor) { func (slf *World[PlayerID, Player]) OnActorAnnihilationEvent(actor game.Actor) {
for _, handle := range slf.actorAnnihilationEventHandles { for _, handle := range slf.actorAnnihilationEventHandles {
handle(actor) handle(actor)
} }
} }
func (slf *World[PlayerID]) RegActorOwnerChangeEvent(handle game.ActorOwnerChangeEventHandle[PlayerID]) { func (slf *World[PlayerID, Player]) RegActorOwnerChangeEvent(handle game.ActorOwnerChangeEventHandle[PlayerID]) {
slf.actorOwnerChangeEventHandles = append(slf.actorOwnerChangeEventHandles, handle) slf.actorOwnerChangeEventHandles = append(slf.actorOwnerChangeEventHandles, handle)
} }
func (slf *World[PlayerID]) OnActorOwnerChangeEvent(actor game.Actor, old, new PlayerID, isolated bool) { func (slf *World[PlayerID, Player]) OnActorOwnerChangeEvent(actor game.Actor, old, new PlayerID, isolated bool) {
for _, handle := range slf.actorOwnerChangeEventHandles { for _, handle := range slf.actorOwnerChangeEventHandles {
handle(actor, old, new, isolated) handle(actor, old, new, isolated)
} }

View File

@ -1,9 +1,11 @@
package builtin package builtin
type WorldOption[PlayerID comparable] func(world *World[PlayerID]) import "minotaur/game"
func WithWorldPlayerLimit[PlayerID comparable](playerLimit int) WorldOption[PlayerID] { type WorldOption[PlayerID comparable, Player game.Player[PlayerID]] func(world *World[PlayerID, Player])
return func(world *World[PlayerID]) {
func WithWorldPlayerLimit[PlayerID comparable, Player game.Player[PlayerID]](playerLimit int) WorldOption[PlayerID, Player] {
return func(world *World[PlayerID, Player]) {
world.playerLimit = playerLimit world.playerLimit = playerLimit
} }
} }

View File

@ -4,6 +4,8 @@ package game
type Player[ID comparable] interface { type Player[ID comparable] interface {
// GetID 用户玩家ID // GetID 用户玩家ID
GetID() ID GetID() ID
// GetConnID 获取连接ID
GetConnID() string
// Send 发送数据包 // Send 发送数据包
Send(packet []byte) error Send(packet []byte) error
// Close 关闭玩家并且释放其资源 // Close 关闭玩家并且释放其资源

View File

@ -1,15 +1,17 @@
package game package game
// World 游戏世界接口定义 // World 游戏世界接口定义
type World[PlayerID comparable] interface { type World[PlayerID comparable, P Player[PlayerID]] interface {
// GetGuid 获取世界的唯一标识符 // GetGuid 获取世界的唯一标识符
GetGuid() int64 GetGuid() int64
// GetPlayerLimit 获取玩家人数上限 // GetPlayerLimit 获取玩家人数上限
GetPlayerLimit() int GetPlayerLimit() int
// GetPlayerWithConnID 根据连接ID获取玩家
GetPlayerWithConnID(id string) P
// GetPlayer 根据玩家id获取玩家 // GetPlayer 根据玩家id获取玩家
GetPlayer(id PlayerID) Player[PlayerID] GetPlayer(id PlayerID) P
// GetPlayers 获取世界中的所有玩家 // GetPlayers 获取世界中的所有玩家
GetPlayers() map[PlayerID]Player[PlayerID] GetPlayers() map[PlayerID]P
// GetActor 根据唯一标识符获取世界中的游戏对象 // GetActor 根据唯一标识符获取世界中的游戏对象
GetActor(guid int64) Actor GetActor(guid int64) Actor
// GetActors 获取世界中的所有游戏对象 // GetActors 获取世界中的所有游戏对象
@ -26,9 +28,9 @@ type World[PlayerID comparable] interface {
IsOwner(id PlayerID, guid int64) bool IsOwner(id PlayerID, guid int64) bool
// Join 使特定玩家加入游戏世界 // Join 使特定玩家加入游戏世界
Join(player Player[PlayerID]) error Join(player P) error
// Leave 使特定玩家离开游戏世界 // Leave 使特定玩家离开游戏世界
Leave(player Player[PlayerID]) Leave(id PlayerID)
// AddActor 添加游戏对象 // AddActor 添加游戏对象
AddActor(actor Actor) AddActor(actor Actor)
@ -45,17 +47,17 @@ type World[PlayerID comparable] interface {
Release() Release()
// RegWorldResetEvent 世界被重置后将立即执行被注册的事件处理函数 // RegWorldResetEvent 世界被重置后将立即执行被注册的事件处理函数
RegWorldResetEvent(handle WorldResetEventHandle[PlayerID]) RegWorldResetEvent(handle WorldResetEventHandle[PlayerID, P])
OnWorldResetEvent() OnWorldResetEvent()
// RegWorldReleaseEvent 直接被释放前将立即执行被注册的事件处理函数,此刻世界仍然可用 // RegWorldReleaseEvent 直接被释放前将立即执行被注册的事件处理函数,此刻世界仍然可用
RegWorldReleaseEvent(handle WorldReleaseEventHandle[PlayerID]) RegWorldReleaseEvent(handle WorldReleaseEventHandle[PlayerID, P])
OnWorldReleaseEvent() OnWorldReleaseEvent()
// RegPlayerJoinWorldEvent 玩家进入世界时将立即执行被注册的事件处理函数 // RegPlayerJoinWorldEvent 玩家进入世界时将立即执行被注册的事件处理函数
RegPlayerJoinWorldEvent(handle PlayerJoinWorldEventHandle[PlayerID]) RegPlayerJoinWorldEvent(handle PlayerJoinWorldEventHandle[PlayerID, P])
OnPlayerJoinWorldEvent(player Player[PlayerID]) OnPlayerJoinWorldEvent(player P)
// RegPlayerLeaveWorldEvent 玩家离开世界时将立即执行被注册的事件处理函数 // RegPlayerLeaveWorldEvent 玩家离开世界时将立即执行被注册的事件处理函数
RegPlayerLeaveWorldEvent(handle PlayerLeaveWorldEventHandle[PlayerID]) RegPlayerLeaveWorldEvent(handle PlayerLeaveWorldEventHandle[PlayerID, P])
OnPlayerLeaveWorldEvent(player Player[PlayerID]) OnPlayerLeaveWorldEvent(player P)
// RegActorGeneratedEvent 游戏世界中的游戏对象生成完成时将立即执行被注册的事件处理函数 // RegActorGeneratedEvent 游戏世界中的游戏对象生成完成时将立即执行被注册的事件处理函数
RegActorGeneratedEvent(handle ActorGeneratedEventHandle) RegActorGeneratedEvent(handle ActorGeneratedEventHandle)
OnActorGeneratedEvent(actor Actor) OnActorGeneratedEvent(actor Actor)
@ -68,11 +70,11 @@ type World[PlayerID comparable] interface {
} }
type ( type (
WorldResetEventHandle[ID comparable] func(world World[ID]) WorldResetEventHandle[ID comparable, P Player[ID]] func(world World[ID, P])
WorldReleaseEventHandle[ID comparable] func(world World[ID]) WorldReleaseEventHandle[ID comparable, P Player[ID]] func(world World[ID, P])
PlayerJoinWorldEventHandle[ID comparable] func(player Player[ID]) PlayerJoinWorldEventHandle[ID comparable, P Player[ID]] func(player P)
PlayerLeaveWorldEventHandle[ID comparable] func(player Player[ID]) PlayerLeaveWorldEventHandle[ID comparable, P Player[ID]] func(player P)
ActorGeneratedEventHandle func(actor Actor) ActorGeneratedEventHandle func(actor Actor)
ActorAnnihilationEventHandle func(actor Actor) ActorAnnihilationEventHandle func(actor Actor)
ActorOwnerChangeEventHandle[ID comparable] func(actor Actor, old, new ID, isolated bool) ActorOwnerChangeEventHandle[ID comparable] func(actor Actor, old, new ID, isolated bool)
) )

View File

@ -32,6 +32,7 @@ func newGNetConn(conn gnet.Conn) *Conn {
// newKcpConn 创建一个处理WebSocket的连接 // newKcpConn 创建一个处理WebSocket的连接
func newWebsocketConn(ws *websocket.Conn) *Conn { func newWebsocketConn(ws *websocket.Conn) *Conn {
return &Conn{ return &Conn{
ip: ws.RemoteAddr().String(),
ws: ws, ws: ws,
write: func(data []byte) error { write: func(data []byte) error {
return ws.WriteMessage(websocket.BinaryMessage, data) return ws.WriteMessage(websocket.BinaryMessage, data)
@ -49,6 +50,10 @@ type Conn struct {
data map[any]any data map[any]any
} }
func (slf *Conn) GetID() string {
return slf.ip
}
// Write 向连接中写入数据 // Write 向连接中写入数据
func (slf *Conn) Write(data []byte) error { func (slf *Conn) Write(data []byte) error {
return slf.write(data) return slf.write(data)

View File

@ -56,6 +56,7 @@ func (slf *event) RegConnectionClosedEvent(handle ConnectionClosedEventHandle) {
} }
func (slf *event) OnConnectionClosedEvent(conn *Conn) { func (slf *event) OnConnectionClosedEvent(conn *Conn) {
slf.Server.connections.Delete(conn.ip)
for _, handle := range slf.connectionClosedEventHandles { for _, handle := range slf.connectionClosedEventHandles {
handle(conn) handle(conn)
} }
@ -71,6 +72,7 @@ func (slf *event) RegConnectionOpenedEvent(handle ConnectionOpenedEventHandle) {
} }
func (slf *event) OnConnectionOpenedEvent(conn *Conn) { func (slf *event) OnConnectionOpenedEvent(conn *Conn) {
slf.Server.connections.Set(conn.ip, conn)
for _, handle := range slf.connectionOpenedEventHandles { for _, handle := range slf.connectionOpenedEventHandles {
handle(conn) handle(conn)
} }

View File

@ -9,6 +9,7 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
"google.golang.org/grpc" "google.golang.org/grpc"
"minotaur/utils/log" "minotaur/utils/log"
"minotaur/utils/synchronization"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -37,8 +38,9 @@ func New(network Network, options ...Option) *Server {
// Server 网络服务器 // Server 网络服务器
type Server struct { type Server struct {
*event *event
network Network // 网络类型 network Network // 网络类型
addr string // 侦听地址 addr string // 侦听地址
connections *synchronization.Map[string, *Conn]
httpServer *gin.Engine // HTTP模式下的服务器 httpServer *gin.Engine // HTTP模式下的服务器
grpcServer *grpc.Server // GRPC模式下的服务器 grpcServer *grpc.Server // GRPC模式下的服务器
gServer *gNet // TCP或UDP模式下的服务器 gServer *gNet // TCP或UDP模式下的服务器
@ -68,6 +70,7 @@ func (slf *Server) Run(addr string) error {
slf.addr = addr slf.addr = addr
var protoAddr = fmt.Sprintf("%s://%s", slf.network, slf.addr) var protoAddr = fmt.Sprintf("%s://%s", slf.network, slf.addr)
var connectionInitHandle = func(callback func()) { var connectionInitHandle = func(callback func()) {
slf.connections = synchronization.NewMap[string, *Conn]()
slf.initMessageChannel = true slf.initMessageChannel = true
slf.messageChannel = make(chan *message, 4096*1000) slf.messageChannel = make(chan *message, 4096*1000)
if slf.network != NetworkHttp && slf.network != NetworkWebsocket { if slf.network != NetworkHttp && slf.network != NetworkWebsocket {
@ -176,7 +179,6 @@ func (slf *Server) Run(addr string) error {
} }
conn := newWebsocketConn(ws) conn := newWebsocketConn(ws)
conn.ip = ip
slf.OnConnectionOpenedEvent(conn) slf.OnConnectionOpenedEvent(conn)
defer func() { defer func() {
@ -237,6 +239,11 @@ func (slf *Server) IsProd() bool {
// Shutdown 停止运行服务器 // Shutdown 停止运行服务器
func (slf *Server) Shutdown(err error) { func (slf *Server) Shutdown(err error) {
if slf.connections != nil {
slf.connections.Range(func(connId string, conn *Conn) {
conn.Close()
})
}
if slf.initMessageChannel { if slf.initMessageChannel {
close(slf.messageChannel) close(slf.messageChannel)
} }