重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
dojo-client by dojoengine/book
npx skills add https://github.com/dojoengine/book --skill dojo-client将您的游戏客户端或前端连接到您部署的 Dojo 世界,支持跨多个平台。
处理以下客户端的集成:
| 平台 | 语言 | 包 |
|---|---|---|
| JavaScript/TypeScript | JS/TS | @dojoengine/sdk |
| Unity | C# | dojo.unity |
| Unreal Engine | C++ |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
dojo.unreal| Godot | GDScript | dojo.godot |
| Bevy | Rust | dojo.bevy |
| C/C++ | C/C++ | dojo.c |
使用快速启动向导:
pnpx @dojoengine/create-dojo start
# 核心包
pnpm add @dojoengine/core @dojoengine/sdk @dojoengine/torii-client
# Controller + starknet-react(推荐)
pnpm add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet
# 用于状态管理
pnpm add @dojoengine/state zustand immer
# 支持 WASM 的构建工具
pnpm add -D vite-plugin-wasm vite-plugin-top-level-await
dojoConfig.ts:import { createDojoConfig } from "@dojoengine/core";
import manifest from "../path/to/manifest_dev.json";
export const dojoConfig = createDojoConfig({ manifest });
重要提示:清单必须包含一个有效的世界 ABI,其中至少有一个 type: "interface" 条目。如果 manifest.world.abi 缺失或为空,starknet.js 会抛出 "Unable to determine Cairo version"。这由 sozo build 自动填充——如果您看到此错误,请重新构建您的合约。
DOJO_MANIFEST_PATH="../path/to/Scarb.toml" sozo build --typescript
import { init } from "@dojoengine/sdk";
import { DojoSdkProvider } from "@dojoengine/sdk/react";
import { dojoConfig } from "./dojoConfig.ts";
import { setupWorld } from "./bindings/typescript/contracts.gen.ts";
import type { SchemaType } from "./bindings/typescript/models.gen.ts";
async function main() {
const sdk = await init<SchemaType>({
client: {
worldAddress: dojoConfig.manifest.world.address,
toriiUrl: "http://localhost:8080",
relayUrl: "/ip4/127.0.0.1/tcp/9090",
},
domain: {
name: "MyDojoProject",
version: "1.0",
chainId: "KATANA",
revision: "1",
},
});
// 在 React 中使用
createRoot(document.getElementById("root")!).render(
<DojoSdkProvider sdk={sdk} dojoConfig={dojoConfig} clientFn={setupWorld}>
<StarknetProvider>
<App />
</StarknetProvider>
</DojoSdkProvider>
);
}
Cartridge Controller 是处理 Dojo 游戏中账户管理的推荐方式。它通过 starknet-react 提供基于会话的身份验证。
定义策略并创建连接器(在 React 组件外部):
import { ControllerConnector } from "@cartridge/connector";
import { SessionPolicies } from "@cartridge/controller";
const policies: SessionPolicies = {
contracts: {
[ACTIONS_CONTRACT_ADDRESS]: {
methods: [
{ name: "spawn", entrypoint: "spawn" },
{ name: "move", entrypoint: "move" },
],
},
},
};
const connector = new ControllerConnector({ policies });
用 StarknetConfig 包装您的应用:
import { StarknetConfig } from "@starknet-react/core";
import { sepolia, mainnet } from "@starknet-react/chains";
function StarknetProvider({ children }: { children: React.ReactNode }) {
return (
<StarknetConfig
autoConnect
chains={[mainnet, sepolia]}
connectors={[connector]}
provider={provider}
>
{children}
</StarknetConfig>
);
}
连接/断开连接:
import { useConnect, useDisconnect, useAccount } from "@starknet-react/core";
function ConnectWallet() {
const { connect, connectors } = useConnect();
const { disconnect } = useDisconnect();
const { address } = useAccount();
return address ? (
<button onClick={() => disconnect()}>断开连接</button>
) : (
<button onClick={() => connect({ connector: connectors[0] })}>
连接
</button>
);
}
下面"执行系统"部分中使用的 useAccount() 钩子,在连接后返回 Controller 会话账户。
import { ToriiQueryBuilder, KeysClause, MemberClause } from "@dojoengine/sdk";
// 简单查询:查找特定玩家
const entities = await sdk.getEntities({
query: new ToriiQueryBuilder().withClause(
KeysClause(["dojo_starter-Player"], ["0xabcde..."], "FixedLen").build()
),
});
// 访问结果
entities.items.forEach((entity) => {
const player = entity.models.dojo_starter.Player;
console.log(`玩家: ${player?.name}, 分数: ${player?.score}`);
});
const entities = await sdk.getEntities({
query: new ToriiQueryBuilder()
.withClause(
MemberClause("dojo_starter-Player", "score", "Gt", 0).build()
)
.withLimit(10)
.withOffset(0)
.withOrderBy([{ field: "score", direction: "Desc" }]),
});
const [initialEntities, subscription] = await sdk.subscribeEntityQuery({
query: new ToriiQueryBuilder()
.withClause(
MemberClause("dojo_starter-Player", "score", "Gt", 100).build()
)
.includeHashedKeys(),
callback: ({ data, error }) => {
if (data) {
data.forEach((entity) => {
const player = entity.models.dojo_starter.Player;
console.log(`玩家 ${player?.id}: ${player?.score} 分`);
});
}
},
});
// 稍后取消
// subscription.cancel();
import { useEntityQuery, useModels, useModel, useEntityId } from "@dojoengine/sdk/react";
function MyComponent() {
// 订阅实体变更
useEntityQuery(
new ToriiQueryBuilder()
.withClause(MemberClause("dojo_starter-Item", "durability", "Eq", 2).build())
.includeHashedKeys()
);
// 从存储中获取所有物品
const items = useModels("dojo_starter-Item");
// 通过实体 ID 获取单个物品
const entityId = useEntityId(1);
const item = useModel(entityId, "dojo_starter-Item");
return (
<div>
{Object.entries(items).map(([id, item]) => (
<div key={id}>物品 {id}: 耐久度 {item?.durability}</div>
))}
</div>
);
}
import { useDojoSDK } from "@dojoengine/sdk/react";
import { useAccount } from "@starknet-react/core";
function GameActions() {
const { client } = useDojoSDK();
const { account } = useAccount();
async function spawn() {
await client.actions.spawn({ account });
}
async function move(direction: number) {
await client.actions.move({ account, direction });
}
return (
<div>
<button onClick={spawn}>生成</button>
<button onClick={() => move(1)}>向右移动</button>
</div>
);
}
请参阅 dojo.unity 文档 了解:
请参阅 dojo.unreal 文档 了解:
请参阅 dojo.godot 文档 了解:
dojo-deploy 技能)dojo-indexer 技能)sozo build --typescript)dojo_starter-Position)客户端集成后:
每周安装数
66
仓库
GitHub 星标数
53
首次出现
2026年1月30日
安全审计
已安装于
opencode60
codex60
cursor59
kimi-cli58
gemini-cli58
github-copilot57
Connect your game client or frontend to your deployed Dojo world across multiple platforms.
Handles client integration for:
| Platform | Language | Package |
|---|---|---|
| JavaScript/TypeScript | JS/TS | @dojoengine/sdk |
| Unity | C# | dojo.unity |
| Unreal Engine | C++ | dojo.unreal |
| Godot | GDScript | dojo.godot |
| Bevy | Rust | dojo.bevy |
| C/C++ | C/C++ | dojo.c |
Use the quickstart wizard:
pnpx @dojoengine/create-dojo start
# Essential packages
pnpm add @dojoengine/core @dojoengine/sdk @dojoengine/torii-client
# Controller + starknet-react (recommended)
pnpm add @cartridge/connector @cartridge/controller @starknet-react/core @starknet-react/chains starknet
# For state management
pnpm add @dojoengine/state zustand immer
# Build tools for WASM support
pnpm add -D vite-plugin-wasm vite-plugin-top-level-await
2. CreatedojoConfig.ts:
import { createDojoConfig } from "@dojoengine/core";
import manifest from "../path/to/manifest_dev.json";
export const dojoConfig = createDojoConfig({ manifest });
Important : The manifest must contain a valid world ABI with at least one type: "interface" entry. If manifest.world.abi is missing or empty, starknet.js throws "Unable to determine Cairo version". This is populated automatically by sozo build — if you see this error, rebuild your contracts.
DOJO_MANIFEST_PATH="../path/to/Scarb.toml" sozo build --typescript
import { init } from "@dojoengine/sdk";
import { DojoSdkProvider } from "@dojoengine/sdk/react";
import { dojoConfig } from "./dojoConfig.ts";
import { setupWorld } from "./bindings/typescript/contracts.gen.ts";
import type { SchemaType } from "./bindings/typescript/models.gen.ts";
async function main() {
const sdk = await init<SchemaType>({
client: {
worldAddress: dojoConfig.manifest.world.address,
toriiUrl: "http://localhost:8080",
relayUrl: "/ip4/127.0.0.1/tcp/9090",
},
domain: {
name: "MyDojoProject",
version: "1.0",
chainId: "KATANA",
revision: "1",
},
});
// Use in React
createRoot(document.getElementById("root")!).render(
<DojoSdkProvider sdk={sdk} dojoConfig={dojoConfig} clientFn={setupWorld}>
<StarknetProvider>
<App />
</StarknetProvider>
</DojoSdkProvider>
);
}
Cartridge Controller is the recommended way to handle account management in Dojo games. It provides session-based authentication via starknet-react.
Define policies and create the connector (outside React components):
import { ControllerConnector } from "@cartridge/connector";
import { SessionPolicies } from "@cartridge/controller";
const policies: SessionPolicies = {
contracts: {
[ACTIONS_CONTRACT_ADDRESS]: {
methods: [
{ name: "spawn", entrypoint: "spawn" },
{ name: "move", entrypoint: "move" },
],
},
},
};
const connector = new ControllerConnector({ policies });
Wrap your app with StarknetConfig:
import { StarknetConfig } from "@starknet-react/core";
import { sepolia, mainnet } from "@starknet-react/chains";
function StarknetProvider({ children }: { children: React.ReactNode }) {
return (
<StarknetConfig
autoConnect
chains={[mainnet, sepolia]}
connectors={[connector]}
provider={provider}
>
{children}
</StarknetConfig>
);
}
Connect/disconnect:
import { useConnect, useDisconnect, useAccount } from "@starknet-react/core";
function ConnectWallet() {
const { connect, connectors } = useConnect();
const { disconnect } = useDisconnect();
const { address } = useAccount();
return address ? (
<button onClick={() => disconnect()}>Disconnect</button>
) : (
<button onClick={() => connect({ connector: connectors[0] })}>
Connect
</button>
);
}
The useAccount() hook used in the "Executing Systems" section below returns the Controller session account once connected.
import { ToriiQueryBuilder, KeysClause, MemberClause } from "@dojoengine/sdk";
// Simple query: Find a specific player
const entities = await sdk.getEntities({
query: new ToriiQueryBuilder().withClause(
KeysClause(["dojo_starter-Player"], ["0xabcde..."], "FixedLen").build()
),
});
// Access the results
entities.items.forEach((entity) => {
const player = entity.models.dojo_starter.Player;
console.log(`Player: ${player?.name}, Score: ${player?.score}`);
});
const entities = await sdk.getEntities({
query: new ToriiQueryBuilder()
.withClause(
MemberClause("dojo_starter-Player", "score", "Gt", 0).build()
)
.withLimit(10)
.withOffset(0)
.withOrderBy([{ field: "score", direction: "Desc" }]),
});
const [initialEntities, subscription] = await sdk.subscribeEntityQuery({
query: new ToriiQueryBuilder()
.withClause(
MemberClause("dojo_starter-Player", "score", "Gt", 100).build()
)
.includeHashedKeys(),
callback: ({ data, error }) => {
if (data) {
data.forEach((entity) => {
const player = entity.models.dojo_starter.Player;
console.log(`Player ${player?.id}: ${player?.score} points`);
});
}
},
});
// Cancel later
// subscription.cancel();
import { useEntityQuery, useModels, useModel, useEntityId } from "@dojoengine/sdk/react";
function MyComponent() {
// Subscribe to entity changes
useEntityQuery(
new ToriiQueryBuilder()
.withClause(MemberClause("dojo_starter-Item", "durability", "Eq", 2).build())
.includeHashedKeys()
);
// Get all items from the store
const items = useModels("dojo_starter-Item");
// Get a single item by entity ID
const entityId = useEntityId(1);
const item = useModel(entityId, "dojo_starter-Item");
return (
<div>
{Object.entries(items).map(([id, item]) => (
<div key={id}>Item {id}: durability {item?.durability}</div>
))}
</div>
);
}
import { useDojoSDK } from "@dojoengine/sdk/react";
import { useAccount } from "@starknet-react/core";
function GameActions() {
const { client } = useDojoSDK();
const { account } = useAccount();
async function spawn() {
await client.actions.spawn({ account });
}
async function move(direction: number) {
await client.actions.move({ account, direction });
}
return (
<div>
<button onClick={spawn}>Spawn</button>
<button onClick={() => move(1)}>Move Right</button>
</div>
);
}
See dojo.unity documentation for:
See dojo.unreal documentation for:
See dojo.godot documentation for:
dojo-deploy skill)dojo-indexer skill)sozo build --typescript)dojo_starter-Position)After client integration:
Weekly Installs
66
Repository
GitHub Stars
53
First Seen
Jan 30, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
opencode60
codex60
cursor59
kimi-cli58
gemini-cli58
github-copilot57
CoinGecko API 集成 - 实时加密货币价格、市场数据与区块链分析工具
4,100 周安装
Azure 工作负载自动升级评估工具 - 支持 Functions、App Service 计划与 SKU 迁移
303 周安装
Tauri 跨平台桌面应用开发指南:TypeScript + Rust 全栈实战教程
306 周安装
Fastify OAuth 2.0/2.1 实现与调试指南:授权码+PKCE流程详解
301 周安装
FastAPI专家技能:高性能异步API开发、微服务架构与生产部署指南
306 周安装
移动端响应式设计指南:CSS断点、Tailwind与触摸交互实现移动优先Web应用
302 周安装
GitHub 问题自动创建与优化工具 - 支持 Bug、功能、用户故事和任务
336 周安装