Create Dojo systems that implement game logic, modify model state, and handle player actions. Use when implementing game mechanics, player commands, or automated logic.
Generates Cairo smart contracts for Dojo game systems that modify model state and handle player actions. Use when you need to implement game mechanics like movement, combat, or resource gathering triggered by player commands or automated logic.
/plugin marketplace add dojoengine/book/plugin install book@dojoengineThis skill is limited to using the following tools:
Create Dojo systems (smart contracts) that implement your game's logic and modify model state.
Generates Cairo system contracts with:
#[dojo::contract] attribute#[dojo::interface]world.read_model(), world.write_model())Interactive mode:
"Create a system for player movement"
I'll ask about:
Direct mode:
"Create a move system that updates Position based on Direction"
use dojo::model::{ModelStorage, ModelValueStorage};
use dojo::event::EventStorage;
#[dojo::interface]
pub trait IActions {
fn spawn(ref self: ContractState);
fn move(ref self: ContractState, direction: Direction);
}
#[dojo::contract]
pub mod actions {
use super::IActions;
#[abi(embed_v0)]
impl ActionsImpl of IActions<ContractState> {
fn spawn(ref self: ContractState) {
let mut world = self.world_default();
let player = get_caller_address();
// Create initial state
world.write_model(@Position {
player,
x: 0,
y: 0
});
}
fn move(ref self: ContractState, direction: Direction) {
let mut world = self.world_default();
let player = get_caller_address();
// Read current state
let mut position: Position = world.read_model(player);
// Modify state
match direction {
Direction::Up => position.y += 1,
Direction::Down => position.y -= 1,
Direction::Left => position.x -= 1,
Direction::Right => position.x += 1,
}
// Write updated state
world.write_model(@position);
// Emit event
world.emit_event(@Moved { player, direction });
}
}
}
Handle player actions:
Manage entity lifecycle:
Time-based or conditional:
let position: Position = world.read_model(player);
world.write_model(@Position { player, x: 10, y: 20 });
let mut health: Health = world.read_model(entity_id);
health.current -= damage;
world.write_model(@health);
world.emit_event(@PlayerMoved {
player,
from: old_pos,
to: new_pos
});
// Only owner can call
world.assert_owner(player);
// Only writer can call
world.assert_writer(get_caller_address());
get_caller_address() for player identityassert!fn move(ref self: ContractState, direction: Direction) {
let player = get_caller_address();
let mut pos: Position = world.read_model(player);
// Update based on direction
match direction {
Direction::Up => pos.y += 1,
_ => // ...
}
world.write_model(@pos);
}
fn attack(ref self: ContractState, target: u32) {
let attacker = get_caller_address();
// Get attacker and target stats
let atk_stats: Stats = world.read_model(attacker);
let mut def_health: Health = world.read_model(target);
// Calculate damage
let damage = calculate_damage(atk_stats.strength);
def_health.current -= damage;
// Update and emit
world.write_model(@def_health);
world.emit_event(@AttackEvent { attacker, target, damage });
}
fn gather(ref self: ContractState, x: u32, y: u32) {
let player = get_caller_address();
// Check tile
let tile: Tile = world.read_model((x, y));
assert(tile.has_resource, 'no resource here');
// Update inventory
let mut inventory: Inventory = world.read_model(player);
inventory.resources += tile.resource_amount;
world.write_model(@inventory);
}
After creating systems:
dojo-test skill to test system logicdojo-review skill to check for issuesdojo-deploy skill to deploy your worlddojo-client skill to call systems from frontendThis skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.