create-mud 2.0.0-alpha.1.21 → 2.0.0-alpha.1.211

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +1 -1
  3. package/dist/templates/{minimal/packages/client → phaser}/.eslintrc +1 -3
  4. package/dist/templates/phaser/package.json +28 -0
  5. package/dist/templates/phaser/packages/art/.gitignore +0 -0
  6. package/dist/templates/phaser/packages/art/README.md +33 -0
  7. package/dist/templates/phaser/packages/art/config-sprites.json +21 -0
  8. package/dist/templates/phaser/packages/art/package.json +27 -0
  9. package/dist/templates/phaser/packages/art/scripts/cli.mjs +190 -0
  10. package/dist/templates/phaser/packages/art/scripts/export-tiled-types.ts +292 -0
  11. package/dist/templates/phaser/packages/art/sprites/golem/attack/0.png +0 -0
  12. package/dist/templates/phaser/packages/art/sprites/golem/attack/1.png +0 -0
  13. package/dist/templates/phaser/packages/art/sprites/golem/attack/2.png +0 -0
  14. package/dist/templates/phaser/packages/art/sprites/golem/attack/3.png +0 -0
  15. package/dist/templates/phaser/packages/art/sprites/golem/attack/4.png +0 -0
  16. package/dist/templates/phaser/packages/art/sprites/golem/attack/5.png +0 -0
  17. package/dist/templates/phaser/packages/art/sprites/golem/death/0.png +0 -0
  18. package/dist/templates/phaser/packages/art/sprites/golem/death/1.png +0 -0
  19. package/dist/templates/phaser/packages/art/sprites/golem/death/2.png +0 -0
  20. package/dist/templates/phaser/packages/art/sprites/golem/idle/0.png +0 -0
  21. package/dist/templates/phaser/packages/art/sprites/golem/idle/1.png +0 -0
  22. package/dist/templates/phaser/packages/art/sprites/golem/idle/2.png +0 -0
  23. package/dist/templates/phaser/packages/art/sprites/golem/idle/3.png +0 -0
  24. package/dist/templates/phaser/packages/art/tilesets/images/world.png +0 -0
  25. package/dist/templates/phaser/packages/art/tilesets/world.tsx +19 -0
  26. package/dist/templates/phaser/packages/client/.env +1 -0
  27. package/dist/templates/phaser/packages/client/.eslintrc +7 -0
  28. package/dist/templates/phaser/packages/client/index.html +39 -0
  29. package/dist/templates/phaser/packages/client/package.json +48 -0
  30. package/dist/templates/phaser/packages/client/public/assets/atlases/atlas.json +292 -0
  31. package/dist/templates/phaser/packages/client/public/assets/atlases/atlas.png +0 -0
  32. package/dist/templates/phaser/packages/client/public/assets/tilesets/world.png +0 -0
  33. package/dist/templates/phaser/packages/client/src/artTypes/world.ts +9 -0
  34. package/dist/templates/phaser/packages/client/src/index.tsx +11 -0
  35. package/dist/templates/phaser/packages/client/src/layers/network/createNetworkLayer.ts +24 -0
  36. package/dist/templates/phaser/packages/client/src/layers/phaser/configurePhaser.ts +91 -0
  37. package/dist/templates/phaser/packages/client/src/layers/phaser/constants.ts +22 -0
  38. package/dist/templates/phaser/packages/client/src/layers/phaser/createPhaserLayer.ts +33 -0
  39. package/dist/templates/phaser/packages/client/src/layers/phaser/systems/createCamera.ts +13 -0
  40. package/dist/templates/phaser/packages/client/src/layers/phaser/systems/createMapSystem.ts +32 -0
  41. package/dist/templates/phaser/packages/client/src/layers/phaser/systems/index.ts +1 -0
  42. package/dist/templates/phaser/packages/client/src/layers/phaser/systems/registerSystems.ts +8 -0
  43. package/dist/templates/phaser/packages/client/src/mud/contractComponents.ts +24 -0
  44. package/dist/templates/phaser/packages/client/src/mud/createClientComponents.ts +10 -0
  45. package/dist/templates/phaser/packages/client/src/mud/createSystemCalls.ts +21 -0
  46. package/dist/templates/phaser/packages/client/src/mud/getNetworkConfig.ts +53 -0
  47. package/dist/templates/phaser/packages/client/src/mud/setup.ts +16 -0
  48. package/dist/templates/phaser/packages/client/src/mud/setupNetwork.ts +102 -0
  49. package/dist/templates/phaser/packages/client/src/mud/supportedChains.ts +5 -0
  50. package/dist/templates/phaser/packages/client/src/mud/world.ts +3 -0
  51. package/dist/templates/phaser/packages/client/src/store.ts +38 -0
  52. package/dist/templates/phaser/packages/client/src/ui/App.tsx +23 -0
  53. package/dist/templates/phaser/packages/client/src/ui/LoadingScreen/BootScreen.tsx +42 -0
  54. package/dist/templates/phaser/packages/client/src/ui/LoadingScreen/LoadingBar.tsx +21 -0
  55. package/dist/templates/phaser/packages/client/src/ui/LoadingScreen/LoadingScreen.tsx +52 -0
  56. package/dist/templates/phaser/packages/client/src/ui/LoadingScreen/index.ts +1 -0
  57. package/dist/templates/phaser/packages/client/src/ui/PhaserLayer.tsx +20 -0
  58. package/dist/templates/phaser/packages/client/src/ui/UIRoot.tsx +20 -0
  59. package/dist/templates/phaser/packages/client/src/ui/Wrapper.tsx +5 -0
  60. package/dist/templates/phaser/packages/client/src/ui/hooks/useNetworkLayer.tsx +17 -0
  61. package/dist/templates/phaser/packages/client/src/ui/hooks/usePhaserLayer.tsx +87 -0
  62. package/dist/templates/phaser/packages/client/src/ui/hooks/usePromiseValue.ts +24 -0
  63. package/dist/templates/phaser/packages/client/src/ui/theme/ClickWrapper.tsx +18 -0
  64. package/dist/templates/phaser/packages/client/src/ui/theme/SpriteImage.tsx +52 -0
  65. package/dist/templates/{minimal → phaser}/packages/client/tsconfig.json +3 -4
  66. package/dist/templates/phaser/packages/client/vite.config.ts +15 -0
  67. package/dist/templates/phaser/packages/contracts/.env +8 -0
  68. package/dist/templates/{minimal → phaser}/packages/contracts/.gitignore +3 -2
  69. package/dist/templates/{minimal → phaser}/packages/contracts/.solhint.json +2 -1
  70. package/dist/templates/phaser/packages/contracts/foundry.toml +22 -0
  71. package/dist/templates/phaser/packages/contracts/mud.config.ts +10 -0
  72. package/dist/templates/phaser/packages/contracts/package.json +45 -0
  73. package/dist/templates/phaser/packages/contracts/remappings.txt +3 -0
  74. package/dist/templates/phaser/packages/contracts/script/PostDeploy.s.sol +17 -0
  75. package/dist/templates/phaser/packages/contracts/src/codegen/Tables.sol +6 -0
  76. package/dist/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +120 -0
  77. package/dist/templates/phaser/packages/contracts/src/codegen/world/IIncrementSystem.sol +8 -0
  78. package/dist/templates/phaser/packages/contracts/src/codegen/world/IWorld.sol +16 -0
  79. package/dist/templates/phaser/packages/contracts/src/systems/IncrementSystem.sol +14 -0
  80. package/dist/templates/phaser/packages/contracts/test/CounterTest.t.sol +38 -0
  81. package/dist/templates/phaser/packages/contracts/tsconfig.json +13 -0
  82. package/dist/templates/phaser/packages/contracts/worlds.json +5 -0
  83. package/dist/templates/react/.eslintrc +10 -0
  84. package/dist/templates/react/package.json +13 -3
  85. package/dist/templates/react/packages/client/.env +1 -0
  86. package/dist/templates/react/packages/client/.eslintrc +2 -12
  87. package/dist/templates/react/packages/client/package.json +18 -21
  88. package/dist/templates/react/packages/client/src/App.tsx +11 -13
  89. package/dist/templates/react/packages/client/src/MUDContext.tsx +21 -0
  90. package/dist/templates/react/packages/client/src/index.tsx +12 -31
  91. package/dist/templates/react/packages/client/src/mud/contractComponents.ts +24 -0
  92. package/dist/templates/react/packages/client/src/mud/createClientComponents.ts +10 -0
  93. package/dist/templates/react/packages/client/src/mud/createSystemCalls.ts +21 -0
  94. package/dist/templates/react/packages/client/src/mud/getNetworkConfig.ts +53 -0
  95. package/dist/templates/react/packages/client/src/mud/setup.ts +16 -0
  96. package/dist/templates/react/packages/client/src/mud/setupNetwork.ts +102 -0
  97. package/dist/templates/react/packages/client/src/mud/supportedChains.ts +5 -0
  98. package/dist/templates/react/packages/client/src/mud/world.ts +3 -0
  99. package/dist/templates/react/packages/client/tsconfig.json +0 -3
  100. package/dist/templates/react/packages/client/vite.config.ts +3 -0
  101. package/dist/templates/react/packages/contracts/.env +8 -0
  102. package/dist/templates/react/packages/contracts/.gitignore +3 -2
  103. package/dist/templates/react/packages/contracts/.solhint.json +2 -1
  104. package/dist/templates/react/packages/contracts/foundry.toml +13 -2
  105. package/dist/templates/react/packages/contracts/mud.config.ts +10 -0
  106. package/dist/templates/react/packages/contracts/package.json +25 -20
  107. package/dist/templates/react/packages/contracts/remappings.txt +3 -9
  108. package/dist/templates/react/packages/contracts/script/PostDeploy.s.sol +24 -0
  109. package/dist/templates/react/packages/contracts/src/codegen/Tables.sol +6 -0
  110. package/dist/templates/react/packages/contracts/src/codegen/tables/Counter.sol +120 -0
  111. package/dist/templates/react/packages/contracts/src/codegen/world/IIncrementSystem.sol +8 -0
  112. package/dist/templates/react/packages/contracts/src/codegen/world/IWorld.sol +16 -0
  113. package/dist/templates/react/packages/contracts/src/systems/IncrementSystem.sol +7 -15
  114. package/dist/templates/react/packages/contracts/test/CounterTest.t.sol +38 -0
  115. package/dist/templates/react/packages/contracts/tsconfig.json +9 -8
  116. package/dist/templates/react/packages/contracts/worlds.json +5 -0
  117. package/dist/templates/threejs/.eslintrc +10 -0
  118. package/dist/templates/threejs/.gitignore +1 -0
  119. package/dist/templates/threejs/.vscode/extensions.json +3 -0
  120. package/dist/templates/threejs/.vscode/settings.json +3 -0
  121. package/dist/templates/threejs/package.json +28 -0
  122. package/dist/templates/threejs/packages/client/.env +1 -0
  123. package/dist/templates/threejs/packages/client/.eslintrc +7 -0
  124. package/dist/templates/threejs/packages/client/.gitignore +3 -0
  125. package/dist/templates/threejs/packages/client/index.html +12 -0
  126. package/dist/templates/threejs/packages/client/package.json +41 -0
  127. package/dist/templates/threejs/packages/client/src/App.tsx +81 -0
  128. package/dist/templates/threejs/packages/client/src/MUDContext.tsx +21 -0
  129. package/dist/templates/threejs/packages/client/src/index.tsx +19 -0
  130. package/dist/templates/threejs/packages/client/src/mud/contractComponents.ts +26 -0
  131. package/dist/templates/threejs/packages/client/src/mud/createClientComponents.ts +10 -0
  132. package/dist/templates/threejs/packages/client/src/mud/createSystemCalls.ts +15 -0
  133. package/dist/templates/threejs/packages/client/src/mud/getNetworkConfig.ts +53 -0
  134. package/dist/templates/threejs/packages/client/src/mud/setup.ts +16 -0
  135. package/dist/templates/threejs/packages/client/src/mud/setupNetwork.ts +102 -0
  136. package/dist/templates/threejs/packages/client/src/mud/supportedChains.ts +5 -0
  137. package/dist/templates/threejs/packages/client/src/mud/world.ts +3 -0
  138. package/dist/templates/threejs/packages/client/src/useKeyboardMovement.ts +60 -0
  139. package/dist/templates/threejs/packages/client/tsconfig.json +19 -0
  140. package/dist/templates/threejs/packages/client/vite.config.ts +15 -0
  141. package/dist/templates/threejs/packages/contracts/.env +8 -0
  142. package/dist/templates/threejs/packages/contracts/.gitignore +11 -0
  143. package/dist/templates/threejs/packages/contracts/.prettierrc +8 -0
  144. package/dist/templates/threejs/packages/contracts/.solhint.json +12 -0
  145. package/dist/templates/threejs/packages/contracts/foundry.toml +22 -0
  146. package/dist/templates/threejs/packages/contracts/mud.config.ts +13 -0
  147. package/dist/templates/threejs/packages/contracts/package.json +45 -0
  148. package/dist/templates/threejs/packages/contracts/remappings.txt +3 -0
  149. package/dist/templates/threejs/packages/contracts/src/codegen/Tables.sol +6 -0
  150. package/dist/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +263 -0
  151. package/dist/templates/threejs/packages/contracts/src/codegen/world/IMoveSystem.sol +8 -0
  152. package/dist/templates/threejs/packages/contracts/src/codegen/world/IWorld.sol +16 -0
  153. package/dist/templates/threejs/packages/contracts/src/systems/MoveSystem.sol +25 -0
  154. package/dist/templates/threejs/packages/contracts/tsconfig.json +13 -0
  155. package/dist/templates/threejs/packages/contracts/worlds.json +5 -0
  156. package/dist/templates/threejs/pnpm-workspace.yaml +2 -0
  157. package/dist/templates/vanilla/.eslintrc +10 -0
  158. package/dist/templates/vanilla/.gitignore +1 -0
  159. package/dist/templates/vanilla/.vscode/extensions.json +3 -0
  160. package/dist/templates/vanilla/.vscode/settings.json +3 -0
  161. package/dist/templates/vanilla/package.json +28 -0
  162. package/dist/templates/vanilla/packages/client/.env +1 -0
  163. package/dist/templates/vanilla/packages/client/.gitignore +3 -0
  164. package/dist/templates/vanilla/packages/client/package.json +32 -0
  165. package/dist/templates/vanilla/packages/client/src/index.ts +22 -0
  166. package/dist/templates/vanilla/packages/client/src/mud/contractComponents.ts +24 -0
  167. package/dist/templates/vanilla/packages/client/src/mud/createClientComponents.ts +10 -0
  168. package/dist/templates/vanilla/packages/client/src/mud/createSystemCalls.ts +21 -0
  169. package/dist/templates/vanilla/packages/client/src/mud/getNetworkConfig.ts +53 -0
  170. package/dist/templates/vanilla/packages/client/src/mud/setup.ts +16 -0
  171. package/dist/templates/vanilla/packages/client/src/mud/setupNetwork.ts +102 -0
  172. package/dist/templates/vanilla/packages/client/src/mud/supportedChains.ts +5 -0
  173. package/dist/templates/vanilla/packages/client/src/mud/world.ts +3 -0
  174. package/dist/templates/vanilla/packages/client/tsconfig.json +18 -0
  175. package/dist/templates/{minimal → vanilla}/packages/client/vite.config.ts +3 -0
  176. package/dist/templates/vanilla/packages/contracts/.env +8 -0
  177. package/dist/templates/vanilla/packages/contracts/.gitignore +11 -0
  178. package/dist/templates/vanilla/packages/contracts/.prettierrc +8 -0
  179. package/dist/templates/vanilla/packages/contracts/.solhint.json +12 -0
  180. package/dist/templates/vanilla/packages/contracts/foundry.toml +22 -0
  181. package/dist/templates/vanilla/packages/contracts/mud.config.ts +10 -0
  182. package/dist/templates/vanilla/packages/contracts/package.json +45 -0
  183. package/dist/templates/vanilla/packages/contracts/remappings.txt +3 -0
  184. package/dist/templates/vanilla/packages/contracts/script/PostDeploy.s.sol +24 -0
  185. package/dist/templates/vanilla/packages/contracts/src/codegen/Tables.sol +6 -0
  186. package/dist/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +120 -0
  187. package/dist/templates/vanilla/packages/contracts/src/codegen/world/IIncrementSystem.sol +8 -0
  188. package/dist/templates/vanilla/packages/contracts/src/codegen/world/IWorld.sol +16 -0
  189. package/dist/templates/vanilla/packages/contracts/src/systems/IncrementSystem.sol +14 -0
  190. package/dist/templates/vanilla/packages/contracts/test/CounterTest.t.sol +38 -0
  191. package/dist/templates/vanilla/packages/contracts/tsconfig.json +13 -0
  192. package/dist/templates/vanilla/packages/contracts/worlds.json +5 -0
  193. package/dist/templates/vanilla/pnpm-workspace.yaml +2 -0
  194. package/package.json +14 -11
  195. package/dist/templates/minimal/package.json +0 -18
  196. package/dist/templates/minimal/packages/client/package.json +0 -37
  197. package/dist/templates/minimal/packages/client/src/config.ts +0 -22
  198. package/dist/templates/minimal/packages/client/src/index.ts +0 -37
  199. package/dist/templates/minimal/packages/contracts/chainSpec.json +0 -5
  200. package/dist/templates/minimal/packages/contracts/deploy.json +0 -4
  201. package/dist/templates/minimal/packages/contracts/exports.sh +0 -22
  202. package/dist/templates/minimal/packages/contracts/foundry.toml +0 -11
  203. package/dist/templates/minimal/packages/contracts/package.json +0 -40
  204. package/dist/templates/minimal/packages/contracts/remappings.txt +0 -9
  205. package/dist/templates/minimal/packages/contracts/src/components/CounterComponent.sol +0 -9
  206. package/dist/templates/minimal/packages/contracts/src/libraries/LibMath.sol +0 -10
  207. package/dist/templates/minimal/packages/contracts/src/systems/IncrementSystem.sol +0 -22
  208. package/dist/templates/minimal/packages/contracts/src/systems/README.md +0 -7
  209. package/dist/templates/minimal/packages/contracts/src/test/Deploy.sol +0 -19
  210. package/dist/templates/minimal/packages/contracts/src/test/Deploy.t.sol +0 -14
  211. package/dist/templates/minimal/packages/contracts/src/test/LibDeploy.sol +0 -22
  212. package/dist/templates/minimal/packages/contracts/tsconfig.json +0 -12
  213. package/dist/templates/react/packages/client/src/config.ts +0 -22
  214. package/dist/templates/react/packages/contracts/chainSpec.json +0 -5
  215. package/dist/templates/react/packages/contracts/deploy.json +0 -4
  216. package/dist/templates/react/packages/contracts/exports.sh +0 -22
  217. package/dist/templates/react/packages/contracts/src/components/CounterComponent.sol +0 -9
  218. package/dist/templates/react/packages/contracts/src/libraries/LibMath.sol +0 -10
  219. package/dist/templates/react/packages/contracts/src/systems/README.md +0 -7
  220. package/dist/templates/react/packages/contracts/src/test/Deploy.sol +0 -19
  221. package/dist/templates/react/packages/contracts/src/test/Deploy.t.sol +0 -14
  222. package/dist/templates/react/packages/contracts/src/test/LibDeploy.sol +0 -22
  223. /package/dist/templates/{minimal → phaser}/.gitignore +0 -0
  224. /package/dist/templates/{minimal → phaser}/.vscode/extensions.json +0 -0
  225. /package/dist/templates/{minimal → phaser}/.vscode/settings.json +0 -0
  226. /package/dist/templates/{minimal → phaser}/packages/client/.gitignore +0 -0
  227. /package/dist/templates/{minimal → phaser}/packages/contracts/.prettierrc +0 -0
  228. /package/dist/templates/{minimal → phaser}/pnpm-workspace.yaml +0 -0
  229. /package/dist/templates/{minimal → vanilla}/packages/client/index.html +0 -0
@@ -0,0 +1,10 @@
1
+ import { SetupNetworkResult } from "./setupNetwork";
2
+
3
+ export type ClientComponents = ReturnType<typeof createClientComponents>;
4
+
5
+ export function createClientComponents({ components }: SetupNetworkResult) {
6
+ return {
7
+ ...components,
8
+ // add your client components or overrides here
9
+ };
10
+ }
@@ -0,0 +1,21 @@
1
+ import { getComponentValue } from "@latticexyz/recs";
2
+ import { awaitStreamValue } from "@latticexyz/utils";
3
+ import { ClientComponents } from "./createClientComponents";
4
+ import { SetupNetworkResult } from "./setupNetwork";
5
+
6
+ export type SystemCalls = ReturnType<typeof createSystemCalls>;
7
+
8
+ export function createSystemCalls(
9
+ { worldSend, txReduced$, singletonEntity }: SetupNetworkResult,
10
+ { Counter }: ClientComponents
11
+ ) {
12
+ const increment = async () => {
13
+ const tx = await worldSend("increment", []);
14
+ await awaitStreamValue(txReduced$, (txHash) => txHash === tx.hash);
15
+ return getComponentValue(Counter, singletonEntity);
16
+ };
17
+
18
+ return {
19
+ increment,
20
+ };
21
+ }
@@ -0,0 +1,53 @@
1
+ import { SetupContractConfig, getBurnerWallet } from "@latticexyz/std-client";
2
+ import worldsJson from "contracts/worlds.json";
3
+ import { supportedChains } from "./supportedChains";
4
+
5
+ const worlds = worldsJson as Partial<Record<string, { address: string; blockNumber?: number }>>;
6
+
7
+ type NetworkConfig = SetupContractConfig & {
8
+ privateKey: string;
9
+ faucetServiceUrl?: string;
10
+ snapSync?: boolean;
11
+ };
12
+
13
+ export async function getNetworkConfig(): Promise<NetworkConfig> {
14
+ const params = new URLSearchParams(window.location.search);
15
+
16
+ const chainId = Number(params.get("chainId") || import.meta.env.VITE_CHAIN_ID || 31337);
17
+ const chainIndex = supportedChains.findIndex((c) => c.id === chainId);
18
+ const chain = supportedChains[chainIndex];
19
+ if (!chain) {
20
+ throw new Error(`Chain ${chainId} not found`);
21
+ }
22
+
23
+ const world = worlds[chain.id.toString()];
24
+ const worldAddress = params.get("worldAddress") || world?.address;
25
+ if (!worldAddress) {
26
+ throw new Error(`No world address found for chain ${chainId}. Did you run \`mud deploy\`?`);
27
+ }
28
+
29
+ const initialBlockNumber = params.has("initialBlockNumber")
30
+ ? Number(params.get("initialBlockNumber"))
31
+ : world?.blockNumber ?? -1; // -1 will attempt to find the block number from RPC
32
+
33
+ return {
34
+ clock: {
35
+ period: 1000,
36
+ initialTime: 0,
37
+ syncInterval: 5000,
38
+ },
39
+ provider: {
40
+ chainId,
41
+ jsonRpcUrl: params.get("rpc") ?? chain.rpcUrls.default.http[0],
42
+ wsRpcUrl: params.get("wsRpc") ?? chain.rpcUrls.default.webSocket?.[0],
43
+ },
44
+ privateKey: getBurnerWallet().value,
45
+ chainId,
46
+ modeUrl: params.get("mode") ?? chain.modeUrl,
47
+ faucetServiceUrl: params.get("faucet") ?? chain.faucetUrl,
48
+ worldAddress,
49
+ initialBlockNumber,
50
+ snapSync: params.get("snapSync") === "true",
51
+ disableCache: params.get("cache") === "false",
52
+ };
53
+ }
@@ -0,0 +1,16 @@
1
+ import { createClientComponents } from "./createClientComponents";
2
+ import { createSystemCalls } from "./createSystemCalls";
3
+ import { setupNetwork } from "./setupNetwork";
4
+
5
+ export type SetupResult = Awaited<ReturnType<typeof setup>>;
6
+
7
+ export async function setup() {
8
+ const network = await setupNetwork();
9
+ const components = createClientComponents(network);
10
+ const systemCalls = createSystemCalls(network, components);
11
+ return {
12
+ network,
13
+ components,
14
+ systemCalls,
15
+ };
16
+ }
@@ -0,0 +1,102 @@
1
+ import { setupMUDV2Network } from "@latticexyz/std-client";
2
+ import { createFastTxExecutor, createFaucetService, getSnapSyncRecords } from "@latticexyz/network";
3
+ import { getNetworkConfig } from "./getNetworkConfig";
4
+ import { defineContractComponents } from "./contractComponents";
5
+ import { world } from "./world";
6
+ import { Contract, Signer, utils } from "ethers";
7
+ import { JsonRpcProvider } from "@ethersproject/providers";
8
+ import { IWorld__factory } from "contracts/types/ethers-contracts/factories/IWorld__factory";
9
+ import { getTableIds } from "@latticexyz/utils";
10
+ import storeConfig from "contracts/mud.config";
11
+
12
+ export type SetupNetworkResult = Awaited<ReturnType<typeof setupNetwork>>;
13
+
14
+ export async function setupNetwork() {
15
+ const contractComponents = defineContractComponents(world);
16
+ const networkConfig = await getNetworkConfig();
17
+ const result = await setupMUDV2Network<typeof contractComponents, typeof storeConfig>({
18
+ networkConfig,
19
+ world,
20
+ contractComponents,
21
+ syncThread: "main",
22
+ storeConfig,
23
+ worldAbi: IWorld__factory.abi,
24
+ });
25
+
26
+ // Request drip from faucet
27
+ const signer = result.network.signer.get();
28
+ if (networkConfig.faucetServiceUrl && signer) {
29
+ const address = await signer.getAddress();
30
+ console.info("[Dev Faucet]: Player address -> ", address);
31
+
32
+ const faucet = createFaucetService(networkConfig.faucetServiceUrl);
33
+
34
+ const requestDrip = async () => {
35
+ const balance = await signer.getBalance();
36
+ console.info(`[Dev Faucet]: Player balance -> ${balance}`);
37
+ const lowBalance = balance?.lte(utils.parseEther("1"));
38
+ if (lowBalance) {
39
+ console.info("[Dev Faucet]: Balance is low, dripping funds to player");
40
+ // Double drip
41
+ await faucet.dripDev({ address });
42
+ await faucet.dripDev({ address });
43
+ }
44
+ };
45
+
46
+ requestDrip();
47
+ // Request a drip every 20 seconds
48
+ setInterval(requestDrip, 20000);
49
+ }
50
+
51
+ const provider = result.network.providers.get().json;
52
+ const signerOrProvider = signer ?? provider;
53
+ // Create a World contract instance
54
+ const worldContract = IWorld__factory.connect(networkConfig.worldAddress, signerOrProvider);
55
+
56
+ if (networkConfig.snapSync) {
57
+ const currentBlockNumber = await provider.getBlockNumber();
58
+ const tableRecords = await getSnapSyncRecords(
59
+ networkConfig.worldAddress,
60
+ getTableIds(storeConfig),
61
+ currentBlockNumber,
62
+ signerOrProvider
63
+ );
64
+
65
+ console.log(`Syncing ${tableRecords.length} records`);
66
+ result.startSync(tableRecords, currentBlockNumber);
67
+ } else {
68
+ result.startSync();
69
+ }
70
+
71
+ // Create a fast tx executor
72
+ const fastTxExecutor =
73
+ signer?.provider instanceof JsonRpcProvider
74
+ ? await createFastTxExecutor(signer as Signer & { provider: JsonRpcProvider })
75
+ : null;
76
+
77
+ // TODO: infer this from fastTxExecute signature?
78
+ type BoundFastTxExecuteFn<C extends Contract> = <F extends keyof C>(
79
+ func: F,
80
+ args: Parameters<C[F]>,
81
+ options?: {
82
+ retryCount?: number;
83
+ }
84
+ ) => Promise<ReturnType<C[F]>>;
85
+
86
+ function bindFastTxExecute<C extends Contract>(contract: C): BoundFastTxExecuteFn<C> {
87
+ return async function (...args) {
88
+ if (!fastTxExecutor) {
89
+ throw new Error("no signer");
90
+ }
91
+ const { tx } = await fastTxExecutor.fastTxExecute(contract, ...args);
92
+ return await tx;
93
+ };
94
+ }
95
+
96
+ return {
97
+ ...result,
98
+ worldContract,
99
+ worldSend: bindFastTxExecute(worldContract),
100
+ fastTxExecutor,
101
+ };
102
+ }
@@ -0,0 +1,5 @@
1
+ import { MUDChain, latticeTestnet } from "@latticexyz/common/chains";
2
+ import { foundry } from "@wagmi/chains";
3
+
4
+ // If you are deploying to chains other than anvil or Lattice testnet, add them here
5
+ export const supportedChains: MUDChain[] = [foundry, latticeTestnet];
@@ -0,0 +1,3 @@
1
+ import { createWorld } from "@latticexyz/recs";
2
+
3
+ export const world = createWorld();
@@ -0,0 +1,38 @@
1
+ import { createStore } from "zustand/vanilla";
2
+ import createReactStore from "zustand";
3
+ import { NetworkLayer } from "./layers/network/createNetworkLayer";
4
+ import { PhaserLayer } from "./layers/phaser/createPhaserLayer";
5
+
6
+ export type Store = {
7
+ networkLayer: NetworkLayer | null;
8
+ phaserLayer: PhaserLayer | null;
9
+ devMode: boolean;
10
+ };
11
+
12
+ export type UIStore = {
13
+ networkLayer: NetworkLayer;
14
+ phaserLayer: PhaserLayer;
15
+ devMode: boolean;
16
+ };
17
+
18
+ export const store = createStore<Store>(() => ({
19
+ networkLayer: null,
20
+ phaserLayer: null,
21
+ devMode: false,
22
+ }));
23
+
24
+ export const useStore = createReactStore(store);
25
+
26
+ export const useMUD = () => {
27
+ const { networkLayer, phaserLayer, devMode } = useStore();
28
+
29
+ if (networkLayer === null || phaserLayer === null) {
30
+ throw new Error("Store not initialized");
31
+ }
32
+
33
+ return {
34
+ networkLayer,
35
+ phaserLayer,
36
+ devMode,
37
+ } as UIStore;
38
+ };
@@ -0,0 +1,23 @@
1
+ import { useEffect } from "react";
2
+ import { useNetworkLayer } from "./hooks/useNetworkLayer";
3
+ import { useStore } from "../store";
4
+ import { PhaserLayer } from "./PhaserLayer";
5
+ import { UIRoot } from "./UIRoot";
6
+
7
+ export const App = () => {
8
+ const networkLayer = useNetworkLayer();
9
+
10
+ useEffect(() => {
11
+ if (networkLayer) {
12
+ useStore.setState({ networkLayer });
13
+ }
14
+ }, [networkLayer]);
15
+
16
+ return (
17
+ <div>
18
+ <PhaserLayer networkLayer={networkLayer} />
19
+
20
+ <UIRoot />
21
+ </div>
22
+ );
23
+ };
@@ -0,0 +1,42 @@
1
+ import React from "react";
2
+ import styled from "styled-components";
3
+
4
+ type Props = {
5
+ children: React.ReactNode;
6
+ };
7
+
8
+ export const BootScreen = ({ children }: Props) => {
9
+ return (
10
+ <Container>
11
+ <div>
12
+ <>{children || <>&nbsp;</>}</>
13
+ </div>
14
+ </Container>
15
+ );
16
+ };
17
+
18
+ const Container = styled.div`
19
+ width: 100%;
20
+ height: 100%;
21
+ position: absolute;
22
+ background-color: rgb(0 0 0 / 100%);
23
+ display: grid;
24
+ align-content: center;
25
+ align-items: center;
26
+ justify-content: center;
27
+ justify-items: center;
28
+ transition: all 2s ease;
29
+ grid-gap: 50px;
30
+ z-index: 100;
31
+ pointer-events: none;
32
+ color: white;
33
+
34
+ div {
35
+ font-family: "Lattice Pixel", sans-serif;
36
+ }
37
+
38
+ img {
39
+ transition: all 2s ease;
40
+ width: 100px;
41
+ }
42
+ `;
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import styled from "styled-components";
3
+
4
+ export const LoadingBar: React.FC<{ percentage: number; className?: string }> = ({ percentage, className }) => {
5
+ return (
6
+ <Wrapper className={className}>
7
+ <Inner percentage={percentage} />
8
+ </Wrapper>
9
+ );
10
+ };
11
+
12
+ const Wrapper = styled.div`
13
+ position: relative;
14
+ height: 4px;
15
+ background-color: #2a2a2a;
16
+ `;
17
+ const Inner = styled.div<{ percentage: number }>`
18
+ height: 100%;
19
+ width: ${(p) => p.percentage}%;
20
+ background-color: #fff;
21
+ `;
@@ -0,0 +1,52 @@
1
+ import React from "react";
2
+ import styled from "styled-components";
3
+ import { SyncState } from "@latticexyz/network";
4
+ import { LoadingBar } from "./LoadingBar";
5
+ import { BootScreen } from "./BootScreen";
6
+ import { useComponentValue } from "@latticexyz/react";
7
+ import { useMUD } from "../../store";
8
+
9
+ export const LoadingScreen = () => {
10
+ const {
11
+ networkLayer: {
12
+ components: { LoadingState },
13
+ singletonEntity,
14
+ },
15
+ } = useMUD();
16
+
17
+ const loadingState = useComponentValue(LoadingState, singletonEntity, {
18
+ msg: "Connecting...",
19
+ percentage: 0,
20
+ state: SyncState.CONNECTING,
21
+ });
22
+
23
+ if (loadingState.state === SyncState.LIVE) {
24
+ return null;
25
+ }
26
+
27
+ return (
28
+ <BootScreen>
29
+ {loadingState.msg}
30
+ <LoadingContainer>
31
+ {Math.floor(loadingState.percentage)}%
32
+ <Loading percentage={loadingState.percentage} />
33
+ </LoadingContainer>
34
+ </BootScreen>
35
+ );
36
+ };
37
+
38
+ const LoadingContainer = styled.div`
39
+ display: grid;
40
+ justify-items: start;
41
+ justify-content: start;
42
+ align-items: center;
43
+ height: 30px;
44
+ width: 100%;
45
+ grid-gap: 20px;
46
+ grid-template-columns: auto 1fr;
47
+ `;
48
+
49
+ const Loading = styled(LoadingBar)`
50
+ width: 100%;
51
+ min-width: 200px;
52
+ `;
@@ -0,0 +1 @@
1
+ export * from "./LoadingScreen";
@@ -0,0 +1,20 @@
1
+ import React, { useEffect } from "react";
2
+ import { NetworkLayer } from "../layers/network/createNetworkLayer";
3
+ import { useStore } from "../store";
4
+ import { usePhaserLayer } from "./hooks/usePhaserLayer";
5
+
6
+ type Props = {
7
+ networkLayer: NetworkLayer | null;
8
+ };
9
+
10
+ export const PhaserLayer = ({ networkLayer }: Props) => {
11
+ const { ref: phaserRef, phaserLayer } = usePhaserLayer({ networkLayer });
12
+
13
+ useEffect(() => {
14
+ if (phaserLayer) {
15
+ useStore.setState({ phaserLayer });
16
+ }
17
+ }, [phaserLayer]);
18
+
19
+ return <div ref={phaserRef} />;
20
+ };
@@ -0,0 +1,20 @@
1
+ import { useStore } from "../store";
2
+ import { LoadingScreen } from "./LoadingScreen";
3
+ import { Wrapper } from "./Wrapper";
4
+
5
+ export const UIRoot = () => {
6
+ const layers = useStore((state) => {
7
+ return {
8
+ networkLayer: state.networkLayer,
9
+ phaserLayer: state.phaserLayer,
10
+ };
11
+ });
12
+
13
+ if (!layers.networkLayer || !layers.phaserLayer) return <></>;
14
+
15
+ return (
16
+ <Wrapper>
17
+ <LoadingScreen />
18
+ </Wrapper>
19
+ );
20
+ };
@@ -0,0 +1,5 @@
1
+ import styled from "styled-components";
2
+
3
+ export const Wrapper = styled.div`
4
+ pointer-events: none;
5
+ `;
@@ -0,0 +1,17 @@
1
+ import { useEffect, useMemo } from "react";
2
+ import { createNetworkLayer } from "../../layers/network/createNetworkLayer";
3
+ import { usePromiseValue } from "./usePromiseValue";
4
+
5
+ export const useNetworkLayer = () => {
6
+ const networkLayerPromise = useMemo(() => {
7
+ return createNetworkLayer();
8
+ }, []);
9
+
10
+ useEffect(() => {
11
+ return () => {
12
+ networkLayerPromise.then((networkLayer) => networkLayer.world.dispose());
13
+ };
14
+ }, [networkLayerPromise]);
15
+
16
+ return usePromiseValue(networkLayerPromise);
17
+ };
@@ -0,0 +1,87 @@
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import useResizeObserver, { ResizeHandler } from "use-resize-observer";
3
+ import { throttle } from "lodash";
4
+ import { createPhaserLayer } from "../../layers/phaser/createPhaserLayer";
5
+ import { NetworkLayer } from "../../layers/network/createNetworkLayer";
6
+ import { usePromiseValue } from "./usePromiseValue";
7
+ import { phaserConfig } from "../../layers/phaser/configurePhaser";
8
+
9
+ const createContainer = () => {
10
+ const container = document.createElement("div");
11
+ container.style.width = "100vw";
12
+ container.style.height = "100vh";
13
+ container.style.pointerEvents = "all";
14
+ container.style.overflow = "hidden";
15
+ return container;
16
+ };
17
+
18
+ type Props = {
19
+ networkLayer: NetworkLayer | null;
20
+ };
21
+
22
+ export const usePhaserLayer = ({ networkLayer }: Props) => {
23
+ const parentRef = useRef<HTMLElement | null>(null);
24
+ const [{ width, height }, setSize] = useState({ width: 0, height: 0 });
25
+
26
+ const { phaserLayerPromise, container } = useMemo(() => {
27
+ if (!networkLayer) return { phaserLayerPromise: null, container: null };
28
+
29
+ const container = createContainer();
30
+ if (parentRef.current) {
31
+ parentRef.current.appendChild(container);
32
+ }
33
+
34
+ return {
35
+ container,
36
+ phaserLayerPromise: createPhaserLayer(networkLayer, {
37
+ ...phaserConfig,
38
+ scale: {
39
+ ...phaserConfig.scale,
40
+ parent: container,
41
+ mode: Phaser.Scale.NONE,
42
+ width,
43
+ height,
44
+ },
45
+ }),
46
+ };
47
+
48
+ // We don't want width/height to recreate phaser layer, so we ignore linter
49
+ // eslint-disable-next-line react-hooks/exhaustive-deps
50
+ }, [networkLayer]);
51
+
52
+ useEffect(() => {
53
+ return () => {
54
+ phaserLayerPromise?.then((phaserLayer) => phaserLayer.world.dispose());
55
+ container?.remove();
56
+ };
57
+ }, [container, phaserLayerPromise]);
58
+
59
+ const phaserLayer = usePromiseValue(phaserLayerPromise);
60
+
61
+ const onResize = useMemo<ResizeHandler>(() => {
62
+ return throttle(({ width, height }) => {
63
+ setSize({ width: width ?? 0, height: height ?? 0 });
64
+ }, 500);
65
+ }, []);
66
+
67
+ useResizeObserver({
68
+ ref: container,
69
+ onResize,
70
+ });
71
+
72
+ const ref = useCallback(
73
+ (el: HTMLElement | null) => {
74
+ parentRef.current = el;
75
+ if (container) {
76
+ if (parentRef.current) {
77
+ parentRef.current.appendChild(container);
78
+ } else {
79
+ container.remove();
80
+ }
81
+ }
82
+ },
83
+ [container]
84
+ );
85
+
86
+ return useMemo(() => ({ ref, phaserLayer }), [ref, phaserLayer]);
87
+ };
@@ -0,0 +1,24 @@
1
+ import { useEffect, useState, useRef } from "react";
2
+
3
+ export const usePromiseValue = <T>(promise: Promise<T> | null) => {
4
+ const promiseRef = useRef<typeof promise>(promise);
5
+ const [value, setValue] = useState<T | null>(null);
6
+ useEffect(() => {
7
+ if (!promise) return;
8
+ let isMounted = true;
9
+ promiseRef.current = promise;
10
+ // TODO: do something with promise errors?
11
+ promise.then((resolvedValue) => {
12
+ // skip if unmounted (state changes will cause errors otherwise)
13
+ if (!isMounted) return;
14
+ // If our promise was replaced before it resolved, ignore the result
15
+ if (promiseRef.current !== promise) return;
16
+
17
+ setValue(resolvedValue);
18
+ });
19
+ return () => {
20
+ isMounted = false;
21
+ };
22
+ }, [promise]);
23
+ return value;
24
+ };
@@ -0,0 +1,18 @@
1
+ import { DetailedHTMLProps, HTMLAttributes } from "react";
2
+
3
+ type Props = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
4
+
5
+ /**
6
+ * Wrap any piece of UI that needs to receive click events with this.
7
+ * Make sure it is unmounted when the click events are no longer needed.
8
+ */
9
+ export const ClickWrapper = (props: Props) => {
10
+ const { children, style } = props;
11
+ const newStyle = { pointerEvents: "all", ...style } as Record<string, string>;
12
+
13
+ return (
14
+ <div {...props} style={newStyle}>
15
+ {children}
16
+ </div>
17
+ );
18
+ };
@@ -0,0 +1,52 @@
1
+ import { Sprites } from "../../layers/phaser/constants";
2
+ import atlasJson from "../../../public/assets/atlases/atlas.json";
3
+ import { useMUD } from "../../store";
4
+
5
+ export const SpriteImage = ({ spriteKey, scale }: { spriteKey: Sprites; scale?: number }) => {
6
+ const {
7
+ phaserLayer: {
8
+ scenes: {
9
+ Main: {
10
+ config: { sprites },
11
+ },
12
+ },
13
+ },
14
+ } = useMUD();
15
+
16
+ const imageScale = scale ?? 1;
17
+ const sprite = sprites[spriteKey];
18
+ const frame = sprite.frame;
19
+
20
+ const atlasDimensions = atlasJson.textures[0].size;
21
+ const spriteAtlasEntry = atlasJson.textures[0].frames.find((atlasFrame) => atlasFrame.filename === frame);
22
+
23
+ if (!spriteAtlasEntry) throw new Error(`Could not find sprite ${spriteKey} in atlas`);
24
+
25
+ const containerStyle = {
26
+ width: `${spriteAtlasEntry.sourceSize.w * imageScale}px`,
27
+ height: `${spriteAtlasEntry.sourceSize.h * imageScale}px`,
28
+ overflow: "hidden",
29
+ position: "relative",
30
+ } as Record<string, string>;
31
+
32
+ const imgStyle = {
33
+ imageRendering: "pixelated",
34
+ maxWidth: `${atlasDimensions.w * imageScale}px`,
35
+ maxHeight: `${atlasDimensions.h * imageScale}px`,
36
+ height: `${atlasDimensions.h * imageScale}px`,
37
+ width: `${atlasDimensions.w * imageScale}px`,
38
+ marginTop: `-${spriteAtlasEntry.frame.y * imageScale}px`,
39
+ marginLeft: `-${spriteAtlasEntry.frame.x * imageScale}px`,
40
+ clipPath: `inset(${spriteAtlasEntry.frame.y + 1}px ${
41
+ atlasDimensions.w - (spriteAtlasEntry.frame.x + spriteAtlasEntry.sourceSize.w)
42
+ }px ${atlasDimensions.h - (spriteAtlasEntry.frame.y + spriteAtlasEntry.sourceSize.h)}px ${
43
+ spriteAtlasEntry.frame.x
44
+ }px)`,
45
+ } as Record<string, string>;
46
+
47
+ return (
48
+ <div style={containerStyle}>
49
+ <img src="assets/atlases/atlas.png" style={imgStyle} />
50
+ </div>
51
+ );
52
+ };
@@ -11,10 +11,9 @@
11
11
  "isolatedModules": true,
12
12
  "esModuleInterop": true,
13
13
  "noEmit": true,
14
- "noUnusedLocals": true,
15
- "noUnusedParameters": true,
16
- "noImplicitReturns": true,
17
- "skipLibCheck": true
14
+ "skipLibCheck": true,
15
+ "jsx": "react-jsx",
16
+ "jsxImportSource": "react"
18
17
  },
19
18
  "include": ["src"]
20
19
  }