世界合约

世界合约是一个中央系统内核,是启动和解决所有交互的基础。在这个内核中,合约被部署、注册和执行,简化了下游系统的流程,使得客户只需与一个合约而不是潜在的数百个合约打交道。

Dojo 核心将此合约抽象化,作为开发者,您无需编写此合约,也无需在构建世界时对其进行修改。但是,了解它的工作原理以及它与系统其他部分的交互方式非常重要。

思考: 将自治世界视为驻留在另一个区块链中的主权区块链--可以说是嵌套区块链。正如你可以在以太坊上部署合约来增强其功能一样,你也可以在世界合约中引入系统来丰富其功能。与以太坊类似,任何人都可以为 "世界 "做出贡献,但与组件状态交互需要授权。有一个专门的主题会讨论授权。

Context(上下文)

你会注意到,每个 System 都接受一个 Context 结构体作为第一个参数。这是一个特殊的结构体,包含有关世界和调用者的信息。

#[derive(Copy, Drop, Serde)]
struct Context {
    world: IWorldDispatcher, // Dispatcher to the world contract
    origin: ContractAddress, // Address of the origin
    system: felt252, // Name of the calling system
    system_class_hash: ClassHash, // Class hash of the calling system
}

uuid()命令

为实体生成唯一 ID 通常很有用。uuid() 函数可用来生成唯一 ID。

像这样使用它:

let game_id = ctx.world.uuid();

完整的世界API

世界公开了一个接口,任何客户端都可以与之交互。

// World interface
#[starknet::interface]
trait IWorld<T> {
    fn component(self: @T, name: felt252) -> ClassHash;
    fn register_component(ref self: T, class_hash: ClassHash);
    fn system(self: @T, name: felt252) -> ClassHash;
    fn register_system(ref self: T, class_hash: ClassHash);
    fn uuid(ref self: T) -> usize;
    fn emit(self: @T, keys: Array<felt252>, values: Span<felt252>);
    fn execute(ref self: T, system: felt252, calldata: Array<felt252>) -> Span<felt252>;
    fn entity(
        self: @T, component: felt252, keys: Span<felt252>, offset: u8, length: usize
    ) -> Span<felt252>;
    fn set_entity(
        ref self: T, component: felt252, keys: Span<felt252>, offset: u8, value: Span<felt252>
    );
    fn entities(
        self: @T, component: felt252, index: felt252, length: usize
    ) -> (Span<felt252>, Span<Span<felt252>>);
    fn set_executor(ref self: T, contract_address: ContractAddress);
    fn executor(self: @T) -> ContractAddress;
    fn delete_entity(ref self: T, component: felt252, keys: Span<felt252>);
    fn origin(self: @T) -> ContractAddress;

    fn is_owner(self: @T, account: ContractAddress, target: felt252) -> bool;
    fn grant_owner(ref self: T, account: ContractAddress, target: felt252);
    fn revoke_owner(ref self: T, account: ContractAddress, target: felt252);

    fn is_writer(self: @T, component: felt252, system: felt252) -> bool;
    fn grant_writer(ref self: T, component: felt252, system: felt252);
    fn revoke_writer(ref self: T, component: felt252, system: felt252);
}