From d4c98f7e086a8b1b675b0b7a184340cd5dd23385 Mon Sep 17 00:00:00 2001 From: Dhvani Patel Date: Wed, 1 May 2024 12:38:24 +0100 Subject: [PATCH 1/7] build for drops contract and client --- packages/hardhat/contracts/Game.sol | 148 ++++- packages/hardhat/deploy/00_deploy_game.ts | 2 +- packages/nextjs/app/page.tsx | 3 +- packages/nextjs/components/Game.tsx | 119 +++- packages/nextjs/components/Landing.tsx | 4 +- packages/nextjs/components/RegisterBiomes.tsx | 4 +- .../nextjs/contracts/deployedContracts.ts | 605 ++++++------------ 7 files changed, 427 insertions(+), 458 deletions(-) diff --git a/packages/hardhat/contracts/Game.sol b/packages/hardhat/contracts/Game.sol index ba911094..908e20d9 100644 --- a/packages/hardhat/contracts/Game.sol +++ b/packages/hardhat/contracts/Game.sol @@ -12,13 +12,27 @@ import { RESOURCE_SYSTEM } from "@latticexyz/world/src/worldResourceTypes.sol"; import { OptionalSystemHooks } from "@latticexyz/world/src/codegen/tables/OptionalSystemHooks.sol"; import { IWorld } from "@biomesaw/world/src/codegen/world/IWorld.sol"; +import { IDropSystem } from "@biomesaw/world/src/codegen/world/IDropSystem.sol"; import { VoxelCoord } from "@biomesaw/utils/src/Types.sol"; +import { Build, buildExistsInWorld } from "../utils/BuildUtils.sol"; +import { ObjectTypeMetadata } from "@biomesaw/world/src/codegen/tables/ObjectTypeMetadata.sol"; +import { AirObjectID } from "@biomesaw/world/src/ObjectTypeIds.sol"; +import { getObjectType, getEntityAtCoord, getPosition, getEntityFromPlayer, getObjectTypeAtCoord } from "../utils/EntityUtils.sol"; +import { voxelCoordsAreEqual } from "@biomesaw/utils/src/VoxelCoordUtils.sol"; contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { address public immutable biomeWorldAddress; address public delegatorAddress; + address[] public allowedItemDrops; + mapping(bytes32 => address) public coordHashToBuilder; + + Build private build; + + ResourceId BuildSystemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "BuildSystem" }); + ResourceId DropSystemId = WorldResourceIdLib.encode({ typeId: RESOURCE_SYSTEM, namespace: "", name: "DropSystem" }); + event GameNotif(address player, string message); constructor(address _biomeWorldAddress, address _delegatorAddress) { @@ -46,7 +60,7 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { } function canUnregister(address delegator) external override onlyBiomeWorld returns (bool) { - return true; + return allowedItemDrops.length == 0; } function onRegisterHook( @@ -69,17 +83,139 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { bytes memory callData ) external override onlyBiomeWorld {} + function getCoordHash(VoxelCoord memory coord) internal pure returns (bytes32) { + return bytes32(keccak256(abi.encode(coord.x, coord.y, coord.z))); + } + function onAfterCallSystem( address msgSender, ResourceId systemId, bytes memory callData - ) external override onlyBiomeWorld {} + ) external override onlyBiomeWorld { + if (ResourceId.unwrap(systemId) == ResourceId.unwrap(BuildSystemId)) { + Slice callDataArgs = SliceLib.getSubslice(callData, 4); + (, VoxelCoord memory coord) = abi.decode(callDataArgs.toBytes(), (uint8, VoxelCoord)); + coordHashToBuilder[getCoordHash(coord)] = msgSender; + } + } + + function setBuild(uint8[] memory objectTypeIds, VoxelCoord[] memory relativePositions) external { + require(msg.sender == delegatorAddress, "Only delegator can add build"); + require(objectTypeIds.length > 0, "AddBuild: Must specify at least one object type ID"); + require( + objectTypeIds.length == relativePositions.length, + "AddBuild: Number of object type IDs must match number of relative positions" + ); + require( + voxelCoordsAreEqual(relativePositions[0], VoxelCoord({ x: 0, y: 0, z: 0 })), + "AddBuild: First relative position must be (0, 0, 0)" + ); + require(build.objectTypeIds.length == 0, "Logo build already set"); + + for (uint i = 0; i < objectTypeIds.length; ++i) { + build.objectTypeIds.push(objectTypeIds[i]); + } + for (uint i = 0; i < relativePositions.length; ++i) { + build.relativePositions.push( + VoxelCoord({ x: relativePositions[i].x, y: relativePositions[i].y, z: relativePositions[i].z }) + ); + } + } + + function matchBuild(VoxelCoord memory baseWorldCoord) external { + require(build.objectTypeIds.length > 0, "Logo build not set"); + + address msgSender = msg.sender; + + // Go through each relative position, aplpy it to the base world coord, and check if the object type id matches + for (uint256 i = 0; i < build.objectTypeIds.length; i++) { + VoxelCoord memory absolutePosition = VoxelCoord({ + x: baseWorldCoord.x + build.relativePositions[i].x, + y: baseWorldCoord.y + build.relativePositions[i].y, + z: baseWorldCoord.z + build.relativePositions[i].z + }); + bytes32 entityId = getEntityAtCoord(absolutePosition); + + uint8 objectTypeId; + if (entityId == bytes32(0)) { + // then it's the terrain + objectTypeId = IWorld(biomeWorldAddress).getTerrainBlock(absolutePosition); + } else { + objectTypeId = getObjectType(entityId); + + address builder = coordHashToBuilder[getCoordHash(absolutePosition)]; + require(builder == msgSender, "Builder does not match"); + } + if (objectTypeId != build.objectTypeIds[i]) { + revert("Build does not match"); + } + } + + // Add user to allowed item drops, if not already added + bool isAllowed = false; + for (uint i = 0; i < allowedItemDrops.length; i++) { + if (allowedItemDrops[i] == msgSender) { + isAllowed = true; + break; + } + } + require(!isAllowed, "Already allowed to drop items"); + allowedItemDrops.push(msgSender); + } + + function getEmptyBlockOnGround(VoxelCoord memory centerCoord) internal returns (VoxelCoord memory) { + for (int8 dx = -1; dx <= 1; dx++) { + for (int8 dy = -1; dy <= 1; dy++) { + for (int8 dz = -1; dz <= 1; dz++) { + VoxelCoord memory coord = VoxelCoord({ x: centerCoord.x + dx, y: centerCoord.y + dy, z: centerCoord.z + dz }); + VoxelCoord memory coordBelow = VoxelCoord({ + x: centerCoord.x + dx, + y: centerCoord.y + dy - 1, + z: centerCoord.z + dz + }); + + if ( + getObjectTypeAtCoord(biomeWorldAddress, coord) == AirObjectID && + getObjectTypeAtCoord(biomeWorldAddress, coordBelow) != AirObjectID + ) { + return coord; + } + } + } + } + revert("No empty block on ground"); + } + + function dropItem(bytes32 toolEntityId) external { + address msgSender = msg.sender; + bool isAllowed = false; + for (uint i = 0; i < allowedItemDrops.length; i++) { + if (allowedItemDrops[i] == msgSender) { + allowedItemDrops[i] = allowedItemDrops[allowedItemDrops.length - 1]; + allowedItemDrops.pop(); + isAllowed = true; + break; + } + } + require(isAllowed, "Not allowed to drop items"); + + bytes32 playerEntityId = getEntityFromPlayer(delegatorAddress); + require(playerEntityId != bytes32(0), "Player entity not found"); + VoxelCoord memory playerPosition = getPosition(playerEntityId); + VoxelCoord memory dropCoord = getEmptyBlockOnGround(playerPosition); + + bytes memory dropCallData = abi.encodeCall(IDropSystem.dropTool, (toolEntityId, dropCoord)); + + IWorld(biomeWorldAddress).callFrom(delegatorAddress, DropSystemId, dropCallData); + } - function basicGetter() external view returns (uint256) { - return 42; + // Getters + // ------------------------------------------------------------------------ + function getBuild() external view returns (Build memory) { + return build; } - function getRegisteredPlayers() external view returns (address[] memory) { - return new address[](0); + function getAllowedItemDrops() external view returns (address[] memory) { + return allowedItemDrops; } } diff --git a/packages/hardhat/deploy/00_deploy_game.ts b/packages/hardhat/deploy/00_deploy_game.ts index 322eef8e..99a535e9 100644 --- a/packages/hardhat/deploy/00_deploy_game.ts +++ b/packages/hardhat/deploy/00_deploy_game.ts @@ -49,7 +49,7 @@ const deployGameContract: DeployFunction = async function (hre: HardhatRuntimeEn await deploy("Game", { from: deployer, // Contract constructor arguments - args: [useBiomesWorldAddress, "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"], + args: [useBiomesWorldAddress, "0xE0ae70caBb529336e25FA7a1f036b77ad0089d2a"], log: true, // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by // automatically mining the contract deployment transaction. There is no effect on live networks. diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx index d24f87f5..2649bb6d 100644 --- a/packages/nextjs/app/page.tsx +++ b/packages/nextjs/app/page.tsx @@ -16,7 +16,8 @@ const Home: NextPage = () => { const setStage = useGlobalState(({ setStage }) => setStage); const isBiomesRegistered = useGlobalState(({ isBiomesRegistered }) => isBiomesRegistered); - const isGameRegistered = useGlobalState(({ isGameRegistered }) => isGameRegistered); + // const isGameRegistered = useGlobalState(({ isGameRegistered }) => isGameRegistered); + const isGameRegistered = true; const isBiomesClientSetup = useGlobalState(({ isBiomesClientSetup }) => isBiomesClientSetup); useEffect(() => { diff --git a/packages/nextjs/components/Game.tsx b/packages/nextjs/components/Game.tsx index 4ad2a72d..b3dc5bd6 100644 --- a/packages/nextjs/components/Game.tsx +++ b/packages/nextjs/components/Game.tsx @@ -1,7 +1,8 @@ import { useReducer } from "react"; import { Abi, AbiFunction } from "abitype"; +import { TransactionReceipt } from "viem"; import { useAccount } from "wagmi"; -import { DisplayVariable, displayTxResult } from "~~/app/debug/_components/contract"; +import { DisplayVariable, WriteOnlyFunctionForm, displayTxResult } from "~~/app/debug/_components/contract"; import { useDeployedContractInfo } from "~~/hooks/scaffold-eth"; import { GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract"; @@ -18,6 +19,26 @@ export const Game: React.FC = ({}) => { return
Loading...
; } + const writeFunctions = ((deployedContractData.abi as Abi).filter(part => part.type === "function") as AbiFunction[]) + .filter(fn => { + const isWriteableFunction = + fn.stateMutability !== "view" && + fn.stateMutability !== "pure" && + fn.name !== "onAfterCallSystem" && + fn.name !== "onBeforeCallSystem" && + fn.name !== "onRegisterHook" && + fn.name !== "onUnregisterHook" && + fn.name !== "canUnregister"; + return isWriteableFunction; + }) + .map(fn => { + return { + fn, + inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name], + }; + }) + .sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1)); + const viewFunctions = ((deployedContractData.abi as Abi).filter(part => part.type === "function") as AbiFunction[]) .filter(fn => { const isQueryableWithNoParams = @@ -32,7 +53,13 @@ export const Game: React.FC = ({}) => { }) .sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1)); - const basicGetterFn = viewFunctions.find(({ fn }) => fn.name === "basicGetter"); + const dropItem = writeFunctions.find(fn => fn.fn.name === "dropItem"); + const matchBuild = writeFunctions.find(fn => fn.fn.name === "matchBuild"); + const getAllowedItemDrops = viewFunctions.find(({ fn }) => fn.name === "getAllowedItemDrops"); + + if (dropItem === undefined || matchBuild === undefined || getAllowedItemDrops === undefined) { + return
Missing required functions
; + } return (
@@ -64,42 +91,72 @@ export const Game: React.FC = ({}) => {

Play Game

- Your Main Game Screen + Submit builds and drop items!

-
+
+
+ { + return; + }} + onBlockConfirmation={(txnReceipt: TransactionReceipt) => { + console.log("txnReceipt", txnReceipt); + }} + contractAddress={deployedContractData.address} + inheritedFrom={matchBuild?.inheritedFrom} + /> +
+
+ { + return; + }} + onBlockConfirmation={(txnReceipt: TransactionReceipt) => { + console.log("txnReceipt", txnReceipt); + }} + contractAddress={deployedContractData.address} + inheritedFrom={dropItem?.inheritedFrom} + /> +
+
+ + {({ result, RefreshButton }) => { + // if (isFetching) return
Loading...
; + + return ( +
+
+
Players Allowed Item Drops
+
{RefreshButton}
+
+ {displayTxResult(result)} +
+ ); + }} +
+
+
- {basicGetterFn && ( - - {({ result, RefreshButton }) => { - return ( -
-
- YOUR GETTER {RefreshButton} -
-
{displayTxResult(result)}
-
- ); - }} -
- )} -
+ > ); diff --git a/packages/nextjs/components/Landing.tsx b/packages/nextjs/components/Landing.tsx index dba0f692..e1f0df69 100644 --- a/packages/nextjs/components/Landing.tsx +++ b/packages/nextjs/components/Landing.tsx @@ -45,9 +45,9 @@ export const Landing: React.FC = ({}) => {
-

Your Game Title

+

Build Bitcoin Logos for Item Drops

- Your game description + Build bitcoin logos and claim your item drops

{ const { address: connectedAddress } = useAccount(); @@ -87,7 +87,7 @@ export const RegisterBiomes: React.FC = ({}) => {

HOOKS

Date: Wed, 1 May 2024 12:42:41 +0100 Subject: [PATCH 2/7] deploy --- packages/nextjs/.firebaserc | 5 +++++ packages/nextjs/firebase.json | 10 ++++++++++ packages/nextjs/package.json | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 packages/nextjs/.firebaserc create mode 100644 packages/nextjs/firebase.json diff --git a/packages/nextjs/.firebaserc b/packages/nextjs/.firebaserc new file mode 100644 index 00000000..7f13c06a --- /dev/null +++ b/packages/nextjs/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "biomes-build-for-drops" + } +} diff --git a/packages/nextjs/firebase.json b/packages/nextjs/firebase.json new file mode 100644 index 00000000..c5c52092 --- /dev/null +++ b/packages/nextjs/firebase.json @@ -0,0 +1,10 @@ +{ + "hosting": { + "public": "out", + "ignore": [ + "firebase.json", + "**/.*", + "**/node_modules/**" + ] + } +} diff --git a/packages/nextjs/package.json b/packages/nextjs/package.json index 3e8833eb..d266beba 100644 --- a/packages/nextjs/package.json +++ b/packages/nextjs/package.json @@ -11,7 +11,8 @@ "format": "prettier --write . '!(node_modules|.next|contracts)/**/*'", "check-types": "tsc --noEmit --incremental", "vercel": "vercel", - "vercel:yolo": "vercel --build-env NEXT_PUBLIC_IGNORE_BUILD_ERROR=true" + "vercel:yolo": "vercel --build-env NEXT_PUBLIC_IGNORE_BUILD_ERROR=true", + "deploy": "NEXT_PUBLIC_IGNORE_BUILD_ERROR=true yarn run build && firebase use biomes-build-for-drops && firebase deploy" }, "dependencies": { "@biomesaw/utils": "0.0.8", From 12fdc6f9fc68dc33615f15c82c8fb80cb4a1b636 Mon Sep 17 00:00:00 2001 From: Dhvani Patel Date: Sat, 11 May 2024 11:32:25 +0100 Subject: [PATCH 3/7] getter --- packages/hardhat/contracts/Game.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/hardhat/contracts/Game.sol b/packages/hardhat/contracts/Game.sol index 908e20d9..23e0a486 100644 --- a/packages/hardhat/contracts/Game.sol +++ b/packages/hardhat/contracts/Game.sol @@ -20,6 +20,8 @@ import { AirObjectID } from "@biomesaw/world/src/ObjectTypeIds.sol"; import { getObjectType, getEntityAtCoord, getPosition, getEntityFromPlayer, getObjectTypeAtCoord } from "../utils/EntityUtils.sol"; import { voxelCoordsAreEqual } from "@biomesaw/utils/src/VoxelCoordUtils.sol"; +import { NamedBuild } from "../utils/GameUtils.sol"; + contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { address public immutable biomeWorldAddress; @@ -218,4 +220,14 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { function getAllowedItemDrops() external view returns (address[] memory) { return allowedItemDrops; } + + function getDisplayName() external view returns (string memory) { + return "Build For Drops"; + } + + function getBuilds() external view returns (NamedBuild[] memory) { + NamedBuild[] memory builds = new NamedBuild[](1); + builds[0] = NamedBuild({ name: "Logo", build: build }); + return builds; + } } From 11ad9390147d68438f829796d96151d057088909 Mon Sep 17 00:00:00 2001 From: Dhvani Patel Date: Mon, 13 May 2024 11:11:33 +0100 Subject: [PATCH 4/7] use hook util --- packages/hardhat/contracts/Game.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/hardhat/contracts/Game.sol b/packages/hardhat/contracts/Game.sol index 23e0a486..4f8b4448 100644 --- a/packages/hardhat/contracts/Game.sol +++ b/packages/hardhat/contracts/Game.sol @@ -19,6 +19,7 @@ import { ObjectTypeMetadata } from "@biomesaw/world/src/codegen/tables/ObjectTyp import { AirObjectID } from "@biomesaw/world/src/ObjectTypeIds.sol"; import { getObjectType, getEntityAtCoord, getPosition, getEntityFromPlayer, getObjectTypeAtCoord } from "../utils/EntityUtils.sol"; import { voxelCoordsAreEqual } from "@biomesaw/utils/src/VoxelCoordUtils.sol"; +import { decodeCallData } from "../utils/HookUtils.sol"; import { NamedBuild } from "../utils/GameUtils.sol"; @@ -95,8 +96,8 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { bytes memory callData ) external override onlyBiomeWorld { if (ResourceId.unwrap(systemId) == ResourceId.unwrap(BuildSystemId)) { - Slice callDataArgs = SliceLib.getSubslice(callData, 4); - (, VoxelCoord memory coord) = abi.decode(callDataArgs.toBytes(), (uint8, VoxelCoord)); + (, bytes memory callDataArgs) = decodeCallData(callData); + (, VoxelCoord memory coord) = abi.decode(callDataArgs, (uint8, VoxelCoord)); coordHashToBuilder[getCoordHash(coord)] = msgSender; } } From 87247402e346bb17d3fa2c6327105adfbbf0e4d5 Mon Sep 17 00:00:00 2001 From: Dhvani Patel Date: Tue, 14 May 2024 11:26:39 +0100 Subject: [PATCH 5/7] getters --- packages/hardhat/contracts/Game.sol | 80 ++++++++++++++++++----------- packages/nextjs/app/page.tsx | 3 +- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/packages/hardhat/contracts/Game.sol b/packages/hardhat/contracts/Game.sol index 4f8b4448..de7835a7 100644 --- a/packages/hardhat/contracts/Game.sol +++ b/packages/hardhat/contracts/Game.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.24; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { StoreSwitch } from "@latticexyz/store/src/StoreSwitch.sol"; import { ResourceId, WorldResourceIdLib, WorldResourceIdInstance } from "@latticexyz/world/src/WorldResourceId.sol"; import { Hook } from "@latticexyz/store/src/Hook.sol"; @@ -21,7 +22,7 @@ import { getObjectType, getEntityAtCoord, getPosition, getEntityFromPlayer, getO import { voxelCoordsAreEqual } from "@biomesaw/utils/src/VoxelCoordUtils.sol"; import { decodeCallData } from "../utils/HookUtils.sol"; -import { NamedBuild } from "../utils/GameUtils.sol"; +import { NamedBuild, getEmptyBlockOnGround } from "../utils/GameUtils.sol"; contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { address public immutable biomeWorldAddress; @@ -166,29 +167,6 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { allowedItemDrops.push(msgSender); } - function getEmptyBlockOnGround(VoxelCoord memory centerCoord) internal returns (VoxelCoord memory) { - for (int8 dx = -1; dx <= 1; dx++) { - for (int8 dy = -1; dy <= 1; dy++) { - for (int8 dz = -1; dz <= 1; dz++) { - VoxelCoord memory coord = VoxelCoord({ x: centerCoord.x + dx, y: centerCoord.y + dy, z: centerCoord.z + dz }); - VoxelCoord memory coordBelow = VoxelCoord({ - x: centerCoord.x + dx, - y: centerCoord.y + dy - 1, - z: centerCoord.z + dz - }); - - if ( - getObjectTypeAtCoord(biomeWorldAddress, coord) == AirObjectID && - getObjectTypeAtCoord(biomeWorldAddress, coordBelow) != AirObjectID - ) { - return coord; - } - } - } - } - revert("No empty block on ground"); - } - function dropItem(bytes32 toolEntityId) external { address msgSender = msg.sender; bool isAllowed = false; @@ -205,7 +183,7 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { bytes32 playerEntityId = getEntityFromPlayer(delegatorAddress); require(playerEntityId != bytes32(0), "Player entity not found"); VoxelCoord memory playerPosition = getPosition(playerEntityId); - VoxelCoord memory dropCoord = getEmptyBlockOnGround(playerPosition); + VoxelCoord memory dropCoord = getEmptyBlockOnGround(biomeWorldAddress, playerPosition); bytes memory dropCallData = abi.encodeCall(IDropSystem.dropTool, (toolEntityId, dropCoord)); @@ -222,13 +200,57 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { return allowedItemDrops; } - function getDisplayName() external view returns (string memory) { - return "Build For Drops"; - } - function getBuilds() external view returns (NamedBuild[] memory) { NamedBuild[] memory builds = new NamedBuild[](1); builds[0] = NamedBuild({ name: "Logo", build: build }); return builds; } + + function getDisplayName() external view returns (string memory) { + return "Build For Drops"; + } + + function getStatus() external view returns (string memory) { + if (msg.sender == delegatorAddress) { + if (build.objectTypeIds.length == 0) { + return "Build not set yet. Please set the build."; + } + + if (allowedItemDrops.length == 0) { + return "No players have been submitted matching builds. Please wait."; + } + + return string.concat("Build set. ", Strings.toString(allowedItemDrops.length), " players allowed to drop items."); + } else { + if (build.objectTypeIds.length == 0) { + return "Build not set yet. Please wait."; + } + + bool isAllowed = false; + for (uint i = 0; i < allowedItemDrops.length; i++) { + if (allowedItemDrops[i] == msg.sender) { + isAllowed = true; + break; + } + } + if (isAllowed) { + return "Allowed to drop items!"; + } else { + return "Not allowed to drop items. Build and submit to be allowed."; + } + } + } + + function getUnregisterMessage() external view returns (string memory) { + if (msg.sender == delegatorAddress && allowedItemDrops.length > 0) { + return + string.concat( + "You cannot unregister until all ", + Strings.toString(allowedItemDrops.length), + " players have used their allowed item drops." + ); + } + + return ""; + } } diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx index 2649bb6d..a227533e 100644 --- a/packages/nextjs/app/page.tsx +++ b/packages/nextjs/app/page.tsx @@ -18,7 +18,8 @@ const Home: NextPage = () => { const isBiomesRegistered = useGlobalState(({ isBiomesRegistered }) => isBiomesRegistered); // const isGameRegistered = useGlobalState(({ isGameRegistered }) => isGameRegistered); const isGameRegistered = true; - const isBiomesClientSetup = useGlobalState(({ isBiomesClientSetup }) => isBiomesClientSetup); + // const isBiomesClientSetup = useGlobalState(({ isBiomesClientSetup }) => isBiomesClientSetup); + const isBiomesClientSetup = true; useEffect(() => { if (connectedAddress) { From 2b8ea9cacb2003b6c70c50e6a6f3dedbbcb24fbb Mon Sep 17 00:00:00 2001 From: Dhvani Patel Date: Tue, 14 May 2024 11:27:56 +0100 Subject: [PATCH 6/7] fix delegator --- packages/hardhat/deploy/00_deploy_game.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/hardhat/deploy/00_deploy_game.ts b/packages/hardhat/deploy/00_deploy_game.ts index 99a535e9..322eef8e 100644 --- a/packages/hardhat/deploy/00_deploy_game.ts +++ b/packages/hardhat/deploy/00_deploy_game.ts @@ -49,7 +49,7 @@ const deployGameContract: DeployFunction = async function (hre: HardhatRuntimeEn await deploy("Game", { from: deployer, // Contract constructor arguments - args: [useBiomesWorldAddress, "0xE0ae70caBb529336e25FA7a1f036b77ad0089d2a"], + args: [useBiomesWorldAddress, "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"], log: true, // autoMine: can be passed to the deploy function to make the deployment process faster on local networks by // automatically mining the contract deployment transaction. There is no effect on live networks. From 26ff82ccfdef4aea3f442fb94c34e0cc43b923d2 Mon Sep 17 00:00:00 2001 From: Dhvani Patel Date: Tue, 14 May 2024 17:38:11 +0100 Subject: [PATCH 7/7] Add events --- packages/hardhat/contracts/Game.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/hardhat/contracts/Game.sol b/packages/hardhat/contracts/Game.sol index de7835a7..b9459cf6 100644 --- a/packages/hardhat/contracts/Game.sol +++ b/packages/hardhat/contracts/Game.sol @@ -165,6 +165,8 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { } require(!isAllowed, "Already allowed to drop items"); allowedItemDrops.push(msgSender); + + emit GameNotif(delegatorAddress, "A new player has been added to allowed item drops"); } function dropItem(bytes32 toolEntityId) external { @@ -188,6 +190,8 @@ contract Game is ICustomUnregisterDelegation, IOptionalSystemHook { bytes memory dropCallData = abi.encodeCall(IDropSystem.dropTool, (toolEntityId, dropCoord)); IWorld(biomeWorldAddress).callFrom(delegatorAddress, DropSystemId, dropCallData); + + emit GameNotif(delegatorAddress, "Item dropped"); } // Getters