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.
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/templates/react/gitignore +14 -5
- package/dist/templates/react/mprocs.yaml +9 -1
- package/dist/templates/react/package.json +28 -4
- package/dist/templates/react/packages/client/gitignore +0 -2
- package/dist/templates/react/packages/client/package.json +21 -12
- package/dist/templates/react/packages/client/postcss.config.cjs +6 -0
- package/dist/templates/react/packages/client/src/App.tsx +38 -100
- package/dist/templates/react/packages/client/src/GameMap.tsx +78 -0
- package/dist/templates/react/packages/client/src/Providers.tsx +44 -0
- package/dist/templates/react/packages/client/src/common.ts +6 -0
- package/dist/templates/react/packages/client/src/index.tsx +17 -31
- package/dist/templates/react/packages/client/src/mud/Explorer.tsx +32 -0
- package/dist/templates/react/packages/client/src/mud/getWorldDeploy.ts +23 -0
- package/dist/templates/react/packages/client/src/mud/stash.ts +4 -0
- package/dist/templates/react/packages/client/src/mud/useSyncProgress.ts +21 -0
- package/dist/templates/react/packages/client/src/mud/useWorldContract.ts +45 -0
- package/dist/templates/react/packages/client/src/ui/icons/ArrowDownIcon.tsx +22 -0
- package/dist/templates/react/packages/client/src/ui/icons/MUDIcon.tsx +25 -0
- package/dist/templates/react/packages/client/src/useKeyboardMovement.ts +26 -0
- package/dist/templates/react/packages/client/src/wagmiConfig.ts +49 -0
- package/dist/templates/react/packages/client/tailwind.config.ts +10 -0
- package/dist/templates/react/packages/client/vite.config.ts +0 -6
- package/dist/templates/react/packages/contracts/gitignore +12 -8
- package/dist/templates/react/packages/contracts/mud.config.ts +13 -8
- package/dist/templates/react/packages/contracts/out/IWorld.sol/IWorld.abi.json +2021 -0
- package/dist/templates/react/packages/contracts/package.json +8 -7
- package/dist/templates/react/packages/contracts/script/PostDeploy.s.sol +1 -9
- package/dist/templates/react/packages/contracts/src/MoveSystem.sol +26 -0
- package/dist/templates/react/packages/contracts/src/codegen/common.sol +11 -0
- package/dist/templates/react/packages/contracts/src/codegen/index.sol +1 -1
- package/dist/templates/react/packages/contracts/src/codegen/tables/Position.sol +318 -0
- package/dist/templates/react/packages/contracts/src/codegen/world/{ITasksSystem.sol → IMoveSystem.sol} +5 -9
- package/dist/templates/react/packages/contracts/src/codegen/world/IWorld.sol +2 -2
- package/dist/templates/react/packages/contracts/worlds.json +1 -1
- package/package.json +1 -1
- package/dist/templates/react/packages/client/src/MUDContext.tsx +0 -21
- package/dist/templates/react/packages/client/src/mud/createSystemCalls.ts +0 -56
- package/dist/templates/react/packages/client/src/mud/getNetworkConfig.ts +0 -76
- package/dist/templates/react/packages/client/src/mud/setup.ts +0 -18
- package/dist/templates/react/packages/client/src/mud/setupNetwork.ts +0 -101
- package/dist/templates/react/packages/client/src/mud/supportedChains.ts +0 -20
- package/dist/templates/react/packages/contracts/src/codegen/tables/Tasks.sol +0 -522
- package/dist/templates/react/packages/contracts/src/systems/TasksSystem.sol +0 -24
- 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
|
|
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-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
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 --
|
|
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": "
|
|
16
|
-
"@latticexyz/common": "
|
|
17
|
-
"@latticexyz/explorer": "
|
|
18
|
-
"@latticexyz/store-indexer": "
|
|
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
|
}
|
|
@@ -11,25 +11,34 @@
|
|
|
11
11
|
"test": "tsc --noEmit"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@latticexyz/common": "
|
|
15
|
-
"@latticexyz/
|
|
16
|
-
"@latticexyz/
|
|
17
|
-
"@latticexyz/
|
|
18
|
-
"@latticexyz/
|
|
19
|
-
"@latticexyz/
|
|
20
|
-
"@latticexyz/
|
|
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
|
-
"
|
|
23
|
-
"react
|
|
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
|
-
"
|
|
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.
|
|
29
|
-
"@types/react-dom": "18.2.
|
|
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
|
}
|
|
@@ -1,105 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
<
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
×
|
|
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
|
+
}
|
|
@@ -1,34 +1,20 @@
|
|
|
1
|
-
import
|
|
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 {
|
|
4
|
-
import {
|
|
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
|
-
|
|
13
|
-
root.render(
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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,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
|
+
}
|