diff --git a/packages/client/public/models/block00.glb b/packages/client/public/models/block00.glb deleted file mode 100644 index ffd36d3..0000000 Binary files a/packages/client/public/models/block00.glb and /dev/null differ diff --git a/packages/client/public/models/block01.glb b/packages/client/public/models/block01.glb deleted file mode 100644 index 9b5bdc3..0000000 Binary files a/packages/client/public/models/block01.glb and /dev/null differ diff --git a/packages/client/public/models/facilities.glb b/packages/client/public/models/facilities.glb new file mode 100644 index 0000000..f982b10 Binary files /dev/null and b/packages/client/public/models/facilities.glb differ diff --git a/packages/client/src/game/data/entities.ts b/packages/client/src/game/data/entities.ts index 7d09f60..ef7c2ae 100644 --- a/packages/client/src/game/data/entities.ts +++ b/packages/client/src/game/data/entities.ts @@ -9,8 +9,17 @@ export type EntityDataType = { costs: [ResourceType, number][]; produces: [ResourceType, number, number][]; variants: ModelDataType[]; + tags: EntityTag[]; }; +export const entityTags = [ + "groundLevel", + "producesPower", + "producesGravity", + "producesPopulation", +] as const; +export type EntityTag = (typeof entityTags)[number]; + const EntityData = { facilities: { gravityhill: { @@ -21,6 +30,7 @@ const EntityData = { costs: [["lapu", 500]], produces: [["gravity", 25, 1]], variants: [ModelData.well00], + tags: ["groundLevel"], }, dynamo: { name: "Whirly Dynamo", @@ -31,6 +41,7 @@ const EntityData = { costs: [["lapu", 200]], produces: [["power", 25, 1]], variants: [ModelData.engine00], + tags: [], }, residence: { name: "Residence", @@ -41,6 +52,7 @@ const EntityData = { costs: [["lapu", 100]], produces: [["population", 5, 1]], variants: [ModelData.block00, ModelData.block01, ModelData.block02], + tags: [], }, } as { [key: string]: EntityDataType }, } as const; diff --git a/packages/client/src/game/data/models.ts b/packages/client/src/game/data/models.ts index 9a3d72b..6fa64e9 100644 --- a/packages/client/src/game/data/models.ts +++ b/packages/client/src/game/data/models.ts @@ -5,6 +5,9 @@ export type ModelDataType = { colors: string[]; }; +export const importModels = ["/models/plants.glb", "/models/facilities.glb"]; +export const importTextures = ["/textures/box01.webp"]; + const ModelData: { [key: string]: ModelDataType } = { block00: { name: "GenericBlock00", diff --git a/packages/client/src/game/entities/facility.tsx b/packages/client/src/game/entities/facility.tsx index 237e79c..84accca 100644 --- a/packages/client/src/game/entities/facility.tsx +++ b/packages/client/src/game/entities/facility.tsx @@ -3,16 +3,13 @@ import { useStore } from "../store"; import { AdditiveBlending, DoubleSide, Mesh, Vector3 } from "three"; import { animated } from "@react-spring/three"; import { MouseInputEvent, useInput } from "../input/useInput"; -import { - buildFacility, - canBuildAtPosition, -} from "../systems/constructionSystem"; +import { buildFacility } from "../systems/constructionSystem"; import { palette } from "../utils/palette"; import { faceDirections } from "@/lib/utils"; import { IFacility } from "../types/entities"; const Renderer = (props: IFacility) => { - const { colorPrimary, colorSecondary, scale, variant, rotation } = props; + const { colorPrimary, colorSecondary, variant, rotation } = props; const { assets: { meshes }, } = useStore(); @@ -29,7 +26,7 @@ const Renderer = (props: IFacility) => { return ( @@ -81,26 +78,16 @@ const Facility = (props: IFacility) => { const { onMouseMove } = useInput((event: MouseInputEvent) => { if (faceIndex === undefined) return; const direction = event.position.clone().add(faceDirections[faceIndex!]); - const canBuild = canBuildAtPosition(direction); - if (canBuild) { - cursor.setCursor({ - position: direction, - cursorState: "valid", - direction: faceDirections[faceIndex!].clone().negate(), - }); - } else { - cursor.setCursor({ cursorState: "hidden" }); - } + cursor.setCursor({ + position: direction, + direction: faceDirections[faceIndex!].clone().negate(), + }); }, entityRef); - const { onMouseDown, onMouseClick } = useInput((event: MouseInputEvent) => { + const { onMouseDown, onMouseClick } = useInput(() => { if (faceIndex === undefined) return; - const direction = event.position.clone().add(faceDirections[faceIndex!]); - const canBuild = canBuildAtPosition(direction); - if (canBuild) { - buildFacility(direction); - setFaceIndex(undefined); - } + buildFacility(cursor.position); + setFaceIndex(undefined); }, entityRef); return ( @@ -141,7 +128,7 @@ const Facility = (props: IFacility) => { ? palette.cursor : "black" } - visible={faceIndex !== undefined && faceIndex === index} + visible={false} transparent={true} // TODO: Remove the face highlighting completely, or use alternative face highlighting like in Townscraper opacity={0} diff --git a/packages/client/src/game/entities/ground.tsx b/packages/client/src/game/entities/ground.tsx index 541c244..c4843c1 100644 --- a/packages/client/src/game/entities/ground.tsx +++ b/packages/client/src/game/entities/ground.tsx @@ -3,10 +3,7 @@ import { Grid, GridProps } from "@react-three/drei"; import { useInput } from "../input/useInput"; import { getState, useStore } from "../store"; -import { - buildFacility, - canBuildAtPosition, -} from "../systems/constructionSystem"; +import { buildFacility } from "../systems/constructionSystem"; import { Directions } from "@/lib/utils"; const gridSize = 1000; @@ -38,10 +35,8 @@ function Ground() { const { input: { cursor }, } = getState(); - const canBuild = canBuildAtPosition(event.position); cursor.setCursor({ position: event.position, - cursorState: canBuild ? "valid" : "hidden", direction: Directions.DOWN(), }); }, gridRef); diff --git a/packages/client/src/game/input/cursor.tsx b/packages/client/src/game/input/cursor.tsx index 843bfad..e9de769 100644 --- a/packages/client/src/game/input/cursor.tsx +++ b/packages/client/src/game/input/cursor.tsx @@ -1,16 +1,18 @@ import { useEffect, useRef, useState } from "react"; import { Sparkles } from "@react-three/drei"; -import { AdditiveBlending, DoubleSide } from "three"; +import { AdditiveBlending, DoubleSide, Vector3 } from "three"; import { useStore } from "../store"; import { palette } from "../utils/palette"; import { faceDirections } from "@/lib/utils"; +import { canBuildAtPosition } from "../systems/constructionSystem"; function Cursor() { const cursorRef = useRef(null); const { input: { - cursor: { position, cursorState, direction }, + cursor: { position, cursorState, direction, setCursor }, + building, }, assets: { textures }, } = useStore(); @@ -23,16 +25,34 @@ function Cursor() { } }, [direction]); + useEffect(() => { + if (building) { + if (!canBuildAtPosition(position)) { + setCursor({ cursorState: "invalid" }); + } else { + setCursor({ cursorState: "valid" }); + } + } else { + setCursor({ cursorState: "hidden" }); + } + }, [cursorState, building, position, setCursor]); + return ( - + - + {/* Face mapping for direction */} {[...Array(6)].map((_, index) => ( {/* 🐁 main cursor block */} - - + + { + const { + input: { building }, + } = getState(); if (position.y < 0) return false; const { getEntityByPosition } = getState().world; const entity = getEntityByPosition(position); - return entity ? false : true; + if (entity) return false; + if (building && !building.tags.includes("groundLevel") && position.y < 1) { + return false; + } + return true; }; const getEntityInDirection = (position: Vector3, direction: Vector3) => { @@ -34,6 +42,7 @@ const buildFacility = (position: Vector3) => { if (!canBuildAtPosition(position)) { console.error("Cannot build here", position); + cursor.setCursor({ cursorState: "invalid" }); return; } @@ -43,7 +52,7 @@ const buildFacility = (position: Vector3) => { const newFacility = { position: position, - scale: new Vector3(Math.random() * 0.1 + 0.9, 1, Math.random() * 0.1 + 0.9), + scale: new Vector3(1, 1, 1), colorPrimary: getRandom(palette.buildingPrimary), colorSecondary: getRandom(palette.buildingSecondary), entityRef: createRef(), @@ -62,7 +71,6 @@ const buildFacility = (position: Vector3) => { addEntity(newFacility); // Move Input logic away from here - cursor.setCursor({ cursorState: "hidden" }); setInput({ building: undefined }); console.log(newFacility); }; diff --git a/packages/client/src/game/utils/importer.tsx b/packages/client/src/game/utils/importer.tsx index 03f0379..846af62 100644 --- a/packages/client/src/game/utils/importer.tsx +++ b/packages/client/src/game/utils/importer.tsx @@ -3,9 +3,7 @@ import { useGLTF, useTexture } from "@react-three/drei"; import { Material, Mesh, Texture } from "three"; import type { GLTF } from "three-stdlib"; import { useStore } from "../store"; - -const models = ["/models/plants.glb", "/models/block01.glb"]; -const textures = ["/textures/box01.webp"]; +import { importModels, importTextures } from "../data/models"; export interface Assets { meshes: Record; @@ -51,12 +49,12 @@ function TextureLoader({ path }: { path: string }) { useTexture.preload(path); }, [path]); - // Loading and storing the model + // Loading and storing the texture const texture = useTexture(path) as Texture; useEffect(() => { if (texture) { - textures.forEach((node) => { + importTextures.forEach((node) => { try { addTexture(node.replace("/textures/", "").split(".")[0], texture); } catch (error) { @@ -72,10 +70,10 @@ function TextureLoader({ path }: { path: string }) { function Importer() { return ( <> - {models.map((model) => ( + {importModels.map((model) => ( ))} - {textures.map((texture) => ( + {importTextures.map((texture) => ( ))} diff --git a/packages/client/src/game/utils/palette.ts b/packages/client/src/game/utils/palette.ts index 77d7503..842d06b 100644 --- a/packages/client/src/game/utils/palette.ts +++ b/packages/client/src/game/utils/palette.ts @@ -4,6 +4,7 @@ const grassColors = ["#9BD48A", "#8FCD5F", "#69CD1E"]; const palette = { cursor: "#76EAE4", + cursorInvalid: "#ff0000", buildingPrimary: buildingPrimary, buildingSecondary: buildingSecondary, grassColors: grassColors, diff --git a/packages/contracts/worlds.json b/packages/contracts/worlds.json index bd48105..ab87925 100644 --- a/packages/contracts/worlds.json +++ b/packages/contracts/worlds.json @@ -1,5 +1,5 @@ { "31337": { - "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3" + "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e" } } \ No newline at end of file