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