create-mud 2.2.15-6aff69a91c627ddcc0c1dbccf7b71580e8e0a8fa → 2.2.15-7482a5ae322f26278722081838b6103ce6d264e6

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 (46) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/templates/react/gitignore +14 -5
  4. package/dist/templates/react/mprocs.yaml +9 -1
  5. package/dist/templates/react/package.json +28 -4
  6. package/dist/templates/react/packages/client/gitignore +0 -2
  7. package/dist/templates/react/packages/client/package.json +21 -12
  8. package/dist/templates/react/packages/client/postcss.config.cjs +6 -0
  9. package/dist/templates/react/packages/client/src/App.tsx +38 -100
  10. package/dist/templates/react/packages/client/src/GameMap.tsx +78 -0
  11. package/dist/templates/react/packages/client/src/Providers.tsx +44 -0
  12. package/dist/templates/react/packages/client/src/common.ts +6 -0
  13. package/dist/templates/react/packages/client/src/index.tsx +17 -31
  14. package/dist/templates/react/packages/client/src/mud/Explorer.tsx +32 -0
  15. package/dist/templates/react/packages/client/src/mud/getWorldDeploy.ts +23 -0
  16. package/dist/templates/react/packages/client/src/mud/stash.ts +4 -0
  17. package/dist/templates/react/packages/client/src/mud/useSyncProgress.ts +21 -0
  18. package/dist/templates/react/packages/client/src/mud/useWorldContract.ts +45 -0
  19. package/dist/templates/react/packages/client/src/ui/icons/ArrowDownIcon.tsx +22 -0
  20. package/dist/templates/react/packages/client/src/ui/icons/MUDIcon.tsx +25 -0
  21. package/dist/templates/react/packages/client/src/useKeyboardMovement.ts +26 -0
  22. package/dist/templates/react/packages/client/src/wagmiConfig.ts +49 -0
  23. package/dist/templates/react/packages/client/tailwind.config.ts +10 -0
  24. package/dist/templates/react/packages/client/vite.config.ts +0 -6
  25. package/dist/templates/react/packages/contracts/gitignore +12 -8
  26. package/dist/templates/react/packages/contracts/mud.config.ts +13 -8
  27. package/dist/templates/react/packages/contracts/out/IWorld.sol/IWorld.abi.json +2021 -0
  28. package/dist/templates/react/packages/contracts/package.json +8 -7
  29. package/dist/templates/react/packages/contracts/script/PostDeploy.s.sol +1 -9
  30. package/dist/templates/react/packages/contracts/src/MoveSystem.sol +26 -0
  31. package/dist/templates/react/packages/contracts/src/codegen/common.sol +11 -0
  32. package/dist/templates/react/packages/contracts/src/codegen/index.sol +1 -1
  33. package/dist/templates/react/packages/contracts/src/codegen/tables/Position.sol +318 -0
  34. package/dist/templates/react/packages/contracts/src/codegen/world/{ITasksSystem.sol → IMoveSystem.sol} +5 -9
  35. package/dist/templates/react/packages/contracts/src/codegen/world/IWorld.sol +2 -2
  36. package/dist/templates/react/packages/contracts/worlds.json +1 -1
  37. package/package.json +1 -1
  38. package/dist/templates/react/packages/client/src/MUDContext.tsx +0 -21
  39. package/dist/templates/react/packages/client/src/mud/createSystemCalls.ts +0 -56
  40. package/dist/templates/react/packages/client/src/mud/getNetworkConfig.ts +0 -76
  41. package/dist/templates/react/packages/client/src/mud/setup.ts +0 -18
  42. package/dist/templates/react/packages/client/src/mud/setupNetwork.ts +0 -101
  43. package/dist/templates/react/packages/client/src/mud/supportedChains.ts +0 -20
  44. package/dist/templates/react/packages/contracts/src/codegen/tables/Tasks.sol +0 -522
  45. package/dist/templates/react/packages/contracts/src/systems/TasksSystem.sol +0 -24
  46. package/dist/templates/react/packages/contracts/test/TasksTest.t.sol +0 -30
package/dist/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- var l=Object.create;var a=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var d=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty;var f=(e,t,s,p)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of m(t))!u.call(e,r)&&r!==s&&a(e,r,{get:()=>t[r],enumerable:!(p=o(t,r))||p.enumerable});return e};var h=(e,t,s)=>(s=e!=null?l(d(e)):{},f(t||!e||!e.__esModule?a(s,"default",{value:e,enumerable:!0}):s,e));var i=require("create-create-app"),n=h(require("path"));var c={name:"create-mud",version:"2.2.15-6aff69a91c627ddcc0c1dbccf7b71580e8e0a8fa",description:"Create a new MUD project",license:"MIT",author:"Lattice <mud@lattice.xyz>",bin:"dist/cli.js",files:["dist"],scripts:{build:"pnpm run build:js","build:js":"tsup && tsx ./scripts/copy-templates.ts",clean:"pnpm run clean:js","clean:js":"shx rm -rf dist",dev:"tsup --watch",prepublishOnly:"npm run clean && npm run build",test:"pnpm run test:vanilla && pnpm run test:react && pnpm run test:react-ecs && pnpm run test:phaser && pnpm run test:threejs","test:ci":"pnpm run test","test:phaser":"dist/cli.js test-project --template phaser && shx rm -rf test-project","test:react":"dist/cli.js test-project --template react && shx rm -rf test-project","test:react-ecs":"dist/cli.js test-project --template react-ecs && shx rm -rf test-project","test:threejs":"dist/cli.js test-project --template threejs && shx rm -rf test-project","test:vanilla":"dist/cli.js test-project --template vanilla && shx rm -rf test-project"},dependencies:{"create-create-app":"git+https://github.com/holic/create-create-app#74376c59b48a04aabbe94d9cacfe9cb1cecccd63"},devDependencies:{"@types/node":"^18.15.11",execa:"^7.0.0",tsup:"^6.7.0"},publishConfig:{access:"public",registry:"https://registry.npmjs.org"}};var b=n.default.resolve(__dirname,"..","dist","templates");(0,i.create)("create-mud",{templateRoot:b,defaultTemplate:"vanilla",defaultPackageManager:"pnpm",promptForDescription:!1,promptForAuthor:!1,promptForEmail:!1,promptForLicense:!1,promptForTemplate:!0,caveat:({answers:e,packageManager:t})=>`Done! Play in the MUD with \`cd ${e.name}\` and \`${t} run dev\``,extra:{"mud-version":{type:"input",describe:"The version of MUD packages to use, defaults to latest",default:c.version}}});
2
+ var l=Object.create;var a=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var d=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty;var h=(e,t,s,p)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of m(t))!u.call(e,r)&&r!==s&&a(e,r,{get:()=>t[r],enumerable:!(p=o(t,r))||p.enumerable});return e};var j=(e,t,s)=>(s=e!=null?l(d(e)):{},h(t||!e||!e.__esModule?a(s,"default",{value:e,enumerable:!0}):s,e));var i=require("create-create-app"),n=j(require("path"));var c={name:"create-mud",version:"2.2.15-7482a5ae322f26278722081838b6103ce6d264e6",description:"Create a new MUD project",license:"MIT",author:"Lattice <mud@lattice.xyz>",bin:"dist/cli.js",files:["dist"],scripts:{build:"pnpm run build:js","build:js":"tsup && tsx ./scripts/copy-templates.ts",clean:"pnpm run clean:js","clean:js":"shx rm -rf dist",dev:"tsup --watch",prepublishOnly:"npm run clean && npm run build",test:"pnpm run test:vanilla && pnpm run test:react && pnpm run test:react-ecs && pnpm run test:phaser && pnpm run test:threejs","test:ci":"pnpm run test","test:phaser":"dist/cli.js test-project --template phaser && shx rm -rf test-project","test:react":"dist/cli.js test-project --template react && shx rm -rf test-project","test:react-ecs":"dist/cli.js test-project --template react-ecs && shx rm -rf test-project","test:threejs":"dist/cli.js test-project --template threejs && shx rm -rf test-project","test:vanilla":"dist/cli.js test-project --template vanilla && shx rm -rf test-project"},dependencies:{"create-create-app":"git+https://github.com/holic/create-create-app#74376c59b48a04aabbe94d9cacfe9cb1cecccd63"},devDependencies:{"@types/node":"^18.15.11",execa:"^7.0.0",tsup:"^6.7.0"},publishConfig:{access:"public",registry:"https://registry.npmjs.org"}};var b=n.default.resolve(__dirname,"..","dist","templates");(0,i.create)("create-mud",{templateRoot:b,defaultTemplate:"vanilla",defaultPackageManager:"pnpm",promptForDescription:!1,promptForAuthor:!1,promptForEmail:!1,promptForLicense:!1,promptForTemplate:!0,caveat:({answers:e,packageManager:t})=>`Done! Play in the MUD with \`cd ${e.name}\` and \`${t} run dev\``,extra:{"mud-version":{type:"input",describe:"The version of MUD packages to use, defaults to latest",default:c.version}}});
3
3
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { create } from \"create-create-app\";\nimport path from \"node:path\";\nimport packageJson from \"../package.json\";\n\nconst templateRoot = path.resolve(__dirname, \"..\", \"dist\", \"templates\");\n\n// See https://github.com/uetchy/create-create-app/blob/master/README.md for other options.\ncreate(\"create-mud\", {\n templateRoot,\n defaultTemplate: \"vanilla\",\n // templates use pnpm workspaces, so default to that for now\n // not sure if it's worth trying to support multiple kinds of package managers for monorepos, given the tooling is so different\n defaultPackageManager: \"pnpm\",\n promptForDescription: false,\n promptForAuthor: false,\n promptForEmail: false,\n promptForLicense: false,\n promptForTemplate: true,\n caveat: ({ answers, packageManager }) =>\n `Done! Play in the MUD with \\`cd ${answers.name}\\` and \\`${packageManager} run dev\\``,\n extra: {\n \"mud-version\": {\n type: \"input\",\n describe: \"The version of MUD packages to use, defaults to latest\",\n default: packageJson.version,\n },\n },\n});\n","{\n \"name\": \"create-mud\",\n \"version\": \"2.2.15-6aff69a91c627ddcc0c1dbccf7b71580e8e0a8fa\",\n \"description\": \"Create a new MUD project\",\n \"license\": \"MIT\",\n \"author\": \"Lattice <mud@lattice.xyz>\",\n \"bin\": \"dist/cli.js\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"pnpm run build:js\",\n \"build:js\": \"tsup && tsx ./scripts/copy-templates.ts\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"shx rm -rf dist\",\n \"dev\": \"tsup --watch\",\n \"prepublishOnly\": \"npm run clean && npm run build\",\n \"test\": \"pnpm run test:vanilla && pnpm run test:react && pnpm run test:react-ecs && pnpm run test:phaser && pnpm run test:threejs\",\n \"test:ci\": \"pnpm run test\",\n \"test:phaser\": \"dist/cli.js test-project --template phaser && shx rm -rf test-project\",\n \"test:react\": \"dist/cli.js test-project --template react && shx rm -rf test-project\",\n \"test:react-ecs\": \"dist/cli.js test-project --template react-ecs && shx rm -rf test-project\",\n \"test:threejs\": \"dist/cli.js test-project --template threejs && shx rm -rf test-project\",\n \"test:vanilla\": \"dist/cli.js test-project --template vanilla && shx rm -rf test-project\"\n },\n \"dependencies\": {\n \"create-create-app\": \"git+https://github.com/holic/create-create-app#74376c59b48a04aabbe94d9cacfe9cb1cecccd63\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^18.15.11\",\n \"execa\": \"^7.0.0\",\n \"tsup\": \"^6.7.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n}\n"],"mappings":";2cACA,IAAAA,EAAuB,6BACvBC,EAAiB,mBCFjB,IAAAC,EAAA,CACE,KAAQ,aACR,QAAW,kDACX,YAAe,2BACf,QAAW,MACX,OAAU,4BACV,IAAO,cACP,MAAS,CACP,MACF,EACA,QAAW,CACT,MAAS,oBACT,WAAY,0CACZ,MAAS,oBACT,WAAY,kBACZ,IAAO,eACP,eAAkB,iCAClB,KAAQ,2HACR,UAAW,gBACX,cAAe,wEACf,aAAc,uEACd,iBAAkB,2EAClB,eAAgB,yEAChB,eAAgB,wEAClB,EACA,aAAgB,CACd,oBAAqB,yFACvB,EACA,gBAAmB,CACjB,cAAe,YACf,MAAS,SACT,KAAQ,QACV,EACA,cAAiB,CACf,OAAU,SACV,SAAY,4BACd,CACF,EDhCA,IAAMC,EAAe,EAAAC,QAAK,QAAQ,UAAW,KAAM,OAAQ,WAAW,KAGtE,UAAO,aAAc,CACnB,aAAAD,EACA,gBAAiB,UAGjB,sBAAuB,OACvB,qBAAsB,GACtB,gBAAiB,GACjB,eAAgB,GAChB,iBAAkB,GAClB,kBAAmB,GACnB,OAAQ,CAAC,CAAE,QAAAE,EAAS,eAAAC,CAAe,IACjC,mCAAmCD,EAAQ,gBAAgBC,cAC7D,MAAO,CACL,cAAe,CACb,KAAM,QACN,SAAU,yDACV,QAASC,EAAY,OACvB,CACF,CACF,CAAC","names":["import_create_create_app","import_node_path","package_default","templateRoot","path","answers","packageManager","package_default"]}
1
+ {"version":3,"sources":["../src/cli.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { create } from \"create-create-app\";\nimport path from \"node:path\";\nimport packageJson from \"../package.json\";\n\nconst templateRoot = path.resolve(__dirname, \"..\", \"dist\", \"templates\");\n\n// See https://github.com/uetchy/create-create-app/blob/master/README.md for other options.\ncreate(\"create-mud\", {\n templateRoot,\n defaultTemplate: \"vanilla\",\n // templates use pnpm workspaces, so default to that for now\n // not sure if it's worth trying to support multiple kinds of package managers for monorepos, given the tooling is so different\n defaultPackageManager: \"pnpm\",\n promptForDescription: false,\n promptForAuthor: false,\n promptForEmail: false,\n promptForLicense: false,\n promptForTemplate: true,\n caveat: ({ answers, packageManager }) =>\n `Done! Play in the MUD with \\`cd ${answers.name}\\` and \\`${packageManager} run dev\\``,\n extra: {\n \"mud-version\": {\n type: \"input\",\n describe: \"The version of MUD packages to use, defaults to latest\",\n default: packageJson.version,\n },\n },\n});\n","{\n \"name\": \"create-mud\",\n \"version\": \"2.2.15-7482a5ae322f26278722081838b6103ce6d264e6\",\n \"description\": \"Create a new MUD project\",\n \"license\": \"MIT\",\n \"author\": \"Lattice <mud@lattice.xyz>\",\n \"bin\": \"dist/cli.js\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"pnpm run build:js\",\n \"build:js\": \"tsup && tsx ./scripts/copy-templates.ts\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"shx rm -rf dist\",\n \"dev\": \"tsup --watch\",\n \"prepublishOnly\": \"npm run clean && npm run build\",\n \"test\": \"pnpm run test:vanilla && pnpm run test:react && pnpm run test:react-ecs && pnpm run test:phaser && pnpm run test:threejs\",\n \"test:ci\": \"pnpm run test\",\n \"test:phaser\": \"dist/cli.js test-project --template phaser && shx rm -rf test-project\",\n \"test:react\": \"dist/cli.js test-project --template react && shx rm -rf test-project\",\n \"test:react-ecs\": \"dist/cli.js test-project --template react-ecs && shx rm -rf test-project\",\n \"test:threejs\": \"dist/cli.js test-project --template threejs && shx rm -rf test-project\",\n \"test:vanilla\": \"dist/cli.js test-project --template vanilla && shx rm -rf test-project\"\n },\n \"dependencies\": {\n \"create-create-app\": \"git+https://github.com/holic/create-create-app#74376c59b48a04aabbe94d9cacfe9cb1cecccd63\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^18.15.11\",\n \"execa\": \"^7.0.0\",\n \"tsup\": \"^6.7.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org\"\n }\n}\n"],"mappings":";2cACA,IAAAA,EAAuB,6BACvBC,EAAiB,mBCFjB,IAAAC,EAAA,CACE,KAAQ,aACR,QAAW,kDACX,YAAe,2BACf,QAAW,MACX,OAAU,4BACV,IAAO,cACP,MAAS,CACP,MACF,EACA,QAAW,CACT,MAAS,oBACT,WAAY,0CACZ,MAAS,oBACT,WAAY,kBACZ,IAAO,eACP,eAAkB,iCAClB,KAAQ,2HACR,UAAW,gBACX,cAAe,wEACf,aAAc,uEACd,iBAAkB,2EAClB,eAAgB,yEAChB,eAAgB,wEAClB,EACA,aAAgB,CACd,oBAAqB,yFACvB,EACA,gBAAmB,CACjB,cAAe,YACf,MAAS,SACT,KAAQ,QACV,EACA,cAAiB,CACf,OAAU,SACV,SAAY,4BACd,CACF,EDhCA,IAAMC,EAAe,EAAAC,QAAK,QAAQ,UAAW,KAAM,OAAQ,WAAW,KAGtE,UAAO,aAAc,CACnB,aAAAD,EACA,gBAAiB,UAGjB,sBAAuB,OACvB,qBAAsB,GACtB,gBAAiB,GACjB,eAAgB,GAChB,iBAAkB,GAClB,kBAAmB,GACnB,OAAQ,CAAC,CAAE,QAAAE,EAAS,eAAAC,CAAe,IACjC,mCAAmCD,EAAQ,gBAAgBC,cAC7D,MAAO,CACL,cAAe,CACb,KAAM,QACN,SAAU,yDACV,QAASC,EAAY,OACvB,CACF,CACF,CAAC","names":["import_create_create_app","import_node_path","package_default","templateRoot","path","answers","packageManager","package_default"]}
@@ -1,7 +1,16 @@
1
+ .DS_Store
2
+ logs
3
+ *.log
4
+
1
5
  node_modules
2
6
 
3
- # mud artifacts
4
- .mud
5
- # sqlite indexer data
6
- *.db
7
- *.db-journal
7
+ .env.*
8
+
9
+ # foundry
10
+ cache
11
+ broadcast
12
+ out/*
13
+ !out/IWorld.sol
14
+ out/IWorld.sol/*
15
+ !out/IWorld.sol/IWorld.abi.json
16
+ !out/IWorld.sol/IWorld.abi.d.json.ts
@@ -1,3 +1,4 @@
1
+ scrollback: 10000
1
2
  procs:
2
3
  client:
3
4
  cwd: packages/client
@@ -5,9 +6,16 @@ procs:
5
6
  contracts:
6
7
  cwd: packages/contracts
7
8
  shell: pnpm mud dev-contracts --rpc http://127.0.0.1:8545
9
+ deploy-prereqs:
10
+ cwd: packages/contracts
11
+ shell: pnpm deploy-local-prereqs
12
+ env:
13
+ DEBUG: "mud:*"
14
+ # Anvil default account (0x70997970C51812dc3A010C7d01b50e0d17dc79C8)
15
+ PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
8
16
  anvil:
9
17
  cwd: packages/contracts
10
- shell: anvil --base-fee 0 --block-time 2
18
+ shell: anvil --block-time 2
11
19
  explorer:
12
20
  cwd: packages/contracts
13
21
  shell: pnpm explorer
@@ -12,10 +12,10 @@
12
12
  "test": "pnpm recursive run test"
13
13
  },
14
14
  "devDependencies": {
15
- "@latticexyz/cli": "{{mud-version}}",
16
- "@latticexyz/common": "{{mud-version}}",
17
- "@latticexyz/explorer": "{{mud-version}}",
18
- "@latticexyz/store-indexer": "{{mud-version}}",
15
+ "@latticexyz/cli": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
16
+ "@latticexyz/common": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
17
+ "@latticexyz/explorer": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
18
+ "@latticexyz/store-indexer": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
19
19
  "@types/debug": "4.1.7",
20
20
  "@typescript-eslint/eslint-plugin": "7.1.1",
21
21
  "@typescript-eslint/parser": "7.1.1",
@@ -27,5 +27,29 @@
27
27
  "engines": {
28
28
  "node": "^18",
29
29
  "pnpm": "^8 || ^9"
30
+ },
31
+ "pnpm": {
32
+ "overrides": {
33
+ "@latticexyz/abi-ts": "{{mud-version}}",
34
+ "@latticexyz/block-logs-stream": "{{mud-version}}",
35
+ "@latticexyz/cli": "{{mud-version}}",
36
+ "@latticexyz/common": "{{mud-version}}",
37
+ "@latticexyz/config": "{{mud-version}}",
38
+ "@latticexyz/entrykit": "{{mud-version}}",
39
+ "@latticexyz/explorer": "{{mud-version}}",
40
+ "@latticexyz/gas-report": "{{mud-version}}",
41
+ "@latticexyz/paymaster": "{{mud-version}}",
42
+ "@latticexyz/protocol-parser": "{{mud-version}}",
43
+ "@latticexyz/recs": "{{mud-version}}",
44
+ "@latticexyz/schema-type": "{{mud-version}}",
45
+ "@latticexyz/stash": "{{mud-version}}",
46
+ "@latticexyz/store": "{{mud-version}}",
47
+ "@latticexyz/store-indexer": "{{mud-version}}",
48
+ "@latticexyz/store-sync": "{{mud-version}}",
49
+ "@latticexyz/utils": "{{mud-version}}",
50
+ "@latticexyz/world": "{{mud-version}}",
51
+ "@latticexyz/world-module-metadata": "{{mud-version}}",
52
+ "@latticexyz/world-modules": "{{mud-version}}"
53
+ }
30
54
  }
31
55
  }
@@ -1,3 +1 @@
1
- node_modules
2
1
  dist
3
- .DS_Store
@@ -11,25 +11,34 @@
11
11
  "test": "tsc --noEmit"
12
12
  },
13
13
  "dependencies": {
14
- "@latticexyz/common": "{{mud-version}}",
15
- "@latticexyz/dev-tools": "{{mud-version}}",
16
- "@latticexyz/react": "{{mud-version}}",
17
- "@latticexyz/schema-type": "{{mud-version}}",
18
- "@latticexyz/store-sync": "{{mud-version}}",
19
- "@latticexyz/utils": "{{mud-version}}",
20
- "@latticexyz/world": "{{mud-version}}",
14
+ "@latticexyz/common": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
15
+ "@latticexyz/entrykit": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
16
+ "@latticexyz/explorer": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
17
+ "@latticexyz/react": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
18
+ "@latticexyz/schema-type": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
19
+ "@latticexyz/stash": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
20
+ "@latticexyz/store-sync": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
21
+ "@latticexyz/utils": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
22
+ "@latticexyz/world": "2.2.15-f9de085862ac62ce15fe3b7743916cfd631592ea",
23
+ "@tanstack/react-query": "^5.63.0",
21
24
  "contracts": "workspace:*",
22
- "react": "^18.2.0",
23
- "react-dom": "^18.2.0",
25
+ "fast-deep-equal": "^3.1.3",
26
+ "react": "18.2.0",
27
+ "react-dom": "18.2.0",
24
28
  "rxjs": "7.5.5",
25
- "viem": "2.21.19"
29
+ "tailwind-merge": "^2.6.0",
30
+ "viem": "2.21.19",
31
+ "wagmi": "2.12.11"
26
32
  },
27
33
  "devDependencies": {
28
- "@types/react": "18.2.22",
29
- "@types/react-dom": "18.2.7",
34
+ "@types/react": "18.2.0",
35
+ "@types/react-dom": "18.2.0",
30
36
  "@vitejs/plugin-react": "^3.1.0",
37
+ "autoprefixer": "^10.4.20",
31
38
  "eslint-plugin-react": "7.31.11",
32
39
  "eslint-plugin-react-hooks": "4.6.0",
40
+ "postcss": "^8.4.49",
41
+ "tailwindcss": "^3.4.17",
33
42
  "vite": "^4.2.1",
34
43
  "wait-port": "^1.0.4"
35
44
  }
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -1,105 +1,43 @@
1
- import { useMUD } from "./MUDContext";
2
-
3
- const styleUnset = { all: "unset" } as const;
4
-
5
- export const App = () => {
6
- const {
7
- network: { tables, useStore },
8
- systemCalls: { addTask, toggleTask, deleteTask },
9
- } = useMUD();
10
-
11
- const tasks = useStore((state) => {
12
- const records = Object.values(state.getRecords(tables.Tasks));
13
- records.sort((a, b) => Number(a.value.createdAt - b.value.createdAt));
14
- return records;
15
- });
1
+ import { stash } from "./mud/stash";
2
+ import { useSyncProgress } from "./mud/useSyncProgress";
3
+ import { useRecords } from "@latticexyz/stash/react";
4
+ import { AccountButton } from "@latticexyz/entrykit/internal";
5
+ import { Direction } from "./common";
6
+ import mudConfig from "contracts/mud.config";
7
+ import { useMemo } from "react";
8
+ import { GameMap } from "./GameMap";
9
+ import { useWorldContract } from "./mud/useWorldContract";
10
+
11
+ export function App() {
12
+ const { isLive, message, percentage } = useSyncProgress();
13
+
14
+ const players = useRecords({ stash, table: mudConfig.tables.app__Position });
15
+
16
+ const worldContract = useWorldContract();
17
+ const onMove = useMemo(
18
+ () =>
19
+ worldContract
20
+ ? async (direction: Direction) => {
21
+ await worldContract.write.app__move([mudConfig.enums.Direction.indexOf(direction)]);
22
+ }
23
+ : undefined,
24
+ [worldContract],
25
+ );
16
26
 
17
27
  return (
18
28
  <>
19
- <table>
20
- <tbody>
21
- {tasks.map((task) => (
22
- <tr key={task.id}>
23
- <td align="right">
24
- <input
25
- type="checkbox"
26
- checked={task.value.completedAt > 0n}
27
- title={task.value.completedAt === 0n ? "Mark task as completed" : "Mark task as incomplete"}
28
- onChange={async (event) => {
29
- event.preventDefault();
30
- const checkbox = event.currentTarget;
31
-
32
- checkbox.disabled = true;
33
- try {
34
- await toggleTask(task.key.id);
35
- } finally {
36
- checkbox.disabled = false;
37
- }
38
- }}
39
- />
40
- </td>
41
- <td>{task.value.completedAt > 0n ? <s>{task.value.description}</s> : <>{task.value.description}</>}</td>
42
- <td align="right">
43
- <button
44
- type="button"
45
- title="Delete task"
46
- style={styleUnset}
47
- onClick={async (event) => {
48
- event.preventDefault();
49
- if (!window.confirm("Are you sure you want to delete this task?")) return;
50
-
51
- const button = event.currentTarget;
52
- button.disabled = true;
53
- try {
54
- await deleteTask(task.key.id);
55
- } finally {
56
- button.disabled = false;
57
- }
58
- }}
59
- >
60
- &times;
61
- </button>
62
- </td>
63
- </tr>
64
- ))}
65
- </tbody>
66
- <tfoot>
67
- <tr>
68
- <td>
69
- <input type="checkbox" disabled />
70
- </td>
71
- <td colSpan={2}>
72
- <form
73
- onSubmit={async (event) => {
74
- event.preventDefault();
75
- const form = event.currentTarget;
76
- const fieldset = form.querySelector("fieldset");
77
- if (!(fieldset instanceof HTMLFieldSetElement)) return;
78
-
79
- const formData = new FormData(form);
80
- const desc = formData.get("description");
81
- if (typeof desc !== "string") return;
82
-
83
- fieldset.disabled = true;
84
- try {
85
- await addTask(desc);
86
- form.reset();
87
- } finally {
88
- fieldset.disabled = false;
89
- }
90
- }}
91
- >
92
- <fieldset style={styleUnset}>
93
- <input type="text" name="description" />{" "}
94
- <button type="submit" title="Add task">
95
- Add
96
- </button>
97
- </fieldset>
98
- </form>
99
- </td>
100
- </tr>
101
- </tfoot>
102
- </table>
29
+ <div className="fixed inset-0 grid place-items-center p-4">
30
+ {isLive ? (
31
+ <GameMap players={players} onMove={onMove} />
32
+ ) : (
33
+ <div className="tabular-nums">
34
+ {message} ({percentage.toFixed(1)}%)…
35
+ </div>
36
+ )}
37
+ </div>
38
+ <div className="fixed top-2 right-2">
39
+ <AccountButton />
40
+ </div>
103
41
  </>
104
42
  );
105
- };
43
+ }
@@ -0,0 +1,78 @@
1
+ import { serialize, useAccount } from "wagmi";
2
+ import { useKeyboardMovement } from "./useKeyboardMovement";
3
+ import { Address, Hex, hexToBigInt, keccak256 } from "viem";
4
+ import { ArrowDownIcon } from "./ui/icons/ArrowDownIcon";
5
+ import { twMerge } from "tailwind-merge";
6
+ import { Direction } from "./common";
7
+ import mudConfig from "contracts/mud.config";
8
+
9
+ export type Props = {
10
+ readonly players?: readonly {
11
+ readonly player: Address;
12
+ readonly x: number;
13
+ readonly y: number;
14
+ }[];
15
+
16
+ readonly onMove?: (direction: Direction) => void;
17
+ };
18
+
19
+ const size = 40;
20
+ const scale = 100 / size;
21
+
22
+ function getColorAngle(seed: Hex) {
23
+ return Number(hexToBigInt(keccak256(seed)) % 360n);
24
+ }
25
+
26
+ const rotateClassName = {
27
+ North: "rotate-0",
28
+ East: "rotate-90",
29
+ South: "rotate-180",
30
+ West: "-rotate-90",
31
+ } as const satisfies Record<Direction, `${"" | "-"}rotate-${number}`>;
32
+
33
+ export function GameMap({ players = [], onMove }: Props) {
34
+ const { address: userAddress } = useAccount();
35
+ useKeyboardMovement(onMove);
36
+ return (
37
+ <div className="aspect-square w-full max-w-[40rem]">
38
+ <div className="relative w-full h-full border-8 border-black/10">
39
+ {onMove
40
+ ? mudConfig.enums.Direction.map((direction) => (
41
+ <button
42
+ key={direction}
43
+ title={`Move ${direction.toLowerCase()}`}
44
+ className={twMerge(
45
+ "outline-0 absolute inset-0 cursor-pointer grid p-4",
46
+ rotateClassName[direction],
47
+ "transition bg-gradient-to-t from-transparent via-transparent to-blue-50 text-blue-400 opacity-0 hover:opacity-40 active:opacity-100",
48
+ )}
49
+ style={{ clipPath: "polygon(0% 0%, 100% 0%, 50% 50%)" }}
50
+ onClick={() => onMove(direction)}
51
+ >
52
+ <ArrowDownIcon className="rotate-180 text-4xl self-start justify-self-center" />
53
+ </button>
54
+ ))
55
+ : null}
56
+
57
+ {players.map((player) => (
58
+ <div
59
+ key={player.player}
60
+ className="absolute bg-current"
61
+ style={{
62
+ color: `hwb(${getColorAngle(player.player)} 40% 20%)`,
63
+ width: `${scale}%`,
64
+ height: `${scale}%`,
65
+ left: `${((((player.x + size / 2) % size) + size) % size) * scale}%`,
66
+ top: `${((size - ((player.y + size / 2) % size)) % size) * scale}%`,
67
+ }}
68
+ title={serialize(player, null, 2)}
69
+ >
70
+ {player.player.toLowerCase() === userAddress?.toLowerCase() ? (
71
+ <div className="w-full h-full bg-current animate-ping opacity-50" />
72
+ ) : null}
73
+ </div>
74
+ ))}
75
+ </div>
76
+ </div>
77
+ );
78
+ }
@@ -0,0 +1,44 @@
1
+ import { WagmiProvider } from "wagmi";
2
+ import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
3
+ import { ReactNode } from "react";
4
+ import { createSyncAdapter } from "@latticexyz/store-sync/internal";
5
+ import { SyncProvider } from "@latticexyz/store-sync/react";
6
+ import { stash } from "./mud/stash";
7
+ import { Address } from "viem";
8
+ import { defineConfig, EntryKitProvider } from "@latticexyz/entrykit/internal";
9
+ import { wagmiConfig } from "./wagmiConfig";
10
+ import { chainId } from "./common";
11
+
12
+ const queryClient = new QueryClient();
13
+
14
+ export type Props = {
15
+ worldDeploy: {
16
+ address: Address;
17
+ blockNumber: bigint | null;
18
+ };
19
+ children: ReactNode;
20
+ };
21
+
22
+ export function Providers({ worldDeploy, children }: Props) {
23
+ return (
24
+ <WagmiProvider config={wagmiConfig}>
25
+ <QueryClientProvider client={queryClient}>
26
+ <EntryKitProvider
27
+ config={defineConfig({
28
+ chainId,
29
+ worldAddress: worldDeploy.address,
30
+ })}
31
+ >
32
+ <SyncProvider
33
+ chainId={chainId}
34
+ address={worldDeploy.address}
35
+ startBlock={worldDeploy.blockNumber ?? undefined}
36
+ adapter={createSyncAdapter({ stash })}
37
+ >
38
+ {children}
39
+ </SyncProvider>
40
+ </EntryKitProvider>
41
+ </QueryClientProvider>
42
+ </WagmiProvider>
43
+ );
44
+ }
@@ -0,0 +1,6 @@
1
+ import mudConfig from "contracts/mud.config";
2
+
3
+ export const chainId = parseInt(import.meta.env.VITE_CHAIN_ID) || 31337;
4
+ export const url = new URL(window.location.href);
5
+
6
+ export type Direction = (typeof mudConfig.enums.Direction)[number];
@@ -1,34 +1,20 @@
1
- import ReactDOM from "react-dom/client";
1
+ import "tailwindcss/tailwind.css";
2
+ import { StrictMode } from "react";
3
+ import { createRoot } from "react-dom/client";
4
+ import { getWorldDeploy } from "./mud/getWorldDeploy";
5
+ import { Providers } from "./Providers";
2
6
  import { App } from "./App";
3
- import { setup } from "./mud/setup";
4
- import { MUDProvider } from "./MUDContext";
5
- import mudConfig from "contracts/mud.config";
6
-
7
- const rootElement = document.getElementById("react-root");
8
- if (!rootElement) throw new Error("React root not found");
9
- const root = ReactDOM.createRoot(rootElement);
7
+ import { chainId } from "./common";
8
+ import { Explorer } from "./mud/Explorer";
10
9
 
11
10
  // TODO: figure out if we actually want this to be async or if we should render something else in the meantime
12
- setup().then(async (result) => {
13
- root.render(
14
- <MUDProvider value={result}>
15
- <App />
16
- </MUDProvider>,
17
- );
18
-
19
- // https://vitejs.dev/guide/env-and-mode.html
20
- if (import.meta.env.DEV) {
21
- const { mount: mountDevTools } = await import("@latticexyz/dev-tools");
22
- mountDevTools({
23
- config: mudConfig,
24
- publicClient: result.network.publicClient,
25
- walletClient: result.network.walletClient,
26
- latestBlock$: result.network.latestBlock$,
27
- storedBlockLogs$: result.network.storedBlockLogs$,
28
- worldAddress: result.network.worldContract.address,
29
- worldAbi: result.network.worldContract.abi,
30
- write$: result.network.write$,
31
- useStore: result.network.useStore,
32
- });
33
- }
34
- });
11
+ getWorldDeploy(chainId).then((worldDeploy) =>
12
+ createRoot(document.getElementById("react-root")!).render(
13
+ <StrictMode>
14
+ <Providers worldDeploy={worldDeploy}>
15
+ <App />
16
+ <Explorer />
17
+ </Providers>
18
+ </StrictMode>,
19
+ ),
20
+ );
@@ -0,0 +1,32 @@
1
+ import { useState } from "react";
2
+ import { twMerge } from "tailwind-merge";
3
+ import { useEntryKitConfig } from "@latticexyz/entrykit/internal";
4
+ import { MUDIcon } from "../ui/icons/MUDIcon";
5
+
6
+ export function Explorer() {
7
+ const [open, setOpen] = useState(false);
8
+ const { chain, worldAddress } = useEntryKitConfig();
9
+ const explorerUrl = chain.blockExplorers?.worldsExplorer?.url;
10
+ if (!explorerUrl) return null;
11
+
12
+ return (
13
+ <div className="fixed bottom-0 inset-x-0 flex flex-col opacity-80 transition hover:opacity-100">
14
+ <button
15
+ type="button"
16
+ onClick={() => setOpen(!open)}
17
+ className="outline-none flex justify-end gap-2 p-2 font-medium leading-none text-black"
18
+ >
19
+ {open ? (
20
+ <>Close</>
21
+ ) : (
22
+ <>
23
+ Explore <MUDIcon className="text-orange-500" />
24
+ </>
25
+ )}
26
+ </button>
27
+ {open ? (
28
+ <iframe src={`${explorerUrl}/${worldAddress}`} className={twMerge("bg-black", open ? "h-[50vh]" : "h-0")} />
29
+ ) : null}
30
+ </div>
31
+ );
32
+ }
@@ -0,0 +1,23 @@
1
+ import { Address } from "viem";
2
+
3
+ export async function getWorldDeploy(chainId: number): Promise<{
4
+ chainId: number;
5
+ address: Address;
6
+ blockNumber: bigint | null;
7
+ }> {
8
+ // TODO: figure out how to catch vite:import-analysis error when this file is missing
9
+ const { default: worlds } = await import("contracts/worlds.json").catch((error) => {
10
+ console.debug("Could not import worlds.json", error);
11
+ return { default: null };
12
+ });
13
+ const deploy = worlds?.[`${chainId}`];
14
+ if (!deploy) {
15
+ throw new Error(`No world deploy found for chain ${chainId} in "worlds.json".`);
16
+ }
17
+ console.log("chain:", chainId, "world:", deploy);
18
+ return {
19
+ chainId,
20
+ address: deploy.address,
21
+ blockNumber: deploy.blockNumber != null ? BigInt(deploy.blockNumber) : null,
22
+ };
23
+ }
@@ -0,0 +1,4 @@
1
+ import { createStash } from "@latticexyz/stash/internal";
2
+ import config from "contracts/mud.config";
3
+
4
+ export const stash = createStash(config);
@@ -0,0 +1,21 @@
1
+ import { stash } from "./stash";
2
+ import { initialProgress, SyncProgress } from "@latticexyz/store-sync/internal";
3
+ import { SyncStep } from "@latticexyz/store-sync";
4
+ import { useMemo } from "react";
5
+ import { useRecord } from "@latticexyz/stash/react";
6
+
7
+ export function useSyncProgress() {
8
+ const progress = useRecord({
9
+ stash,
10
+ table: SyncProgress,
11
+ key: {},
12
+ defaultValue: initialProgress,
13
+ });
14
+ return useMemo(
15
+ () => ({
16
+ ...progress,
17
+ isLive: progress.step === SyncStep.LIVE,
18
+ }),
19
+ [progress],
20
+ );
21
+ }
@@ -0,0 +1,45 @@
1
+ import { useClient } from "wagmi";
2
+ import { chainId } from "../common";
3
+ import { Account, Chain, Client, GetContractReturnType, Transport, getContract } from "viem";
4
+ import { useQuery } from "@tanstack/react-query";
5
+ import { useSessionClient, useEntryKitConfig } from "@latticexyz/entrykit/internal";
6
+ import { observer } from "@latticexyz/explorer/observer";
7
+ import worldAbi from "contracts/out/IWorld.sol/IWorld.abi.json";
8
+
9
+ export function useWorldContract():
10
+ | GetContractReturnType<
11
+ typeof worldAbi,
12
+ {
13
+ public: Client<Transport, Chain>;
14
+ wallet: Client<Transport, Chain, Account>;
15
+ }
16
+ >
17
+ | undefined {
18
+ const { worldAddress } = useEntryKitConfig();
19
+ const client = useClient({ chainId });
20
+ const { data: sessionClient } = useSessionClient();
21
+
22
+ const { data: worldContract } = useQuery({
23
+ queryKey: ["worldContract", worldAddress, client?.uid, sessionClient?.uid],
24
+ queryFn: () => {
25
+ if (!client || !sessionClient) {
26
+ throw new Error("Not connected.");
27
+ }
28
+
29
+ return getContract({
30
+ abi: worldAbi,
31
+ address: worldAddress,
32
+ client: {
33
+ public: client,
34
+ wallet: sessionClient.extend(observer()),
35
+ },
36
+ });
37
+ },
38
+ staleTime: Infinity,
39
+ refetchOnMount: false,
40
+ refetchOnReconnect: false,
41
+ refetchOnWindowFocus: false,
42
+ });
43
+
44
+ return worldContract;
45
+ }