diff --git a/game/builtin/examples/game/README.md b/game/builtin/examples/game/README.md new file mode 100644 index 0000000..7f81c6f --- /dev/null +++ b/game/builtin/examples/game/README.md @@ -0,0 +1 @@ +简单游戏实现demo \ No newline at end of file diff --git a/game/builtin/examples/game/game/app.go b/game/builtin/examples/game/game/app.go new file mode 100644 index 0000000..7be3dd6 --- /dev/null +++ b/game/builtin/examples/game/game/app.go @@ -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] +} diff --git a/game/builtin/examples/game/game/player.go b/game/builtin/examples/game/game/player.go new file mode 100644 index 0000000..4d8093c --- /dev/null +++ b/game/builtin/examples/game/game/player.go @@ -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") +} diff --git a/game/builtin/examples/game/game/server.go b/game/builtin/examples/game/game/server.go new file mode 100644 index 0000000..507af65 --- /dev/null +++ b/game/builtin/examples/game/game/server.go @@ -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) + } +} diff --git a/game/builtin/examples/game/main.go b/game/builtin/examples/game/main.go new file mode 100644 index 0000000..d42af78 --- /dev/null +++ b/game/builtin/examples/game/main.go @@ -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) + } +} diff --git a/game/builtin/player.go b/game/builtin/player.go index 24e85e4..05e3f27 100644 --- a/game/builtin/player.go +++ b/game/builtin/player.go @@ -19,6 +19,10 @@ func (slf *Player[ID]) GetID() ID { return slf.id } +func (slf *Player[ID]) GetConnID() string { + return slf.conn.GetID() +} + // Send 向该玩家发送数据 func (slf *Player[ID]) Send(packet []byte) error { return slf.conn.Write(packet) diff --git a/game/builtin/world.go b/game/builtin/world.go index cea57b5..2a875b1 100644 --- a/game/builtin/world.go +++ b/game/builtin/world.go @@ -6,10 +6,11 @@ import ( "sync/atomic" ) -func NewWorld[PlayerID comparable](guid int64, options ...WorldOption[PlayerID]) *World[PlayerID] { - world := &World[PlayerID]{ +func NewWorld[PlayerID comparable, Player game.Player[PlayerID]](guid int64, options ...WorldOption[PlayerID, Player]) *World[PlayerID, Player] { + world := &World[PlayerID, Player]{ 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]](), owners: synchronization.NewMap[int64, PlayerID](), actors: synchronization.NewMap[int64, game.Actor](), @@ -20,70 +21,75 @@ func NewWorld[PlayerID comparable](guid int64, options ...WorldOption[PlayerID]) return world } -type World[PlayerID comparable] struct { +type World[PlayerID comparable, Player game.Player[PlayerID]] struct { guid int64 actorGuid atomic.Int64 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]] owners *synchronization.Map[int64, PlayerID] actors *synchronization.Map[int64, game.Actor] - playerJoinWorldEventHandles []game.PlayerJoinWorldEventHandle[PlayerID] - playerLeaveWorldEventHandles []game.PlayerLeaveWorldEventHandle[PlayerID] + playerJoinWorldEventHandles []game.PlayerJoinWorldEventHandle[PlayerID, Player] + playerLeaveWorldEventHandles []game.PlayerLeaveWorldEventHandle[PlayerID, Player] actorGeneratedEventHandles []game.ActorGeneratedEventHandle actorAnnihilationEventHandles []game.ActorAnnihilationEventHandle actorOwnerChangeEventHandles []game.ActorOwnerChangeEventHandle[PlayerID] - worldResetEventHandles []game.WorldResetEventHandle[PlayerID] - worldReleasedEventHandles []game.WorldReleaseEventHandle[PlayerID] + worldResetEventHandles []game.WorldResetEventHandle[PlayerID, Player] + worldReleasedEventHandles []game.WorldReleaseEventHandle[PlayerID, Player] released atomic.Bool } -func (slf *World[PlayerID]) GetGuid() int64 { +func (slf *World[PlayerID, Player]) GetGuid() int64 { return slf.guid } -func (slf *World[PlayerID]) GetPlayerLimit() int { +func (slf *World[PlayerID, Player]) GetPlayerLimit() int { 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) } -func (slf *World[PlayerID]) GetPlayers() map[PlayerID]game.Player[PlayerID] { +func (slf *World[PlayerID, Player]) GetPlayers() map[PlayerID]Player { 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) } -func (slf *World[PlayerID]) GetActors() map[int64]game.Actor { +func (slf *World[PlayerID, Player]) GetActors() map[int64]game.Actor { 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 { return actors.Get(guid) } 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() } -func (slf *World[PlayerID]) IsExistPlayer(id PlayerID) bool { +func (slf *World[PlayerID, Player]) IsExistPlayer(id PlayerID) bool { 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) } -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) if actors != nil { return actors.Exist(guid) @@ -91,7 +97,7 @@ func (slf *World[PlayerID]) IsOwner(id PlayerID, guid int64) bool { 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() { return ErrWorldReleased } @@ -103,12 +109,14 @@ func (slf *World[PlayerID]) Join(player game.Player[PlayerID]) error { actors = synchronization.NewMap[int64, game.Actor]() slf.playerActors.Set(player.GetID(), actors) } + slf.playersConn.Set(player.GetConnID(), player) slf.OnPlayerJoinWorldEvent(player) return nil } -func (slf *World[PlayerID]) Leave(player game.Player[PlayerID]) { - if !slf.players.Exist(player.GetID()) { +func (slf *World[PlayerID, Player]) Leave(id PlayerID) { + player, exist := slf.players.GetExist(id) + if !exist { return } slf.OnPlayerLeaveWorldEvent(player) @@ -118,16 +126,17 @@ func (slf *World[PlayerID]) Leave(player game.Player[PlayerID]) { }) slf.playerActors.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) actor.SetGuid(guid) slf.actors.Set(actor.GetGuid(), 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 { slf.OnActorAnnihilationEvent(actor) 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) if exist && oldId == id { return @@ -151,7 +160,7 @@ func (slf *World[PlayerID]) SetActorOwner(guid int64, id PlayerID) { 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) if !exist { return @@ -161,7 +170,7 @@ func (slf *World[PlayerID]) RemoveActorOwner(guid int64) { slf.OnActorOwnerChangeEvent(slf.GetActor(guid), id, id, true) } -func (slf *World[PlayerID]) Reset() { +func (slf *World[PlayerID, Player]) Reset() { slf.players.Clear() slf.playerActors.Range(func(id PlayerID, actors *synchronization.Map[int64, game.Actor]) { actors.Clear() @@ -170,10 +179,11 @@ func (slf *World[PlayerID]) Reset() { slf.owners.Clear() slf.actors.Clear() slf.actorGuid.Store(0) + slf.playersConn.Clear() slf.OnWorldResetEvent() } -func (slf *World[PlayerID]) Release() { +func (slf *World[PlayerID, Player]) Release() { if !slf.released.Swap(true) { slf.OnWorldReleaseEvent() 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) } -func (slf *World[PlayerID]) OnWorldResetEvent() { +func (slf *World[PlayerID, Player]) OnWorldResetEvent() { for _, handle := range slf.worldResetEventHandles { 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) } -func (slf *World[PlayerID]) OnWorldReleaseEvent() { +func (slf *World[PlayerID, Player]) OnWorldReleaseEvent() { for _, handle := range slf.worldReleasedEventHandles { 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) } -func (slf *World[PlayerID]) OnPlayerJoinWorldEvent(player game.Player[PlayerID]) { +func (slf *World[PlayerID, Player]) OnPlayerJoinWorldEvent(player Player) { for _, handle := range slf.playerJoinWorldEventHandles { 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) } -func (slf *World[PlayerID]) OnPlayerLeaveWorldEvent(player game.Player[PlayerID]) { +func (slf *World[PlayerID, Player]) OnPlayerLeaveWorldEvent(player Player) { for _, handle := range slf.playerLeaveWorldEventHandles { 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) } -func (slf *World[PlayerID]) OnActorGeneratedEvent(actor game.Actor) { +func (slf *World[PlayerID, Player]) OnActorGeneratedEvent(actor game.Actor) { for _, handle := range slf.actorGeneratedEventHandles { 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) } -func (slf *World[PlayerID]) OnActorAnnihilationEvent(actor game.Actor) { +func (slf *World[PlayerID, Player]) OnActorAnnihilationEvent(actor game.Actor) { for _, handle := range slf.actorAnnihilationEventHandles { 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) } -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 { handle(actor, old, new, isolated) } diff --git a/game/builtin/world_options.go b/game/builtin/world_options.go index 1502b4d..739bdd1 100644 --- a/game/builtin/world_options.go +++ b/game/builtin/world_options.go @@ -1,9 +1,11 @@ package builtin -type WorldOption[PlayerID comparable] func(world *World[PlayerID]) +import "minotaur/game" -func WithWorldPlayerLimit[PlayerID comparable](playerLimit int) WorldOption[PlayerID] { - return func(world *World[PlayerID]) { +type WorldOption[PlayerID comparable, Player game.Player[PlayerID]] func(world *World[PlayerID, Player]) + +func WithWorldPlayerLimit[PlayerID comparable, Player game.Player[PlayerID]](playerLimit int) WorldOption[PlayerID, Player] { + return func(world *World[PlayerID, Player]) { world.playerLimit = playerLimit } } diff --git a/game/player.go b/game/player.go index 1762a84..a9eff3c 100644 --- a/game/player.go +++ b/game/player.go @@ -4,6 +4,8 @@ package game type Player[ID comparable] interface { // GetID 用户玩家ID GetID() ID + // GetConnID 获取连接ID + GetConnID() string // Send 发送数据包 Send(packet []byte) error // Close 关闭玩家并且释放其资源 diff --git a/game/world.go b/game/world.go index 77ae269..14a994f 100644 --- a/game/world.go +++ b/game/world.go @@ -1,15 +1,17 @@ package game // World 游戏世界接口定义 -type World[PlayerID comparable] interface { +type World[PlayerID comparable, P Player[PlayerID]] interface { // GetGuid 获取世界的唯一标识符 GetGuid() int64 // GetPlayerLimit 获取玩家人数上限 GetPlayerLimit() int + // GetPlayerWithConnID 根据连接ID获取玩家 + GetPlayerWithConnID(id string) P // GetPlayer 根据玩家id获取玩家 - GetPlayer(id PlayerID) Player[PlayerID] + GetPlayer(id PlayerID) P // GetPlayers 获取世界中的所有玩家 - GetPlayers() map[PlayerID]Player[PlayerID] + GetPlayers() map[PlayerID]P // GetActor 根据唯一标识符获取世界中的游戏对象 GetActor(guid int64) Actor // GetActors 获取世界中的所有游戏对象 @@ -26,9 +28,9 @@ type World[PlayerID comparable] interface { IsOwner(id PlayerID, guid int64) bool // Join 使特定玩家加入游戏世界 - Join(player Player[PlayerID]) error + Join(player P) error // Leave 使特定玩家离开游戏世界 - Leave(player Player[PlayerID]) + Leave(id PlayerID) // AddActor 添加游戏对象 AddActor(actor Actor) @@ -45,17 +47,17 @@ type World[PlayerID comparable] interface { Release() // RegWorldResetEvent 世界被重置后将立即执行被注册的事件处理函数 - RegWorldResetEvent(handle WorldResetEventHandle[PlayerID]) + RegWorldResetEvent(handle WorldResetEventHandle[PlayerID, P]) OnWorldResetEvent() // RegWorldReleaseEvent 直接被释放前将立即执行被注册的事件处理函数,此刻世界仍然可用 - RegWorldReleaseEvent(handle WorldReleaseEventHandle[PlayerID]) + RegWorldReleaseEvent(handle WorldReleaseEventHandle[PlayerID, P]) OnWorldReleaseEvent() // RegPlayerJoinWorldEvent 玩家进入世界时将立即执行被注册的事件处理函数 - RegPlayerJoinWorldEvent(handle PlayerJoinWorldEventHandle[PlayerID]) - OnPlayerJoinWorldEvent(player Player[PlayerID]) + RegPlayerJoinWorldEvent(handle PlayerJoinWorldEventHandle[PlayerID, P]) + OnPlayerJoinWorldEvent(player P) // RegPlayerLeaveWorldEvent 玩家离开世界时将立即执行被注册的事件处理函数 - RegPlayerLeaveWorldEvent(handle PlayerLeaveWorldEventHandle[PlayerID]) - OnPlayerLeaveWorldEvent(player Player[PlayerID]) + RegPlayerLeaveWorldEvent(handle PlayerLeaveWorldEventHandle[PlayerID, P]) + OnPlayerLeaveWorldEvent(player P) // RegActorGeneratedEvent 游戏世界中的游戏对象生成完成时将立即执行被注册的事件处理函数 RegActorGeneratedEvent(handle ActorGeneratedEventHandle) OnActorGeneratedEvent(actor Actor) @@ -68,11 +70,11 @@ type World[PlayerID comparable] interface { } type ( - WorldResetEventHandle[ID comparable] func(world World[ID]) - WorldReleaseEventHandle[ID comparable] func(world World[ID]) - PlayerJoinWorldEventHandle[ID comparable] func(player Player[ID]) - PlayerLeaveWorldEventHandle[ID comparable] func(player Player[ID]) - ActorGeneratedEventHandle func(actor Actor) - ActorAnnihilationEventHandle func(actor Actor) - ActorOwnerChangeEventHandle[ID comparable] func(actor Actor, old, new ID, isolated bool) + WorldResetEventHandle[ID comparable, P Player[ID]] func(world World[ID, P]) + WorldReleaseEventHandle[ID comparable, P Player[ID]] func(world World[ID, P]) + PlayerJoinWorldEventHandle[ID comparable, P Player[ID]] func(player P) + PlayerLeaveWorldEventHandle[ID comparable, P Player[ID]] func(player P) + ActorGeneratedEventHandle func(actor Actor) + ActorAnnihilationEventHandle func(actor Actor) + ActorOwnerChangeEventHandle[ID comparable] func(actor Actor, old, new ID, isolated bool) ) diff --git a/server/conn.go b/server/conn.go index 89f951a..2bc2c8c 100644 --- a/server/conn.go +++ b/server/conn.go @@ -32,6 +32,7 @@ func newGNetConn(conn gnet.Conn) *Conn { // newKcpConn 创建一个处理WebSocket的连接 func newWebsocketConn(ws *websocket.Conn) *Conn { return &Conn{ + ip: ws.RemoteAddr().String(), ws: ws, write: func(data []byte) error { return ws.WriteMessage(websocket.BinaryMessage, data) @@ -49,6 +50,10 @@ type Conn struct { data map[any]any } +func (slf *Conn) GetID() string { + return slf.ip +} + // Write 向连接中写入数据 func (slf *Conn) Write(data []byte) error { return slf.write(data) diff --git a/server/event.go b/server/event.go index 59171d0..dd47c2f 100644 --- a/server/event.go +++ b/server/event.go @@ -56,6 +56,7 @@ func (slf *event) RegConnectionClosedEvent(handle ConnectionClosedEventHandle) { } func (slf *event) OnConnectionClosedEvent(conn *Conn) { + slf.Server.connections.Delete(conn.ip) for _, handle := range slf.connectionClosedEventHandles { handle(conn) } @@ -71,6 +72,7 @@ func (slf *event) RegConnectionOpenedEvent(handle ConnectionOpenedEventHandle) { } func (slf *event) OnConnectionOpenedEvent(conn *Conn) { + slf.Server.connections.Set(conn.ip, conn) for _, handle := range slf.connectionOpenedEventHandles { handle(conn) } diff --git a/server/server.go b/server/server.go index dff8f54..10f9d8e 100644 --- a/server/server.go +++ b/server/server.go @@ -9,6 +9,7 @@ import ( "go.uber.org/zap" "google.golang.org/grpc" "minotaur/utils/log" + "minotaur/utils/synchronization" "net" "net/http" "os" @@ -37,8 +38,9 @@ func New(network Network, options ...Option) *Server { // Server 网络服务器 type Server struct { *event - network Network // 网络类型 - addr string // 侦听地址 + network Network // 网络类型 + addr string // 侦听地址 + connections *synchronization.Map[string, *Conn] httpServer *gin.Engine // HTTP模式下的服务器 grpcServer *grpc.Server // GRPC模式下的服务器 gServer *gNet // TCP或UDP模式下的服务器 @@ -68,6 +70,7 @@ func (slf *Server) Run(addr string) error { slf.addr = addr var protoAddr = fmt.Sprintf("%s://%s", slf.network, slf.addr) var connectionInitHandle = func(callback func()) { + slf.connections = synchronization.NewMap[string, *Conn]() slf.initMessageChannel = true slf.messageChannel = make(chan *message, 4096*1000) if slf.network != NetworkHttp && slf.network != NetworkWebsocket { @@ -176,7 +179,6 @@ func (slf *Server) Run(addr string) error { } conn := newWebsocketConn(ws) - conn.ip = ip slf.OnConnectionOpenedEvent(conn) defer func() { @@ -237,6 +239,11 @@ func (slf *Server) IsProd() bool { // Shutdown 停止运行服务器 func (slf *Server) Shutdown(err error) { + if slf.connections != nil { + slf.connections.Range(func(connId string, conn *Conn) { + conn.Close() + }) + } if slf.initMessageChannel { close(slf.messageChannel) }