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
159 lines
5.7 KiB
GDScript
159 lines
5.7 KiB
GDScript
## Plugin Base — Abstract plugin interface
|
|
##
|
|
## All server plugins must extend this class and may override any
|
|
## of the virtual hook methods. Hooks that return a bool act as
|
|
## filters/callbacks — return true to allow/accept the event,
|
|
## false to block/reject it (where the hook definition supports it).
|
|
##
|
|
## The base class provides a `plugin_name` property that is
|
|
## automatically populated at load time from the manifest, and a
|
|
## `log(msg)` convenience method for structured logging.
|
|
##
|
|
## Usage:
|
|
## extends PluginBase
|
|
## func on_server_start():
|
|
## log_info("My plugin started!")
|
|
##
|
|
## func on_player_say(id, msg) -> bool:
|
|
## if "badword" in msg:
|
|
## return false # block the message
|
|
## return true
|
|
|
|
extends Node
|
|
class_name PluginBase
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Public properties — populated by PluginManager at load time
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## The canonical name of this plugin, set from the manifest at load time.
|
|
var plugin_name: String = &""
|
|
|
|
## The version string from the manifest (e.g. "1.0.0").
|
|
var plugin_version: String = &""
|
|
|
|
## The author string from the manifest.
|
|
var plugin_author: String = &""
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Logging helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## Log an informational message prefixed with the plugin name.
|
|
func log_info(msg: String) -> void:
|
|
print("[Plugin:%s] %s" % [plugin_name, msg])
|
|
|
|
## Log a warning message prefixed with the plugin name.
|
|
func log_warn(msg: String) -> void:
|
|
push_warning("[Plugin:%s] %s" % [plugin_name, msg])
|
|
|
|
## Log an error message prefixed with the plugin name.
|
|
func log_err(msg: String) -> void:
|
|
push_error("[Plugin:%s] %s" % [plugin_name, msg])
|
|
|
|
## Set metadata on this plugin from the manifest.
|
|
## Called automatically by PluginManager during load.
|
|
func set_plugin_meta(name: String, version: String, author: String) -> void:
|
|
plugin_name = name
|
|
plugin_version = version
|
|
plugin_author = author
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Server lifecycle hooks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## Called when the server starts (after all autoloads are ready).
|
|
## Use this to initialise timers, connect signals, or register cvars.
|
|
func on_server_start() -> void:
|
|
pass
|
|
|
|
## Called when the server is shutting down.
|
|
## Use this to flush state, save data, or disconnect from external services.
|
|
func on_server_stop() -> void:
|
|
pass
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Map lifecycle hooks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## Called when a map starts loading.
|
|
## map_name: the resource path or identifier of the map.
|
|
func on_map_start(map_name: String) -> void:
|
|
pass
|
|
|
|
## Called when a map ends (all players left, next map loading).
|
|
## map_name: the resource path or identifier of the map that ended.
|
|
func on_map_end(map_name: String) -> void:
|
|
pass
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Player hooks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## Called when a player attempts to connect to the server.
|
|
## id: the peer/connection id assigned by the network layer.
|
|
## name: the player's display name.
|
|
## steam_id: the player's unique platform identifier.
|
|
##
|
|
## Return true to allow the connection, false to reject it.
|
|
func on_player_connect(id: int, name: String, steam_id: String) -> bool:
|
|
return true
|
|
|
|
## Called when a player disconnects from the server.
|
|
## id: the peer/connection id of the player.
|
|
## reason: a string describing why the player left (optional).
|
|
func on_player_disconnect(id: int, reason: String) -> void:
|
|
pass
|
|
|
|
## Called when a player sends a chat message.
|
|
## id: the peer/connection id of the sender.
|
|
## msg: the plain-text chat message.
|
|
##
|
|
## Return true to allow the message through, false to suppress it.
|
|
func on_player_say(id: int, msg: String) -> bool:
|
|
return true
|
|
|
|
## Called when a player spawns into the game world.
|
|
## id: the peer/connection id of the player.
|
|
func on_player_spawn(id: int) -> void:
|
|
pass
|
|
|
|
## Called when a player is killed.
|
|
## victim: peer id of the killed player.
|
|
## killer: peer id of the killer (may equal victim for suicide).
|
|
## weapon: weapon name/identifier string (e.g. "rifle", "pistol").
|
|
func on_player_killed(victim: int, killer: int, weapon: String) -> void:
|
|
pass
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Round hooks
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## Called when a new round begins.
|
|
## number: the round number (1-based, increments each round).
|
|
func on_round_start(number: int) -> void:
|
|
pass
|
|
|
|
## Called when a round ends.
|
|
## winner_team: 0 = draw/stalemate, 1 = team A, 2 = team B.
|
|
## reason: a string describing the end condition ("time_limit", "all_dead", etc.).
|
|
func on_round_end(winner_team: int, reason: String) -> void:
|
|
pass
|
|
|
|
## Called when the team scores change.
|
|
## team_a_score and team_b_score reflect the current match state.
|
|
func on_score_changed(team_a_score: int, team_b_score: int) -> void:
|
|
pass
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Per-tick hook
|
|
# ---------------------------------------------------------------------------
|
|
|
|
## Called every physics tick (at the configured tick rate, typically 128 Hz).
|
|
## delta: time elapsed since last tick in seconds (approximately 1/tickrate).
|
|
##
|
|
## WARNING: This is called at high frequency — keep implementations cheap
|
|
## to avoid impacting server performance.
|
|
func on_tick(delta: float) -> void:
|
|
pass
|