refactor
This commit is contained in:
124
autoloads/stats.gd
Normal file
124
autoloads/stats.gd
Normal file
@@ -0,0 +1,124 @@
|
||||
extends Node
|
||||
|
||||
const SYNCED_STATS: Array = [
|
||||
"health", "shield", "max_health", "max_shield",
|
||||
"role", "level", "xp", "xp_to_next",
|
||||
"buff_damage", "buff_heal", "buff_shield",
|
||||
]
|
||||
const SYNC_INTERVAL: float = 0.10
|
||||
|
||||
var _entities: Dictionary = {}
|
||||
var _player_cache: Dictionary = {}
|
||||
var _dirty: Dictionary = {}
|
||||
var _accum: float = 0.0
|
||||
|
||||
func _ready() -> void:
|
||||
set_process(true)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
_accum += delta
|
||||
if _accum < SYNC_INTERVAL:
|
||||
return
|
||||
_accum = 0.0
|
||||
if multiplayer.multiplayer_peer == null or multiplayer.multiplayer_peer is OfflineMultiplayerPeer or not multiplayer.is_server():
|
||||
_dirty.clear()
|
||||
return
|
||||
if _dirty.is_empty():
|
||||
return
|
||||
for entity in _dirty.keys():
|
||||
if not is_instance_valid(entity) or not entity.is_inside_tree():
|
||||
continue
|
||||
_sync_stats_batch.rpc(String(entity.get_path()), _dirty[entity])
|
||||
_dirty.clear()
|
||||
|
||||
@rpc("authority", "unreliable_ordered")
|
||||
func _sync_stats_batch(path_str: String, changes: Dictionary) -> void:
|
||||
var entity := get_node_or_null(NodePath(path_str))
|
||||
if entity == null or not entity in _entities:
|
||||
return
|
||||
for stat in changes.keys():
|
||||
_entities[entity][stat] = changes[stat]
|
||||
match stat:
|
||||
"health":
|
||||
EventBus.health_changed.emit(entity, changes[stat], _entities[entity].get("max_health", 100.0))
|
||||
"shield":
|
||||
EventBus.shield_changed.emit(entity, changes[stat], _entities[entity].get("max_shield", 0.0))
|
||||
"role":
|
||||
EventBus.role_changed.emit(entity, changes[stat])
|
||||
"level":
|
||||
EventBus.level_up.emit(entity, changes[stat])
|
||||
"buff_damage", "buff_heal", "buff_shield":
|
||||
EventBus.buff_changed.emit(entity, StringName(stat), changes[stat])
|
||||
|
||||
func register(entity: Node, base_resource: Resource) -> void:
|
||||
if not is_instance_valid(entity):
|
||||
return
|
||||
var data: Dictionary = {}
|
||||
for prop in base_resource.get_property_list():
|
||||
var name: String = prop.name
|
||||
if not (prop.usage & PROPERTY_USAGE_STORAGE):
|
||||
continue
|
||||
if name in ["resource_local_to_scene", "resource_path", "resource_name", "resource_scene_unique_id", "script"]:
|
||||
continue
|
||||
data[name] = base_resource.get(name)
|
||||
data["health"] = data.get("max_health", 100.0)
|
||||
data["shield"] = data.get("max_shield", 0.0)
|
||||
data["shield_regen_timer"] = 0.0
|
||||
data["base_resource"] = base_resource
|
||||
_entities[entity] = data
|
||||
EventBus.entity_registered.emit(entity)
|
||||
|
||||
func deregister(entity: Node) -> void:
|
||||
if entity in _entities:
|
||||
_entities.erase(entity)
|
||||
EventBus.entity_deregistered.emit(entity)
|
||||
|
||||
func has(entity: Node) -> bool:
|
||||
return entity in _entities
|
||||
|
||||
func get_stat(entity: Node, stat: String, default: Variant = 0.0) -> Variant:
|
||||
if entity in _entities:
|
||||
return _entities[entity].get(stat, default)
|
||||
return default
|
||||
|
||||
func set_stat(entity: Node, stat: String, value: Variant) -> void:
|
||||
if not entity in _entities:
|
||||
return
|
||||
var prev: Variant = _entities[entity].get(stat)
|
||||
_entities[entity][stat] = value
|
||||
if stat in SYNCED_STATS and prev != value and multiplayer.multiplayer_peer != null and not (multiplayer.multiplayer_peer is OfflineMultiplayerPeer) and multiplayer.is_server() and is_instance_valid(entity) and entity.is_inside_tree():
|
||||
if not entity in _dirty:
|
||||
_dirty[entity] = {}
|
||||
_dirty[entity][stat] = value
|
||||
|
||||
|
||||
func get_all(entity: Node) -> Dictionary:
|
||||
return _entities.get(entity, {})
|
||||
|
||||
func entities() -> Array:
|
||||
return _entities.keys()
|
||||
|
||||
func entities_in_group(group: StringName) -> Array:
|
||||
var out: Array = []
|
||||
for e in _entities.keys():
|
||||
if is_instance_valid(e) and e.is_in_group(group):
|
||||
out.append(e)
|
||||
return out
|
||||
|
||||
func cache_player(peer_id: int, entity: Node) -> void:
|
||||
if entity in _entities:
|
||||
_player_cache[peer_id] = _entities[entity].duplicate(true)
|
||||
|
||||
func restore_player(peer_id: int, entity: Node) -> void:
|
||||
if peer_id in _player_cache:
|
||||
_entities[entity] = _player_cache[peer_id].duplicate(true)
|
||||
|
||||
func clear_player_cache(peer_id: int = -1) -> void:
|
||||
if peer_id == -1:
|
||||
_player_cache.clear()
|
||||
else:
|
||||
_player_cache.erase(peer_id)
|
||||
|
||||
func clear_all() -> void:
|
||||
_entities.clear()
|
||||
_player_cache.clear()
|
||||
Reference in New Issue
Block a user