Python API¶
Scripts run inside splintertree-world against an embedded Python
runtime (PyO3). The splintertree module exposes typed handles
(Creature, Player, GameObject, Item, Unit, MapInstance,
World, …) and ~22 base classes covering the AzerothCore hook
surface.
Base classes¶
| Class | Purpose |
|---|---|
CreatureScript |
NPC / mob behaviour |
PlayerScript |
Player-lifecycle hooks |
SpellScript |
Spell pre / post effects |
ItemScript |
Use / equip / quest-item hooks |
GameObjectScript |
World-object interactions |
WorldScript |
World-level lifecycle |
InstanceMapScript |
Per-instance state |
DungeonScript, RaidScript |
Encounter logic |
BattlegroundScript, ArenaScript |
PvP map control |
GlobalScript |
Cross-cutting hooks |
GuildScript, GroupScript, ArenaTeamScript |
Social entities |
AuctionHouseScript, MailScript |
Economy hooks |
EventListenerScript |
Generic event subscriber |
Hooks¶
Each base class binds the matching AC-style hook surface:
on_spawn, on_enter_combat, on_death, on_update,
on_gossip_hello / select, on_spell_hit, on_kill_player,
on_damage_taken, on_heal_received, on_before_melee_damage,
on_before_spell_damage, on_before_heal, …
from splintertree import (
Creature, CreatureScript, MapInstance, Unit,
on_enter_combat, on_spawn,
)
class Hogger(CreatureScript):
entry = 448
@on_spawn
def greet(self, instance: MapInstance, creature: Creature) -> None:
print(f"hogger up at ({creature.x:.1f},{creature.y:.1f})")
@on_enter_combat
def engage(
self,
instance: MapInstance,
creature: Creature,
attacker: Unit | None,
) -> None:
creature.cast(spell_id=12555, target=attacker) # Pummel
Server-pushed UI (AIO)¶
Mods talk to the client through instance.* methods on
MapInstance. The Splintertree client addon ships in every
realm's auto-built .rcmod (no per-player install) and dispatches
incoming frames by channel name:
from splintertree import (
AIOReplyScript, on_aio_reply, on_login,
)
class TradeReplies(AIOReplyScript):
@on_aio_reply("mymod.trade.accept")
def accept(self, instance, player, payload):
...
@on_login
def offer_trade(self, instance, player):
instance.show_confirm(
player.char_id,
message=instance.localize(player.char_id, "mymod.trade.prompt"),
on_ok="mymod.trade.accept",
on_cancel="mymod.trade.reject",
)
Built-in primitives¶
show_confirm, show_toast, show_message, show_input,
show_picker, show_wizard. For arbitrary client work the
unsandboxed instance.send_code(player, lua_text, compress=True)
pushes raw Lua against the full _G.
A capability handshake (STAIOHS on PLAYER_LOGIN) populates
instance.player_has_aio(char_id) so mods can degrade gracefully
on addon-less clients.
Compression¶
Static-dictionary compression (~30% reduction) for large payloads,
multi-frame reassembly for >219-byte bodies. The wire format is
opaque to the script author — pass any JSON-serialisable Python
value to send_ui and the runtime handles the rest.
Localisation¶
Strings live in cluster.i18n_strings keyed by mod name +
key + locale. Per-character last_locale is the fallback for
offline players.
Custom DB tables¶
stctl orm build lets mods declare typed cluster.* tables in
YAML; the builder emits SQL migrations and matching Python
accessors.
from splintertree.orm import MyModBalances
balances = MyModBalances.get_or_create(char_id=player.char_id)
balances.gold += 100
balances.save()
Live reload¶
Re-imports every scripts/*.py and re-wires hooks without restarting
the world worker. Pair it with splintertree-test-harness for an
inner loop that runs in seconds.