159c554a86
- Add PluginBase (plugin_base.gd) — abstract base class with 12 virtual hooks - Add PluginManifest (plugin_manifest.gd) — custom Resource for plugin metadata - Add PluginManager (plugin_manager.gd) — autoload singleton: directory scan, hook dispatch, lifecycle (load/unload/reload/rescan), cvar integration - Add hello_world example plugin with all hooks demonstrating usage - Register PluginManager autoload in project.godot - Extend rcon_command_handler.gd with 'plugin' subcommand (list/load/unload/ reload/info/rescan) delegating to PluginManager
105 lines
3.7 KiB
GDScript
105 lines
3.7 KiB
GDScript
## Hello World — Example Server Plugin
|
|
##
|
|
## Demonstrates all available plugin hooks by logging each event.
|
|
## Use this as a template for creating new plugins.
|
|
|
|
extends PluginBase
|
|
class_name HelloWorldPlugin
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Plugin state
|
|
# ---------------------------------------------------------------------------
|
|
var _player_count: int = 0
|
|
var _round_count: int = 0
|
|
var _tick_count: int = 0
|
|
var _start_time: int = 0
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Initialization
|
|
# ---------------------------------------------------------------------------
|
|
func _ready() -> void:
|
|
log_info("Hello World plugin initializing...")
|
|
_start_time = Time.get_ticks_msec()
|
|
|
|
func _exit_tree() -> void:
|
|
log_info("Hello World plugin shutting down. Uptime: %.1f seconds" %
|
|
[(Time.get_ticks_msec() - _start_time) / 1000.0])
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Server lifecycle hooks
|
|
# ---------------------------------------------------------------------------
|
|
func on_server_start() -> void:
|
|
log_info("on_server_start — Server is now online")
|
|
_tick_count = 0
|
|
|
|
func on_server_stop() -> void:
|
|
log_info("on_server_stop — Server is shutting down")
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Map lifecycle hooks
|
|
# ---------------------------------------------------------------------------
|
|
func on_map_start(map_name: String) -> void:
|
|
log_info("on_map_start — Loading map: %s" % map_name)
|
|
_player_count = 0
|
|
_round_count = 0
|
|
|
|
func on_map_end(map_name: String) -> void:
|
|
log_info("on_map_end — Map ended: %s (rounds played: %d)" % [map_name, _round_count])
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Player hooks
|
|
# ---------------------------------------------------------------------------
|
|
func on_player_connect(id: int, name: String, steam_id: String) -> bool:
|
|
log_info("on_player_connect — Player connecting: id=%d, name='%s', steam_id=%s" %
|
|
[id, name, steam_id])
|
|
# Return true to allow connection
|
|
return true
|
|
|
|
func on_player_disconnect(id: int, reason: String) -> void:
|
|
log_info("on_player_disconnect — Player disconnected: id=%d, reason='%s'" %
|
|
[id, reason])
|
|
|
|
func on_player_say(id: int, msg: String) -> bool:
|
|
log_info("on_player_say — Player %d says: \"%s\"" % [id, msg])
|
|
# Return true to let the message through
|
|
return true
|
|
|
|
func on_player_spawn(id: int) -> void:
|
|
_player_count += 1
|
|
log_info("on_player_spawn — Player %d spawned (total spawns: %d)" %
|
|
[id, _player_count])
|
|
|
|
func on_player_killed(victim: int, killer: int, weapon: String) -> void:
|
|
var desc: String
|
|
if victim == killer:
|
|
desc = "suicide"
|
|
else:
|
|
desc = "killed by %d" % killer
|
|
log_info("on_player_killed — Player %d %s with '%s'" % [victim, desc, weapon])
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Round hooks
|
|
# ---------------------------------------------------------------------------
|
|
func on_round_start(number: int) -> void:
|
|
_round_count = number
|
|
log_info("on_round_start — Round %d begins" % number)
|
|
|
|
func on_round_end(winner_team: int, reason: String) -> void:
|
|
var team_name: String = "Draw"
|
|
match winner_team:
|
|
1:
|
|
team_name = "Team A"
|
|
2:
|
|
team_name = "Team B"
|
|
log_info("on_round_end — Round %d ended: %s wins (%s)" %
|
|
[_round_count, team_name, reason])
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Per-tick hook
|
|
# ---------------------------------------------------------------------------
|
|
func on_tick(delta: float) -> void:
|
|
_tick_count += 1
|
|
# Log only every ~100 ticks to avoid spam (at 128 Hz ≈ every 0.78s)
|
|
if _tick_count % 100 == 0:
|
|
log_info("on_tick — Tick %d (delta=%.4f)" % [_tick_count, delta])
|