From 567c2aef5d37ed321d6416429415270202566467 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Tue, 21 Jan 2025 11:26:16 +0000 Subject: [PATCH] Revert "feat(create-mud): new react template with stash/entrykit" (#3477) --- .changeset/cuddly-pugs-cough.md | 5 - .changeset/five-bats-live.md | 5 - packages/create-mud/scripts/copy-templates.ts | 18 +- packages/entrykit/package.json | 2 +- pnpm-lock.yaml | 20 +- templates/react/.gitignore | 19 +- templates/react/mprocs.yaml | 10 +- templates/react/package.json | 7 - templates/react/packages/client/.gitignore | 2 + templates/react/packages/client/index.html | 4 +- templates/react/packages/client/package.json | 26 +- .../react/packages/client/postcss.config.cjs | 6 - templates/react/packages/client/src/App.tsx | 141 +- .../react/packages/client/src/MUDContext.tsx | 21 + .../react/packages/client/src/Providers.tsx | 35 - templates/react/packages/client/src/common.ts | 26 - .../packages/client/src/game/GameMap.tsx | 102 - .../client/src/game/useKeyboardMovement.ts | 26 - templates/react/packages/client/src/index.tsx | 49 +- .../packages/client/src/mud/Explorer.tsx | 32 - .../react/packages/client/src/mud/Synced.tsx | 14 - .../client/src/mud/createSystemCalls.ts | 56 + .../client/src/mud/getNetworkConfig.ts | 76 + .../react/packages/client/src/mud/setup.ts | 18 + .../packages/client/src/mud/setupNetwork.ts | 101 + .../react/packages/client/src/mud/stash.ts | 4 - .../client/src/mud/supportedChains.ts | 20 + .../packages/client/src/mud/useSyncStatus.ts | 21 - .../client/src/mud/useWorldContract.ts | 44 - .../packages/client/src/ui/AsyncButton.tsx | 41 - .../packages/client/src/ui/ErrorFallback.tsx | 58 - .../client/src/ui/icons/ArrowDownIcon.tsx | 22 - .../packages/client/src/ui/icons/MUDIcon.tsx | 25 - .../react/packages/client/src/wagmiConfig.ts | 49 - .../react/packages/client/tailwind.config.ts | 10 - templates/react/packages/client/tsconfig.json | 2 +- .../react/packages/client/vite.config.ts | 9 +- templates/react/packages/contracts/.gitignore | 20 +- .../react/packages/contracts/mud.config.ts | 21 +- .../contracts/out/IWorld.sol/IWorld.abi.json | 2021 ----------------- .../react/packages/contracts/package.json | 1 - .../contracts/script/PostDeploy.s.sol | 10 +- .../packages/contracts/src/MoveSystem.sol | 26 - .../packages/contracts/src/codegen/common.sol | 11 - .../packages/contracts/src/codegen/index.sol | 2 +- .../contracts/src/codegen/tables/Position.sol | 318 --- .../contracts/src/codegen/tables/Tasks.sol | 522 +++++ .../{IMoveSystem.sol => ITasksSystem.sol} | 14 +- .../contracts/src/codegen/world/IWorld.sol | 4 +- .../contracts/src/systems/TasksSystem.sol | 24 + .../packages/contracts/test/MoveTest.t.sol | 27 - .../packages/contracts/test/TasksTest.t.sol | 30 + .../packages/contracts/test/WorldTest.t.sol | 21 - .../react/packages/contracts/worlds.json | 2 +- 54 files changed, 1088 insertions(+), 3112 deletions(-) delete mode 100644 .changeset/cuddly-pugs-cough.md delete mode 100644 .changeset/five-bats-live.md delete mode 100644 templates/react/packages/client/postcss.config.cjs create mode 100644 templates/react/packages/client/src/MUDContext.tsx delete mode 100644 templates/react/packages/client/src/Providers.tsx delete mode 100644 templates/react/packages/client/src/common.ts delete mode 100644 templates/react/packages/client/src/game/GameMap.tsx delete mode 100644 templates/react/packages/client/src/game/useKeyboardMovement.ts delete mode 100644 templates/react/packages/client/src/mud/Explorer.tsx delete mode 100644 templates/react/packages/client/src/mud/Synced.tsx create mode 100644 templates/react/packages/client/src/mud/createSystemCalls.ts create mode 100644 templates/react/packages/client/src/mud/getNetworkConfig.ts create mode 100644 templates/react/packages/client/src/mud/setup.ts create mode 100644 templates/react/packages/client/src/mud/setupNetwork.ts delete mode 100644 templates/react/packages/client/src/mud/stash.ts create mode 100644 templates/react/packages/client/src/mud/supportedChains.ts delete mode 100644 templates/react/packages/client/src/mud/useSyncStatus.ts delete mode 100644 templates/react/packages/client/src/mud/useWorldContract.ts delete mode 100644 templates/react/packages/client/src/ui/AsyncButton.tsx delete mode 100644 templates/react/packages/client/src/ui/ErrorFallback.tsx delete mode 100644 templates/react/packages/client/src/ui/icons/ArrowDownIcon.tsx delete mode 100644 templates/react/packages/client/src/ui/icons/MUDIcon.tsx delete mode 100644 templates/react/packages/client/src/wagmiConfig.ts delete mode 100644 templates/react/packages/client/tailwind.config.ts delete mode 100644 templates/react/packages/contracts/out/IWorld.sol/IWorld.abi.json delete mode 100644 templates/react/packages/contracts/src/MoveSystem.sol delete mode 100644 templates/react/packages/contracts/src/codegen/common.sol delete mode 100644 templates/react/packages/contracts/src/codegen/tables/Position.sol create mode 100644 templates/react/packages/contracts/src/codegen/tables/Tasks.sol rename templates/react/packages/contracts/src/codegen/world/{IMoveSystem.sol => ITasksSystem.sol} (51%) create mode 100644 templates/react/packages/contracts/src/systems/TasksSystem.sol delete mode 100644 templates/react/packages/contracts/test/MoveTest.t.sol create mode 100644 templates/react/packages/contracts/test/TasksTest.t.sol delete mode 100644 templates/react/packages/contracts/test/WorldTest.t.sol diff --git a/.changeset/cuddly-pugs-cough.md b/.changeset/cuddly-pugs-cough.md deleted file mode 100644 index 00de7fe84b..0000000000 --- a/.changeset/cuddly-pugs-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@latticexyz/entrykit": patch ---- - -Bumped react-error-boundary dependency. diff --git a/.changeset/five-bats-live.md b/.changeset/five-bats-live.md deleted file mode 100644 index d9cacf7466..0000000000 --- a/.changeset/five-bats-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"create-mud": patch ---- - -Updated React template with Stash client state library, EntryKit for wallet support, and a cleaned up app structure. diff --git a/packages/create-mud/scripts/copy-templates.ts b/packages/create-mud/scripts/copy-templates.ts index 9e74978b13..a68b2d33d5 100644 --- a/packages/create-mud/scripts/copy-templates.ts +++ b/packages/create-mud/scripts/copy-templates.ts @@ -7,7 +7,6 @@ import { glob } from "glob"; const packageDir = path.resolve(__dirname, ".."); const rootDir = path.resolve(packageDir, "../.."); - // TODO: could swap this with `pnpm m ls --json --depth=-1` const mudPackageNames = await (async () => { const files = await glob("packages/*/package.json", { cwd: rootDir }); const packages = await Promise.all( @@ -29,17 +28,16 @@ import { glob } from "glob"; await fs.mkdir(path.dirname(destPath), { recursive: true }); + // Replace all MUD package links with mustache placeholder used by create-create-app + // that will be replaced with the latest MUD version number when the template is used. if (/package.json$/.test(destPath)) { - let source = await fs.readFile(sourcePath, "utf-8"); - // Replace all MUD package links with mustache placeholder used by create-create-app - // that will be replaced with the latest MUD version number when the template is used. - source = source.replace(/"([^"]+)":\s*"(link|file):[^"]+"/g, (match, packageName) => - mudPackageNames.includes(packageName) ? `"${packageName}": "{{mud-version}}"` : match, + const source = await fs.readFile(sourcePath, "utf-8"); + await fs.writeFile( + destPath, + source.replace(/"([^"]+)":\s*"(link|file):[^"]+"/g, (match, packageName) => + mudPackageNames.includes(packageName) ? `"${packageName}": "{{mud-version}}"` : match, + ), ); - const json = JSON.parse(source); - // Strip out pnpm overrides - delete json.pnpm; - await fs.writeFile(destPath, JSON.stringify(json, null, 2) + "\n"); } // Replace template workspace root `tsconfig.json` files (which have paths relative to monorepo) // with one that inherits our base tsconfig. diff --git a/packages/entrykit/package.json b/packages/entrykit/package.json index 48898c241b..b783cebded 100644 --- a/packages/entrykit/package.json +++ b/packages/entrykit/package.json @@ -56,7 +56,7 @@ "debug": "^4.3.4", "dotenv": "^16.0.3", "permissionless": "0.2.25", - "react-error-boundary": "5.0.0", + "react-error-boundary": "^4.0.13", "react-merge-refs": "^2.1.1", "tailwind-merge": "^1.12.0", "usehooks-ts": "^3.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0cacb9a9f4..543db513bb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -460,8 +460,8 @@ importers: specifier: 0.2.25 version: 0.2.25(viem@2.21.19(bufferutil@4.0.8)(typescript@5.4.2)(utf-8-validate@5.0.10)(zod@3.23.8))(webauthn-p256@0.0.10) react-error-boundary: - specifier: 5.0.0 - version: 5.0.0(react@18.2.0) + specifier: ^4.0.13 + version: 4.0.13(react@18.2.0) react-merge-refs: specifier: ^2.1.1 version: 2.1.1 @@ -2554,6 +2554,10 @@ packages: resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.25.6': + resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} + engines: {node: '>=6.9.0'} + '@babel/runtime@7.25.7': resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} engines: {node: '>=6.9.0'} @@ -10504,8 +10508,8 @@ packages: peerDependencies: react: '>=16.13.1' - react-error-boundary@5.0.0: - resolution: {integrity: sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==} + react-error-boundary@4.0.13: + resolution: {integrity: sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==} peerDependencies: react: '>=16.13.1' @@ -13974,6 +13978,10 @@ snapshots: dependencies: regenerator-runtime: 0.13.11 + '@babel/runtime@7.25.6': + dependencies: + regenerator-runtime: 0.14.1 + '@babel/runtime@7.25.7': dependencies: regenerator-runtime: 0.14.1 @@ -23539,9 +23547,9 @@ snapshots: '@babel/runtime': 7.25.7 react: 18.2.0 - react-error-boundary@5.0.0(react@18.2.0): + react-error-boundary@4.0.13(react@18.2.0): dependencies: - '@babel/runtime': 7.25.7 + '@babel/runtime': 7.25.6 react: 18.2.0 react-hook-form@7.52.2(react@18.2.0): diff --git a/templates/react/.gitignore b/templates/react/.gitignore index b05d373f12..3737e58258 100644 --- a/templates/react/.gitignore +++ b/templates/react/.gitignore @@ -1,16 +1,7 @@ -.DS_Store -logs -*.log - node_modules -.env.* - -# foundry -cache -broadcast -out/* -!out/IWorld.sol -out/IWorld.sol/* -!out/IWorld.sol/IWorld.abi.json -!out/IWorld.sol/IWorld.abi.d.json.ts +# mud artifacts +.mud +# sqlite indexer data +*.db +*.db-journal diff --git a/templates/react/mprocs.yaml b/templates/react/mprocs.yaml index f5be11254f..fa8c42c046 100644 --- a/templates/react/mprocs.yaml +++ b/templates/react/mprocs.yaml @@ -1,4 +1,3 @@ -scrollback: 10000 procs: client: cwd: packages/client @@ -6,16 +5,9 @@ procs: contracts: cwd: packages/contracts shell: pnpm mud dev-contracts --rpc http://127.0.0.1:8545 - deploy-prereqs: - cwd: packages/contracts - shell: pnpm deploy-local-prereqs - env: - DEBUG: "mud:*" - # Anvil default account (0x70997970C51812dc3A010C7d01b50e0d17dc79C8) - PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" anvil: cwd: packages/contracts - shell: anvil --block-time 2 + shell: anvil --base-fee 0 --block-time 2 explorer: cwd: packages/contracts shell: pnpm explorer diff --git a/templates/react/package.json b/templates/react/package.json index 661fc6e32f..3a8f28180a 100644 --- a/templates/react/package.json +++ b/templates/react/package.json @@ -27,12 +27,5 @@ "engines": { "node": "^18", "pnpm": "^8 || ^9" - }, - "pnpm": { - "overrides": { - "@tanstack/react-query": "link:../../packages/entrykit/node_modules/@tanstack/react-query", - "@types/react": "link:../../packages/entrykit/node_modules/@types/react", - "wagmi": "link:../../packages/entrykit/node_modules/wagmi" - } } } diff --git a/templates/react/packages/client/.gitignore b/templates/react/packages/client/.gitignore index 1521c8b765..0ca39c007c 100644 --- a/templates/react/packages/client/.gitignore +++ b/templates/react/packages/client/.gitignore @@ -1 +1,3 @@ +node_modules dist +.DS_Store diff --git a/templates/react/packages/client/index.html b/templates/react/packages/client/index.html index ccf1b76fb2..c3f06eb806 100644 --- a/templates/react/packages/client/index.html +++ b/templates/react/packages/client/index.html @@ -1,9 +1,9 @@ - + - a MUD app + a minimal MUD client
diff --git a/templates/react/packages/client/package.json b/templates/react/packages/client/package.json index f9b2d4dee2..29825547ed 100644 --- a/templates/react/packages/client/package.json +++ b/templates/react/packages/client/package.json @@ -6,39 +6,31 @@ "type": "module", "scripts": { "build": "vite build", - "dev": "vite", + "dev": "wait-port localhost:8545 && vite", "preview": "vite preview", "test": "tsc --noEmit" }, "dependencies": { "@latticexyz/common": "link:../../../../packages/common", - "@latticexyz/entrykit": "link:../../../../packages/entrykit", - "@latticexyz/explorer": "link:../../../../packages/explorer", + "@latticexyz/dev-tools": "link:../../../../packages/dev-tools", "@latticexyz/react": "link:../../../../packages/react", "@latticexyz/schema-type": "link:../../../../packages/schema-type", - "@latticexyz/stash": "link:../../../../packages/stash", "@latticexyz/store-sync": "link:../../../../packages/store-sync", "@latticexyz/utils": "link:../../../../packages/utils", "@latticexyz/world": "link:../../../../packages/world", - "@tanstack/react-query": "^5.63.0", "contracts": "workspace:*", - "react": "18.2.0", - "react-dom": "18.2.0", - "react-error-boundary": "5.0.0", - "tailwind-merge": "^2.6.0", - "viem": "2.21.19", - "wagmi": "2.12.11" + "react": "^18.2.0", + "react-dom": "^18.2.0", + "rxjs": "7.5.5", + "viem": "2.21.19" }, "devDependencies": { "@types/react": "18.2.22", "@types/react-dom": "18.2.7", - "@vitejs/plugin-react": "^4.3.4", - "autoprefixer": "^10.4.20", + "@vitejs/plugin-react": "^3.1.0", "eslint-plugin-react": "7.31.11", "eslint-plugin-react-hooks": "4.6.0", - "postcss": "^8.4.49", - "tailwindcss": "^3.4.17", - "vite": "^6.0.7", - "vite-plugin-mud": "link:../../../../packages/vite-plugin-mud" + "vite": "^4.2.1", + "wait-port": "^1.0.4" } } diff --git a/templates/react/packages/client/postcss.config.cjs b/templates/react/packages/client/postcss.config.cjs deleted file mode 100644 index 12a703d900..0000000000 --- a/templates/react/packages/client/postcss.config.cjs +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/templates/react/packages/client/src/App.tsx b/templates/react/packages/client/src/App.tsx index ddc7bae21c..82c60486a9 100644 --- a/templates/react/packages/client/src/App.tsx +++ b/templates/react/packages/client/src/App.tsx @@ -1,46 +1,105 @@ -import { stash } from "./mud/stash"; -import { useRecords } from "@latticexyz/stash/react"; -import { AccountButton } from "@latticexyz/entrykit/internal"; -import { Direction } from "./common"; -import mudConfig from "contracts/mud.config"; -import { useMemo } from "react"; -import { GameMap } from "./game/GameMap"; -import { useWorldContract } from "./mud/useWorldContract"; -import { Synced } from "./mud/Synced"; -import { useSync } from "@latticexyz/store-sync/react"; - -export function App() { - const players = useRecords({ stash, table: mudConfig.tables.app__Position }); - - const sync = useSync(); - const worldContract = useWorldContract(); - const onMove = useMemo( - () => - sync.data && worldContract - ? async (direction: Direction) => { - const tx = await worldContract.write.app__move([mudConfig.enums.Direction.indexOf(direction)]); - await sync.data.waitForTransaction(tx); - } - : undefined, - [sync.data, worldContract], - ); +import { useMUD } from "./MUDContext"; + +const styleUnset = { all: "unset" } as const; + +export const App = () => { + const { + network: { tables, useStore }, + systemCalls: { addTask, toggleTask, deleteTask }, + } = useMUD(); + + const tasks = useStore((state) => { + const records = Object.values(state.getRecords(tables.Tasks)); + records.sort((a, b) => Number(a.value.createdAt - b.value.createdAt)); + return records; + }); return ( <> -
- ( -
- {message} ({percentage.toFixed(1)}%)… -
- )} - > - -
-
-
- -
+ + + {tasks.map((task) => ( + + + + + + ))} + + + + + + + +
+ 0n} + title={task.value.completedAt === 0n ? "Mark task as completed" : "Mark task as incomplete"} + onChange={async (event) => { + event.preventDefault(); + const checkbox = event.currentTarget; + + checkbox.disabled = true; + try { + await toggleTask(task.key.id); + } finally { + checkbox.disabled = false; + } + }} + /> + {task.value.completedAt > 0n ? {task.value.description} : <>{task.value.description}} + +
+ + +
{ + event.preventDefault(); + const form = event.currentTarget; + const fieldset = form.querySelector("fieldset"); + if (!(fieldset instanceof HTMLFieldSetElement)) return; + + const formData = new FormData(form); + const desc = formData.get("description"); + if (typeof desc !== "string") return; + + fieldset.disabled = true; + try { + await addTask(desc); + form.reset(); + } finally { + fieldset.disabled = false; + } + }} + > +
+ {" "} + +
+
+
); -} +}; diff --git a/templates/react/packages/client/src/MUDContext.tsx b/templates/react/packages/client/src/MUDContext.tsx new file mode 100644 index 0000000000..7b5637f6a6 --- /dev/null +++ b/templates/react/packages/client/src/MUDContext.tsx @@ -0,0 +1,21 @@ +import { createContext, ReactNode, useContext } from "react"; +import { SetupResult } from "./mud/setup"; + +const MUDContext = createContext(null); + +type Props = { + children: ReactNode; + value: SetupResult; +}; + +export const MUDProvider = ({ children, value }: Props) => { + const currentValue = useContext(MUDContext); + if (currentValue) throw new Error("MUDProvider can only be used once"); + return {children}; +}; + +export const useMUD = () => { + const value = useContext(MUDContext); + if (!value) throw new Error("Must be used within a MUDProvider"); + return value; +}; diff --git a/templates/react/packages/client/src/Providers.tsx b/templates/react/packages/client/src/Providers.tsx deleted file mode 100644 index ed96171dbb..0000000000 --- a/templates/react/packages/client/src/Providers.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { WagmiProvider } from "wagmi"; -import { QueryClientProvider, QueryClient } from "@tanstack/react-query"; -import { ReactNode } from "react"; -import { createSyncAdapter } from "@latticexyz/store-sync/internal"; -import { SyncProvider } from "@latticexyz/store-sync/react"; -import { stash } from "./mud/stash"; -import { defineConfig, EntryKitProvider } from "@latticexyz/entrykit/internal"; -import { wagmiConfig } from "./wagmiConfig"; -import { chainId, getWorldAddress, startBlock } from "./common"; - -const queryClient = new QueryClient(); - -export type Props = { - children: ReactNode; -}; - -export function Providers({ children }: Props) { - const worldAddress = getWorldAddress(); - return ( - - - - - {children} - - - - - ); -} diff --git a/templates/react/packages/client/src/common.ts b/templates/react/packages/client/src/common.ts deleted file mode 100644 index 6caa86136c..0000000000 --- a/templates/react/packages/client/src/common.ts +++ /dev/null @@ -1,26 +0,0 @@ -import mudConfig from "contracts/mud.config"; -import { chains } from "./wagmiConfig"; -import { Chain } from "viem"; - -export const chainId = import.meta.env.CHAIN_ID; -export const worldAddress = import.meta.env.WORLD_ADDRESS; -export const startBlock = import.meta.env.START_BLOCK; - -export const url = new URL(window.location.href); - -export type Direction = (typeof mudConfig.enums.Direction)[number]; - -export function getWorldAddress() { - if (!worldAddress) { - throw new Error("No world address configured. Is the world still deploying?"); - } - return worldAddress; -} - -export function getChain(): Chain { - const chain = chains.find((c) => c.id === chainId); - if (!chain) { - throw new Error(`No chain configured for chain ID ${chainId}.`); - } - return chain; -} diff --git a/templates/react/packages/client/src/game/GameMap.tsx b/templates/react/packages/client/src/game/GameMap.tsx deleted file mode 100644 index 04d7d24d4f..0000000000 --- a/templates/react/packages/client/src/game/GameMap.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import { serialize, useAccount } from "wagmi"; -import { useKeyboardMovement } from "./useKeyboardMovement"; -import { Address, Hex, hexToBigInt, keccak256 } from "viem"; -import { ArrowDownIcon } from "../ui/icons/ArrowDownIcon"; -import { twMerge } from "tailwind-merge"; -import { Direction } from "../common"; -import mudConfig from "contracts/mud.config"; -import { AsyncButton } from "../ui/AsyncButton"; -import { useAccountModal } from "@latticexyz/entrykit/internal"; - -export type Props = { - readonly players?: readonly { - readonly player: Address; - readonly x: number; - readonly y: number; - }[]; - - readonly onMove?: (direction: Direction) => Promise; -}; - -const size = 40; -const scale = 100 / size; - -function getColorAngle(seed: Hex) { - return Number(hexToBigInt(keccak256(seed)) % 360n); -} - -const rotateClassName = { - North: "rotate-0", - East: "rotate-90", - South: "rotate-180", - West: "-rotate-90", -} as const satisfies Record; - -export function GameMap({ players = [], onMove }: Props) { - const { openAccountModal } = useAccountModal(); - const { address: userAddress } = useAccount(); - const currentPlayer = players.find((player) => player.player.toLowerCase() === userAddress?.toLowerCase()); - useKeyboardMovement(onMove); - return ( -
-
- {onMove - ? mudConfig.enums.Direction.map((direction) => ( - - )) - : null} - - {players.map((player) => ( -
- {player === currentPlayer ?
: null} -
- ))} - - {!currentPlayer ? ( - onMove ? ( -
- onMove("North")} - > - Spawning… - -
- ) : ( -
- -
- ) - ) : null} -
-
- ); -} diff --git a/templates/react/packages/client/src/game/useKeyboardMovement.ts b/templates/react/packages/client/src/game/useKeyboardMovement.ts deleted file mode 100644 index 7e9074290f..0000000000 --- a/templates/react/packages/client/src/game/useKeyboardMovement.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { useEffect } from "react"; -import { Direction } from "../common"; - -const keys = new Map([ - ["ArrowUp", "North"], - ["ArrowRight", "East"], - ["ArrowDown", "South"], - ["ArrowLeft", "West"], -]); - -export const useKeyboardMovement = (move: undefined | ((direction: Direction) => void)) => { - useEffect(() => { - if (!move) return; - - const listener = (event: KeyboardEvent) => { - const direction = keys.get(event.key); - if (direction == null) return; - - event.preventDefault(); - move(direction); - }; - - window.addEventListener("keydown", listener); - return () => window.removeEventListener("keydown", listener); - }, [move]); -}; diff --git a/templates/react/packages/client/src/index.tsx b/templates/react/packages/client/src/index.tsx index 995e6ec9fd..c9b662c9f0 100644 --- a/templates/react/packages/client/src/index.tsx +++ b/templates/react/packages/client/src/index.tsx @@ -1,19 +1,34 @@ -import "tailwindcss/tailwind.css"; -import { StrictMode } from "react"; -import { createRoot } from "react-dom/client"; -import { Providers } from "./Providers"; +import ReactDOM from "react-dom/client"; import { App } from "./App"; -import { Explorer } from "./mud/Explorer"; -import { ErrorBoundary } from "react-error-boundary"; -import { ErrorFallback } from "./ui/ErrorFallback"; +import { setup } from "./mud/setup"; +import { MUDProvider } from "./MUDContext"; +import mudConfig from "contracts/mud.config"; -createRoot(document.getElementById("react-root")!).render( - - - - - - - - , -); +const rootElement = document.getElementById("react-root"); +if (!rootElement) throw new Error("React root not found"); +const root = ReactDOM.createRoot(rootElement); + +// TODO: figure out if we actually want this to be async or if we should render something else in the meantime +setup().then(async (result) => { + root.render( + + + , + ); + + // https://vitejs.dev/guide/env-and-mode.html + if (import.meta.env.DEV) { + const { mount: mountDevTools } = await import("@latticexyz/dev-tools"); + mountDevTools({ + config: mudConfig, + publicClient: result.network.publicClient, + walletClient: result.network.walletClient, + latestBlock$: result.network.latestBlock$, + storedBlockLogs$: result.network.storedBlockLogs$, + worldAddress: result.network.worldContract.address, + worldAbi: result.network.worldContract.abi, + write$: result.network.write$, + useStore: result.network.useStore, + }); + } +}); diff --git a/templates/react/packages/client/src/mud/Explorer.tsx b/templates/react/packages/client/src/mud/Explorer.tsx deleted file mode 100644 index fe59d58c57..0000000000 --- a/templates/react/packages/client/src/mud/Explorer.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { useState } from "react"; -import { getChain, getWorldAddress } from "../common"; -import { MUDIcon } from "../ui/icons/MUDIcon"; - -export function Explorer() { - const [open, setOpen] = useState(false); - - const chain = getChain(); - const worldAddress = getWorldAddress(); - - const explorerUrl = chain.blockExplorers?.worldsExplorer?.url; - if (!explorerUrl) return null; - - return ( -
- - {open ?