From 2414ae118913f43a36b087d52f5bed88feaac1f9 Mon Sep 17 00:00:00 2001 From: reidlab Date: Sun, 20 Aug 2023 23:48:32 -0700 Subject: [PATCH] improve types, internal ui overhaul --- readme.md | 4 +- src/ReplicatedStorage/ecs/state.ts | 12 ++--- .../ecs/systems/client/sprint.ts | 2 + .../StarterPlayerScripts/main.client.ts | 6 ++- .../StarterPlayerScripts/ui/config/config.tsx | 1 + .../StarterPlayerScripts/ui/config/item.tsx | 9 +++- .../StarterPlayerScripts/ui/hotbar/hotbar.tsx | 53 ++++++++++++++----- .../StarterPlayerScripts/ui/hotbar/slot.tsx | 4 +- 8 files changed, 66 insertions(+), 25 deletions(-) diff --git a/readme.md b/readme.md index 189d86a..28b9431 100644 --- a/readme.md +++ b/readme.md @@ -16,8 +16,8 @@ I should put this in the game sometime, but the option to open the configuration * I decided to omit the "TS" folder from [`./default.project.json:40`](./default.project.json) due to the script override not working in Health.server.ts in StarterCharacterScripts. # Todo -* Better null checking for the clientState.character (can cause errors atm) -* Swap to pretty-roact-hooks +* Investigate why our hotbar only loads _sometimes_ +* Maybe swap to our input system in the UI. * Custom player list * Custom chat * Add guns diff --git a/src/ReplicatedStorage/ecs/state.ts b/src/ReplicatedStorage/ecs/state.ts index f1a4d21..40d8d22 100644 --- a/src/ReplicatedStorage/ecs/state.ts +++ b/src/ReplicatedStorage/ecs/state.ts @@ -10,29 +10,29 @@ import { InputKind } from "ReplicatedStorage/inputKind" export class ClientState { constructor( player: Player, - character: CharacterRigR6, debugEnabled: boolean, isRunning: boolean, - backpack: Backpack, - // lastProcessedCommand: Inputkind, + backpack: Instance, + // character?: CharacterRigR6, + // lastProcessedCommand?: Inputkind, logger: Logger ) { - this.character = character this.player = player this.debugEnabled = debugEnabled this.isRunning = isRunning this.backpack = backpack + // this.character = character // this.lastProcessedCommand = lastProcessedCommand this.logger = logger } player: Player - character: CharacterRigR6 debugEnabled: boolean isRunning: boolean - backpack: Backpack + backpack: Instance + character?: CharacterRigR6 lastProcessedCommand?: InputKind logger: Logger diff --git a/src/ReplicatedStorage/ecs/systems/client/sprint.ts b/src/ReplicatedStorage/ecs/systems/client/sprint.ts index 8df1a1a..8682028 100644 --- a/src/ReplicatedStorage/ecs/systems/client/sprint.ts +++ b/src/ReplicatedStorage/ecs/systems/client/sprint.ts @@ -3,6 +3,8 @@ import { match } from "@rbxts/variant" import { ClientState } from "ReplicatedStorage/ecs/state" function sprint(_: World, client: ClientState): void { + if (client.character === undefined) return + if (client.lastProcessedCommand !== undefined) { match(client.lastProcessedCommand, { KeyDown: ({ key }) => { diff --git a/src/StarterPlayer/StarterPlayerScripts/main.client.ts b/src/StarterPlayer/StarterPlayerScripts/main.client.ts index 31125c1..b0cd365 100644 --- a/src/StarterPlayer/StarterPlayerScripts/main.client.ts +++ b/src/StarterPlayer/StarterPlayerScripts/main.client.ts @@ -15,14 +15,16 @@ const clientLogger = Logger.configure() const clientState = new ClientState( Players.LocalPlayer, - (Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6, false, false, - Players.LocalPlayer.WaitForChild("Backpack") as Backpack, + Players.LocalPlayer.WaitForChild("Backpack"), clientLogger ) +clientState.character = (Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6 +clientState.backpack = Players.LocalPlayer.WaitForChild("Backpack") + const worldAndClientState = start(HOST, clientState) showGUI(worldAndClientState[0], clientState) setEnvironment(HOST) \ No newline at end of file diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx index ce5fc22..c8f1776 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -24,6 +24,7 @@ function config(props: ConfigProps): Roact.Element { const [configPosY, setConfigGoal] = useMotor(1.5) + // TODO: maybe opt this into our system for inputs? useEffect(() => { const guid = HttpService.GenerateGUID(false) ContextActionService.BindAction( diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx index 9ec7ae4..43a72fe 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx @@ -34,11 +34,18 @@ function item(props: itemProps): Roact.Element { + toggleConfig(action) diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx index a27cda5..9b170d6 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx @@ -3,12 +3,35 @@ import Slot from "./slot" import { useWorldContext } from "../contexts/worldContext" import Canvas from "ReplicatedStorage/ui/components/canvas" import { StarterGui } from "@rbxts/services" +import { useEffect, useMemo, useState } from "@rbxts/roact-hooked" +import { ClientState } from "ReplicatedStorage/ecs/state" interface HotbarProps extends Roact.JsxInstanceProperties { Event?: Roact.JsxInstanceEvents Change?: Roact.JsxInstanceChangeEvents } +function useBackpackContents(clientState: ClientState): Instance[] { + const [contents, setContents] = useState(clientState.backpack.GetChildren()) + + useEffect(() => { + const addedHandle = clientState.backpack.ChildAdded.Connect(() => { + setContents(clientState.backpack.GetChildren()) + }) + const removingHandle = clientState.backpack.ChildRemoved.Connect((removed) => { + // the tool is removed from the bp when equipped, can cause weird behavior + if (removed.Parent === clientState.character) { return } + setContents(clientState.backpack.GetChildren()) + }) + return () => { + addedHandle.Disconnect() + removingHandle.Disconnect() + } + }, []) + + return contents +} + StarterGui.SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false) function hotbar(props: HotbarProps): Roact.Element { @@ -16,6 +39,13 @@ function hotbar(props: HotbarProps): Roact.Element { const { clientState } = useWorldContext() + const backpackContents = useBackpackContents(clientState) + + const sortedBackpackContents = useMemo(() => { + return backpackContents + .sort((a, b) => a.Name.lower() < b.Name.lower()) + }, [backpackContents]) + const keycodes: Enum.KeyCode[] = [ Enum.KeyCode.One, Enum.KeyCode.Two, @@ -28,18 +58,6 @@ function hotbar(props: HotbarProps): Roact.Element { Enum.KeyCode.Nine ] - const items: Roact.Element[] = [] - clientState.backpack.GetChildren().forEach((tool, i) => { - items.push( - - ) - }) - return ( - {...items} + { + sortedBackpackContents.map((tool, i) => ( + + )) + } ) } diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx index 261ba8e..8f16c56 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx @@ -27,11 +27,12 @@ function slot(props: SlotProps): Roact.Element { delete spreadableProps.keycode delete spreadableProps.tool - const [slotRatio, setSlotGoal] = useMotor(0) + const [slotRatio, setSlotGoal] = useMotor(6) const { clientState } = useWorldContext() const handleActivated = (): void => { + if (clientState.character === undefined) return if (tool.Parent !== clientState.character) { clientState.character.Humanoid.EquipTool(tool) setSlotGoal(SLOT_ACTIVE) @@ -57,6 +58,7 @@ function slot(props: SlotProps): Roact.Element { setSlotGoal(SLOT_DEFAULT) }) }) + return (