简单游戏demo实现
This commit is contained in:
parent
a722ef46e2
commit
723e618df2
|
@ -0,0 +1 @@
|
||||||
|
简单游戏实现demo
|
|
@ -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]
|
||||||
|
}
|
|
@ -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")
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 关闭玩家并且释放其资源
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue