Skip to content

Commit

Permalink
refactor: monster refactor of UseEffects
Browse files Browse the repository at this point in the history
had to refactor all useeffect hooks to stop using useState
  • Loading branch information
Cygnusfear committed Oct 17, 2023
1 parent decd7f8 commit e483fbc
Show file tree
Hide file tree
Showing 31 changed files with 475 additions and 166 deletions.
Binary file added packages/client/public/couple.webp
Binary file not shown.
Binary file added packages/client/public/friends.webp
Binary file not shown.
Binary file added packages/client/public/house.webp
Binary file not shown.
Binary file added packages/client/public/icons/engine.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/client/public/icons/engine.webp
Binary file not shown.
Binary file added packages/client/public/icons/gravity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/client/public/icons/gravity.webp
Binary file not shown.
Binary file added packages/client/public/icons/residence.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/client/public/icons/residence.webp
Binary file not shown.
Binary file added packages/client/public/power.webp
Binary file not shown.
Binary file added packages/client/public/scroll.webp
Binary file not shown.
9 changes: 2 additions & 7 deletions packages/client/src/components/ui/colorWheel.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
import { useState } from "react";
import Wheel from "@uiw/react-color-wheel";
import { ColorResult, hexToHsva } from "@uiw/color-convert";
import { useStore } from "@/game/store";
import { getRandom } from "@/lib/utils";
import { palette } from "@/game/utils/palette";
import { getState } from "@/game/store";

const randomColor = getRandom(palette.buildingSecondary);

function ColorWheel() {
const [hsva, setHsva] = useState(hexToHsva(randomColor));
const [hex, setHex] = useState(randomColor);
const {
input: {
cursor: { setCursor },
},
} = useStore();

const setColor = (color: ColorResult) => {
console.log(color.hex);
setHex(color.hex);
setCursor({ color: color.hex });
getState().input.cursor.setCursor({ color: color.hex });
setHsva({ ...hsva, ...color.hsva });
};

Expand Down
2 changes: 2 additions & 0 deletions packages/client/src/components/ui/gameUI.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Inventory } from "./inventory";
import { ResourcePanel } from "./resourcePanel";
import { Tutorial } from "./tutorialModal";

function GameUI() {
return (
<div className="interface">
<Inventory />
<ResourcePanel />
<Tutorial />
</div>
);
}
Expand Down
115 changes: 66 additions & 49 deletions packages/client/src/components/ui/inventory.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import EntityData, { FacilityDataType } from "@/game/data/entities";
import "./inventory.css";
import { useStore } from "@/game/store";
import { getState, useStore } from "@/game/store";
import { ResourceIcons, ResourceType } from "@/game/data/resources";
import { cn } from "@/lib/utils";
import { useEffect, useMemo, useState } from "react";
Expand All @@ -10,41 +10,37 @@ import {
useTransition,
type SpringValue,
} from "@react-spring/web";
import { useOnce } from "@/lib/useOnce";
import { canAffordBuilding } from "@/game/systems/constructionSystem";
import ColorWheel from "./colorWheel";
import { tutorialSteps } from "@/game/data/tutorial";

function Inventory() {
const {
world: { entities },
player: {
playerData: { tutorialIndex },
},
} = useStore();
const [loaded, setLoaded] = useState(false);
const [cardsLoaded, setcardsLoaded] = useState(false);
const [facilities, setFacilities] = useState<FacilityDataType[]>([]);

useOnce(() => {
const f = Object.entries(EntityData.facilities)
.map(([, entityData]) => entityData)
.filter((entityData) => entityData.tags.includes("startingItem"));
setFacilities(f);
document.addEventListener("gameLoaded", () => {
setLoaded(true);
});
return () => {
document.removeEventListener("gameLoaded", () => {});
useEffect(() => {
const loadInventoryItems = () => {
if (tutorialIndex <= tutorialSteps.length - 1) {
const f = Object.entries(EntityData.facilities)
.map(([, entityData]) => entityData)
.filter((entityData) =>
tutorialSteps[tutorialIndex].inventory.includes(entityData)
);
setFacilities(f);
} else {
const f = Object.entries(EntityData.facilities).map(
([, entityData]) => entityData
);
setFacilities(f);
}
};
});

useEffect(() => {
// TODO: Remove hack to only show gravityhill at startup
if (!loaded) return;
if (cardsLoaded) return;
const f = Object.entries(EntityData.facilities)
.map(([, entityData]) => entityData)
.filter((entityData) => !facilities.includes(entityData));
setFacilities([...facilities, ...f]);
setcardsLoaded(true);
}, [cardsLoaded, entities, facilities, loaded]);
loadInventoryItems();
}, [tutorialIndex]);

const listTransitions = useTransition(facilities, {
config: config.gentle,
Expand All @@ -62,10 +58,9 @@ function Inventory() {
return (
<div className="inventory-bar">
<ColorWheel />
{loaded &&
listTransitions((styles, entityData) => (
<InventoryItem {...entityData} style={styles} />
))}
{listTransitions((styles, entityData) => (
<InventoryItem {...entityData} style={styles} />
))}
</div>
);
}
Expand All @@ -78,9 +73,9 @@ function InventoryItem(
};
}
) {
const { name, blurb, image, produces, costs, style } = props;
const { name, blurb, image, produces, generates, costs, style } = props;
const {
input: { cursor, setInput, building },
input: { building },
} = useStore();

const tooExpensive = useMemo(() => !canAffordBuilding(props), [props]);
Expand All @@ -90,6 +85,7 @@ function InventoryItem(
};

const handleClick = () => {
const { setInput, cursor } = getState().input;
if (building?.name === props.name) setInput({ building: undefined });
else {
setInput({ building: props });
Expand Down Expand Up @@ -141,23 +137,44 @@ function InventoryItem(
})}
</div>
<div className="card-produces">
{Object.entries(produces).map(([key, value]) => {
const resource = value;
const IconComponent = ResourceIcons[resource[0] as ResourceType];
return (
<div
key={key}
className="card-produces-item flex flex-row items-center"
>
<span className="card-produces-item-value inline">
{resource[1]}
</span>
{IconComponent && (
<IconComponent className="ml-0.5 inline self-center" />
)}
</div>
);
})}
{produces &&
Object.entries(produces).map(([key, value]) => {
const resource = value;
const IconComponent =
ResourceIcons[resource[0] as ResourceType];
return (
<div
key={key}
className="card-produces-item flex flex-row items-center"
>
<span className="card-produces-item-value inline">
{resource[1]}
</span>
{IconComponent && (
<IconComponent className="ml-0.5 inline self-center" />
)}
</div>
);
})}
{generates &&
Object.entries(generates).map(([key, value]) => {
const resource = value;
const IconComponent =
ResourceIcons[resource[0] as ResourceType];
return (
<div
key={key}
className="card-produces-item flex flex-row items-center"
>
<span className="card-produces-item-value inline">
{resource[1]}
</span>
{IconComponent && (
<IconComponent className="ml-0.5 inline self-center" />
)}
</div>
);
})}
</div>
</div>
</animated.div>
Expand Down
113 changes: 113 additions & 0 deletions packages/client/src/components/ui/tutorialModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Tutorial.tsx
import {
TutorialStep,
hasRequiredFacilities,
tutorialSteps,
} from "@/game/data/tutorial";
import { getState } from "@/game/store";
import { useState, useEffect } from "react";

function TutorialModal({
step,
screenIndex,
onNext,
}: {
step: TutorialStep;
screenIndex: number;
onNext: () => void;
}) {
const currentScreen = step.screens[screenIndex];

return (
<div className="fixed left-0 top-0 flex h-full w-full items-center justify-center bg-black/50">
<div className="flex max-w-[50rem] flex-col rounded-lg border border-[#76EAE4] bg-[#76eae495] p-6 text-white shadow-lg">
<div className="flex-1">
<h2 className="mb-4 text-2xl">{step.screens[screenIndex].name}</h2>
<div className="flex flex-row items-center justify-between gap-4">
<p
className="flex-1"
dangerouslySetInnerHTML={{
__html: step.screens[screenIndex].text,
}}
></p>
<div className="flex-2">
{currentScreen?.image && (
<img
src={currentScreen.image}
alt="Tutorial image"
className="h-auto w-80"
/>
)}
{currentScreen?.entity && (
<img
src={`/icons/${currentScreen.entity.image}`}
alt="Entity image"
className="mb-4 h-auto w-80"
/>
)}
</div>
</div>
</div>
<div className="mt-4 flex justify-end">
<button
onClick={() => onNext()}
className="rounded bg-[#76EAE4] px-4 py-2 text-white"
>
Next
</button>
</div>
</div>
</div>
);
}

const Tutorial = () => {
const [currentStep, setCurrentStep] = useState<number>(
getState().player.playerData.tutorialIndex || 0
);
const [screenIndex, setScreenIndex] = useState<number>(0);

useEffect(() => {
const playerData = getState().player.playerData;
const checkTutorialCompletion = () => {
const idx = getState().player.playerData.tutorialIndex;
const currentTutorialStep = tutorialSteps[idx];
if (currentTutorialStep) {
const requiredValid = hasRequiredFacilities(
currentTutorialStep,
playerData
);
if (requiredValid && idx < tutorialSteps.length - 1) {
setScreenIndex(0);
getState().player.setPlayerData({
...playerData,
tutorialIndex: currentStep + 1,
});
setCurrentStep(currentStep + 1);
}
}
};
checkTutorialCompletion();
document.addEventListener("buildFacility", checkTutorialCompletion);

return () => {
document.removeEventListener("buildFacility", checkTutorialCompletion);
};
}, [currentStep]);

return (
<>
{screenIndex < tutorialSteps[currentStep]?.screens?.length && (
<TutorialModal
step={tutorialSteps[currentStep]}
screenIndex={screenIndex}
onNext={() => {
setScreenIndex(screenIndex + 1);
}}
/>
)}
</>
);
};

export { Tutorial };
13 changes: 8 additions & 5 deletions packages/client/src/game/data/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export type DataType = {
blurb: string;
description: string;
image: string;
produces: [ResourceType, number, number][];
produces?: [ResourceType, number][];
generates?: [ResourceType, number, number][];
variants: ModelDataType[];
tags: EntityTag[];
};
Expand Down Expand Up @@ -43,7 +44,7 @@ const EntityData = {
["LAPU", 400],
["crystal", 1],
],
produces: [["gravity", 10, 1]],
produces: [["gravity", 10]],
variants: ModelData.well,
tags: ["groundLevel", "hasWires", "producesGravity", "startingItem"],
},
Expand All @@ -58,7 +59,8 @@ const EntityData = {
["gravity", 2],
["LAPU", 300],
],
produces: [["power", 6, 1]],
produces: [["power", 6]],
// generates: [["power", 1, 5000]],
variants: ModelData.engine,
tags: ["hasWires"],
},
Expand All @@ -74,7 +76,8 @@ const EntityData = {
["power", 2],
["LAPU", 75],
],
produces: [["population", 5, 1]],
produces: [["population", 2]],
generates: [["LAPU", 1, 5000]],
variants: ModelData.residence,
tags: ["hasPlants"],
},
Expand Down Expand Up @@ -117,7 +120,7 @@ const EntityData = {
"A floating crystal. It is a crystal that floats. It is also a floating crystal.",
image: "crystal.webp",
resourceType: "crystal",
produces: [["gravity", 25, 1]],
produces: [["crystal", 25]],
variants: [...ModelData.rock, ...ModelData.crystal],
tags: [],
},
Expand Down
Loading

0 comments on commit e483fbc

Please sign in to comment.