sunder/scripts/multiplayer/teams.gd
2026-02-18 18:33:17 -05:00

141 lines
4.4 KiB
GDScript

# This file is part of sunder.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
## This class defines a Teams manager
class_name Teams extends Resource
## Emitted when a [Team] is created.
signal team_added(team_name : String)
## Emitted when a [Team] is removed.
signal team_erased(team_name : String)
## Emitted when a [Player] is added to a [Team].
signal player_added(team_name: String, peer_id: int, username: String)
## Emitted when a [Player] is removed from a [Team].
signal player_erased(team_name: String, peer_id: int)
# The synced teams state.
@export var _state : Dictionary = {}:
get = get_state
func get_state() -> Dictionary:
for team : Team in _teams.values():
_state[team.name] = team.players
return _state
# The internal dictionary of teams.
var _teams : Dictionary = {}
## Retrieves an [Array] of [int] by [param team_name].
## [codeblock]
## var teams := Teams.new()
## teams.add_team("Phoenix")
## print(teams["Phoenix"]) # this calls `_get`
## [/codeblock]
func _get(team_name : StringName) -> Variant:
return _teams.get(team_name)
## Sets a [Team] by [param name] with an optional [param default].
## [codeblock]
## var teams := Teams.new()
## teams["Phoenix"] = Teams.Team.new("Phoenix") # this calls `_set`
## teams["Phoenix"] = null # refcount for Team is now 0
## [/codeblock]
func _set(key : StringName, team : Variant) -> bool:
if team == null:
return erase(key)
if team is Team:
_teams[key] = team
team_added.emit(key)
return true
return false
## This method retrieves the array of managed [Team] names.
func keys() -> Array:
return _teams.keys()
## This method retrieves the array of managed [Team].
func values() -> Array:
return _teams.values()
# This is the iterator index cursor.
var _iter_cursor : int = 0
# This method is an iterator initializer.
func _iter_init(_arg : Variant) -> bool:
_iter_cursor = 0 # reset
return _iter_cursor < len(_teams)
# This method checks if the iterator has a next value.
func _iter_next(_arg : Variant) -> bool:
_iter_cursor += 1
return _iter_cursor < len(_teams)
# This method gets the next iterator value.
func _iter_get(_arg : Variant) -> Team:
return _teams.values()[_iter_cursor]
## This method adds a new [Team] into the manager.
func add_team(key: String) -> bool:
if not _teams.has(key):
var team : Team = Team.new(key)
team.player_added.connect(_on_team_player_added)
team.player_erased.connect(_on_team_player_erased)
return _set(key, team)
return false
## This method adds new [Team] in batch from [param team_names].
func add_teams(team_names: Array[String]) -> Teams:
for team_name in team_names:
add_team(team_name)
return self
func get_peer_team(peer_id : int) -> Team:
for team : Team in _teams.values():
if peer_id in team.players:
return team
return null
func erase(team_name: String) -> bool:
var res: bool = _teams.erase(team_name)
if res:
team_erased.emit(team_name)
return res
func erase_player(peer_id: int) -> void:
for team : Team in _teams.values():
if team.erase(peer_id):
break
## The number of [Team].
func size() -> int:
return len(_teams)
## This method eases peer team switching by moving them to the specified [param team_name].
## It does not do anything if the peer is not already added to a [Team], see [method Team.add].
func switch_team(peer_id: int, team_name: String) -> void:
var lhs:Team = get_peer_team(peer_id)
var rhs:Team = _get(team_name)
if lhs and rhs:
rhs.add(peer_id, lhs.pop(peer_id))
# This method runs when a Team emits `player_added` signal
func _on_team_player_added(team_name: String, peer_id: int, username: String) -> void:
player_added.emit(team_name, peer_id, username) # emit manager signal
# This method runs when a Team emits `player_erased` signal
func _on_team_player_erased(team_name: String, peer_id: int) -> void:
player_erased.emit(team_name, peer_id) # emit manager signal