事件
事件在让外部了解 Dojo 世界中的动态时起着关键作用。每次Component
更新时,World
合约都会发出这些事件。更令人兴奋的是,你可以根据特定需求制作自己的自定义事件!此外,由于使用了 Torii,所有这些事件都被无缝地索引起来,确保了轻松高效的查询。
组件事件
请看 Moves
组件的示例:
#[component]
struct Moves {
#[key]
player: Address,
remaining: u32,
}
当该组件更新时,World
合约将发出一个结构如下的事件:
#[derive(Drop, starknet::Event)]
struct StoreSetRecord {
table: felt252, // Moves
keys: Span<felt252>, // [player]
offset: u8, // 0
value: Span<felt252>, // [remaining]
}
然后,Torii将捕获这些信息,并编制索引以供查询。这样,你就可以重建世界的状态。
同样,当一个组件被删除时,World
合约将发出一个结构如下的事件:
#[derive(Drop, starknet::Event)]
struct StoreDelRecord {
table: felt252,
keys: Span<felt252>,
}
世界事件
当初始化以及注册新组件和系统时,World
合约也会发出事件。这些事件通过以下结构体发出:
#[derive(Drop, starknet::Event)]
struct WorldSpawned {
address: ContractAddress,
caller: ContractAddress
}
#[derive(Drop, starknet::Event)]
struct ComponentRegistered {
name: felt252,
class_hash: ClassHash
}
#[derive(Drop, starknet::Event)]
struct SystemRegistered {
name: felt252,
class_hash: ClassHash
}
Torii 也会捕获这些事件,并编制索引以供查询。
自定义事件
在您的系统中,发射自定义事件是非常有益的。幸运的是,有一个方便的 emit!
宏可以让您直接从您的世界中发射事件。使用方法如下:
emit !(ctx.world, Moved { address: ctx.origin, direction });
在系统中加入此机能后,它将发出一个结构如下的事件:
#[derive(Drop, starknet::Event)]
struct Moved {
address: felt252,
direction: felt252,
}
现在是一个使用自定义事件的完整示例:
fn execute(ctx: Context, direction: Direction) {
let (mut position, mut moves) = get !(ctx.world, ctx.origin, (Position, Moves));
moves.remaining -= 1;
let next = next_position(position, direction);
set !(ctx.world, (moves, next));
emit !(ctx.world, Moved { address: ctx.origin, direction });
return ();
}
注意:请阅读 命令 中的
get!
和set!
宏。