Files
vRp.CD2g_test/game/builtin/world.go
T
2023-04-25 17:28:37 +08:00

262 lines
7.5 KiB
Go

package builtin
import (
"minotaur/game"
"minotaur/utils/synchronization"
"sync/atomic"
)
func NewWorld[PlayerID comparable](guid int64, options ...WorldOption[PlayerID]) *World[PlayerID] {
world := &World[PlayerID]{
guid: guid,
players: synchronization.NewMap[PlayerID, game.Player[PlayerID]](),
playerActors: synchronization.NewMap[PlayerID, *synchronization.Map[int64, game.Actor]](),
owners: synchronization.NewMap[int64, PlayerID](),
actors: synchronization.NewMap[int64, game.Actor](),
}
for _, option := range options {
option(world)
}
return world
}
type World[PlayerID comparable] struct {
guid int64
actorGuid atomic.Int64
playerLimit int
players *synchronization.Map[PlayerID, game.Player[PlayerID]]
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]
actorGeneratedEventHandles []game.ActorGeneratedEventHandle
actorAnnihilationEventHandles []game.ActorAnnihilationEventHandle
actorOwnerChangeEventHandles []game.ActorOwnerChangeEventHandle[PlayerID]
worldResetEventHandles []game.WorldResetEventHandle[PlayerID]
worldReleasedEventHandles []game.WorldReleaseEventHandle[PlayerID]
released atomic.Bool
}
func (slf *World[PlayerID]) GetGuid() int64 {
return slf.guid
}
func (slf *World[PlayerID]) GetPlayerLimit() int {
return slf.playerLimit
}
func (slf *World[PlayerID]) GetPlayer(id PlayerID) game.Player[PlayerID] {
return slf.players.Get(id)
}
func (slf *World[PlayerID]) GetPlayers() map[PlayerID]game.Player[PlayerID] {
return slf.players.Map()
}
func (slf *World[PlayerID]) GetActor(guid int64) game.Actor {
return slf.actors.Get(guid)
}
func (slf *World[PlayerID]) GetActors() map[int64]game.Actor {
return slf.actors.Map()
}
func (slf *World[PlayerID]) 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 {
return slf.playerActors.Get(id).Map()
}
func (slf *World[PlayerID]) IsExistPlayer(id PlayerID) bool {
return slf.players.Exist(id)
}
func (slf *World[PlayerID]) IsExistActor(guid int64) bool {
return slf.actors.Exist(guid)
}
func (slf *World[PlayerID]) IsOwner(id PlayerID, guid int64) bool {
actors := slf.playerActors.Get(id)
if actors != nil {
return actors.Exist(guid)
}
return false
}
func (slf *World[PlayerID]) Join(player game.Player[PlayerID]) error {
if slf.released.Load() {
return ErrWorldReleased
}
if slf.players.Size() >= slf.playerLimit && slf.playerLimit > 0 {
return ErrWorldPlayerLimit
}
slf.players.Set(player.GetID(), player)
if actors := slf.playerActors.Get(player.GetID()); actors == nil {
actors = synchronization.NewMap[int64, game.Actor]()
slf.playerActors.Set(player.GetID(), actors)
}
slf.OnPlayerJoinWorldEvent(player)
return nil
}
func (slf *World[PlayerID]) Leave(player game.Player[PlayerID]) {
if !slf.players.Exist(player.GetID()) {
return
}
slf.OnPlayerLeaveWorldEvent(player)
slf.playerActors.Get(player.GetID()).Range(func(guid int64, actor game.Actor) {
slf.OnActorAnnihilationEvent(actor)
slf.owners.Delete(guid)
})
slf.playerActors.Delete(player.GetID())
slf.players.Delete(player.GetID())
}
func (slf *World[PlayerID]) 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) {
if actor, exist := slf.actors.GetExist(guid); exist {
slf.OnActorAnnihilationEvent(actor)
if id, exist := slf.owners.DeleteGetExist(guid); exist {
slf.playerActors.Get(id).Delete(guid)
}
slf.actors.Delete(guid)
}
}
func (slf *World[PlayerID]) SetActorOwner(guid int64, id PlayerID) {
oldId, exist := slf.owners.GetExist(guid)
if exist && oldId == id {
return
}
actor := slf.GetActor(guid)
if actor == nil {
return
}
slf.owners.Set(guid, id)
slf.playerActors.Get(id).Set(guid, actor)
slf.OnActorOwnerChangeEvent(actor, oldId, id, false)
}
func (slf *World[PlayerID]) RemoveActorOwner(guid int64) {
id, exist := slf.owners.GetExist(guid)
if !exist {
return
}
slf.owners.Delete(guid)
slf.playerActors.Get(id).Delete(guid)
slf.OnActorOwnerChangeEvent(slf.GetActor(guid), id, id, true)
}
func (slf *World[PlayerID]) Reset() {
slf.players.Clear()
slf.playerActors.Range(func(id PlayerID, actors *synchronization.Map[int64, game.Actor]) {
actors.Clear()
})
slf.playerActors.Clear()
slf.owners.Clear()
slf.actors.Clear()
slf.actorGuid.Store(0)
slf.OnWorldResetEvent()
}
func (slf *World[PlayerID]) Release() {
if !slf.released.Swap(true) {
slf.OnWorldReleaseEvent()
slf.Reset()
slf.players = nil
slf.playerActors = nil
slf.owners = nil
slf.actors = nil
slf.playerJoinWorldEventHandles = nil
slf.playerLeaveWorldEventHandles = nil
slf.actorGeneratedEventHandles = nil
slf.actorAnnihilationEventHandles = nil
slf.actorOwnerChangeEventHandles = nil
}
}
func (slf *World[PlayerID]) RegWorldResetEvent(handle game.WorldResetEventHandle[PlayerID]) {
slf.worldResetEventHandles = append(slf.worldResetEventHandles, handle)
}
func (slf *World[PlayerID]) OnWorldResetEvent() {
for _, handle := range slf.worldResetEventHandles {
handle(slf)
}
}
func (slf *World[PlayerID]) RegWorldReleaseEvent(handle game.WorldReleaseEventHandle[PlayerID]) {
slf.worldReleasedEventHandles = append(slf.worldReleasedEventHandles, handle)
}
func (slf *World[PlayerID]) OnWorldReleaseEvent() {
for _, handle := range slf.worldReleasedEventHandles {
handle(slf)
}
}
func (slf *World[PlayerID]) RegPlayerJoinWorldEvent(handle game.PlayerJoinWorldEventHandle[PlayerID]) {
slf.playerJoinWorldEventHandles = append(slf.playerJoinWorldEventHandles, handle)
}
func (slf *World[PlayerID]) OnPlayerJoinWorldEvent(player game.Player[PlayerID]) {
for _, handle := range slf.playerJoinWorldEventHandles {
handle(player)
}
}
func (slf *World[PlayerID]) RegPlayerLeaveWorldEvent(handle game.PlayerLeaveWorldEventHandle[PlayerID]) {
slf.playerLeaveWorldEventHandles = append(slf.playerLeaveWorldEventHandles, handle)
}
func (slf *World[PlayerID]) OnPlayerLeaveWorldEvent(player game.Player[PlayerID]) {
for _, handle := range slf.playerLeaveWorldEventHandles {
handle(player)
}
}
func (slf *World[PlayerID]) RegActorGeneratedEvent(handle game.ActorGeneratedEventHandle) {
slf.actorGeneratedEventHandles = append(slf.actorGeneratedEventHandles, handle)
}
func (slf *World[PlayerID]) OnActorGeneratedEvent(actor game.Actor) {
for _, handle := range slf.actorGeneratedEventHandles {
handle(actor)
}
}
func (slf *World[PlayerID]) RegActorAnnihilationEvent(handle game.ActorAnnihilationEventHandle) {
slf.actorAnnihilationEventHandles = append(slf.actorAnnihilationEventHandles, handle)
}
func (slf *World[PlayerID]) OnActorAnnihilationEvent(actor game.Actor) {
for _, handle := range slf.actorAnnihilationEventHandles {
handle(actor)
}
}
func (slf *World[PlayerID]) RegActorOwnerChangeEvent(handle game.ActorOwnerChangeEventHandle[PlayerID]) {
slf.actorOwnerChangeEventHandles = append(slf.actorOwnerChangeEventHandles, handle)
}
func (slf *World[PlayerID]) OnActorOwnerChangeEvent(actor game.Actor, old, new PlayerID, isolated bool) {
for _, handle := range slf.actorOwnerChangeEventHandles {
handle(actor, old, new, isolated)
}
}