diff --git a/package.json b/package.json index f637509..707cbd5 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,11 @@ "@rbxts/make": "^1.0.6", "@rbxts/matter": "^0.6.2-ts.6", "@rbxts/plasma": "^0.4.1-ts.1", + "@rbxts/pretty-roact-hooks": "^3.1.1", "@rbxts/reflex": "^4.2.0", "@rbxts/rewire": "^0.3.0", "@rbxts/roact": "^1.4.4-ts.0", "@rbxts/roact-hooked": "^2.6.0", - "@rbxts/roact-hooked-plus": "^1.8.1", "@rbxts/roact-reflex": "^2.1.0", "@rbxts/services": "^1.5.1", "@rbxts/testez": "^0.4.2-ts.0", diff --git a/readme.md b/readme.md index 4bccada..28b9431 100644 --- a/readme.md +++ b/readme.md @@ -16,7 +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) +* 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/ReplicatedStorage/ui/components/canvas.tsx b/src/ReplicatedStorage/ui/components/canvas.tsx new file mode 100644 index 0000000..47f4151 --- /dev/null +++ b/src/ReplicatedStorage/ui/components/canvas.tsx @@ -0,0 +1,59 @@ +import Roact from "@rbxts/roact" +import { BindingOrValue, mapBinding } from "ReplicatedStorage/utils/bindingUtil" + +interface canvasProps extends Roact.JsxInstanceProperties { + size?: BindingOrValue + position?: BindingOrValue + anchor?: Vector2 + padding?: { + top?: BindingOrValue + right?: BindingOrValue + bottom?: BindingOrValue + left?: BindingOrValue + } + clipsDescendants?: boolean + zIndex?: number + [Roact.Children]?: Roact.Children + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function canvas(props: canvasProps): Roact.Element { + const { size, position, anchor, padding, clipsDescendants, zIndex } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.size + delete spreadableProps.position + delete spreadableProps.anchor + delete spreadableProps.padding + delete spreadableProps.clipsDescendants + delete spreadableProps.zIndex + delete spreadableProps[Roact.Children] + + return ( + + {padding !== undefined && ( + new UDim(0, px))} + PaddingRight={mapBinding(padding.right, (px) => new UDim(0, px))} + PaddingBottom={mapBinding(padding.bottom, (px) => new UDim(0, px))} + PaddingLeft={mapBinding(padding.left, (px) => new UDim(0, px))} + /> + )} + + {props[Roact.Children]} + + ) +} + +export default canvas \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/fill.tsx b/src/ReplicatedStorage/ui/components/fill.tsx new file mode 100644 index 0000000..4e2e274 --- /dev/null +++ b/src/ReplicatedStorage/ui/components/fill.tsx @@ -0,0 +1,42 @@ +import Roact from "@rbxts/roact" +import { BindingOrValue, mapBinding } from "ReplicatedStorage/utils/bindingUtil" + +interface fillProps extends Roact.JsxInstanceProperties { + color?: BindingOrValue + transparency?: BindingOrValue + radius?: BindingOrValue + [Roact.Children]?: Roact.Children + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function fill(props: fillProps): Roact.Element { + const { color, transparency, radius } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.color + delete spreadableProps.transparency + delete spreadableProps.radius + delete spreadableProps[Roact.Children] + + return ( + + {radius !== undefined && ( + (r === "circular" ? new UDim(1, 0) : new UDim(0, r)))} + /> + )} + + {props[Roact.Children]} + + ) +} + +export default fill \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/padding.tsx b/src/ReplicatedStorage/ui/components/padding.tsx deleted file mode 100644 index 402d2cf..0000000 --- a/src/ReplicatedStorage/ui/components/padding.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import Roact from "@rbxts/roact" - -interface paddingProps extends Roact.JsxInstanceProperties { - padding?: UDim | Roact.Binding - paddingX?: UDim | Roact.Binding - paddingY?: UDim | Roact.Binding - - Event?: Roact.JsxInstanceEvents - Change?: Roact.JsxInstanceChangeEvents -} - -function padding(props: paddingProps): Roact.Element { - const { padding, paddingX, paddingY } = props - - const spreadableProps = { ...props } as Partial - delete spreadableProps.padding - delete spreadableProps.paddingX - delete spreadableProps.paddingY - - return ( - - ) -} - -export default padding \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/surface.tsx b/src/ReplicatedStorage/ui/components/surface.tsx new file mode 100644 index 0000000..e5c2c33 --- /dev/null +++ b/src/ReplicatedStorage/ui/components/surface.tsx @@ -0,0 +1,65 @@ +import Roact from "@rbxts/roact" +import Canvas from "./canvas" +import Acrylic from "./acrylic" +import Fill from "./fill" +import { BindingOrValue } from "ReplicatedStorage/utils/bindingUtil" + +interface surfaceProps extends Roact.JsxInstanceProperties { + size: BindingOrValue + position: BindingOrValue + ratio?: BindingOrValue + color?: BindingOrValue + anchor?: Vector2 + [Roact.Children]?: Roact.Children + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function surface(props: surfaceProps): Roact.Element { + const { size, position, ratio, color, anchor } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.size + delete spreadableProps.position + delete spreadableProps.ratio + delete spreadableProps.color + delete spreadableProps.anchor + delete spreadableProps[Roact.Children] + + return ( + + <> + { + ratio !== undefined && + } + + + + + + + + {props[Roact.Children]} + + + ) +} + +export default surface \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/components/text.tsx b/src/ReplicatedStorage/ui/components/text.tsx new file mode 100644 index 0000000..8403910 --- /dev/null +++ b/src/ReplicatedStorage/ui/components/text.tsx @@ -0,0 +1,40 @@ +import Roact from "@rbxts/roact" + +interface textProps extends Roact.JsxInstanceProperties { + bold?: boolean + paddingX?: UDim + paddingY?: UDim + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function text(props: textProps): Roact.Element { + const { bold, paddingX, paddingY, Text, TextXAlignment } = props + + const spreadableProps = { ...props } as Partial + delete spreadableProps.bold + delete spreadableProps.paddingX + delete spreadableProps.paddingY + + return ( + + + + ) +} + +export default text \ No newline at end of file diff --git a/src/ReplicatedStorage/ui/store/producer/config.ts b/src/ReplicatedStorage/ui/store/producer/config.ts index de831aa..d0f997f 100644 --- a/src/ReplicatedStorage/ui/store/producer/config.ts +++ b/src/ReplicatedStorage/ui/store/producer/config.ts @@ -5,12 +5,12 @@ export interface ConfigState { } const initialState: ConfigState = { - acrylicBlur: false + acrylicBlur: true } export const configProducer = createProducer(initialState, { - toggleAcrylic: (state) => ({ + toggleConfig: (state, action: keyof ConfigState) => ({ ...state, - acrylicBlur: !state.acrylicBlur + [action]: !state[action] }) }) \ No newline at end of file diff --git a/src/ReplicatedStorage/utils/bindingUtil.ts b/src/ReplicatedStorage/utils/bindingUtil.ts new file mode 100644 index 0000000..36a479f --- /dev/null +++ b/src/ReplicatedStorage/utils/bindingUtil.ts @@ -0,0 +1,15 @@ +import Roact from "@rbxts/roact" + +export type BindingOrValue = T | Roact.Binding + +export function isBinding(binding: unknown): binding is Roact.Binding { + return typeIs(binding, "table") && "getValue" in binding +} + +export function mapBinding(value: BindingOrValue, transform: (value: T) => U): Roact.Binding { + return isBinding(value) ? value.map(transform) : Roact.createBinding(transform(value))[0] +} + +export function asBinding(value: BindingOrValue): Roact.Binding { + return isBinding(value) ? value : Roact.createBinding(value)[0] +} \ No newline at end of file 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 92a05dc..c8f1776 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/config.tsx @@ -1,11 +1,10 @@ import Roact from "@rbxts/roact" -import Padding from "ReplicatedStorage/ui/components/padding" -import Acrylic from "ReplicatedStorage/ui/components/acrylic" import { ContextActionService, HttpService } from "@rbxts/services" import { Spring } from "@rbxts/flipper" -import { useGroupMotor } from "@rbxts/roact-hooked-plus" import { useEffect } from "@rbxts/roact-hooked" -import { useRootProducer } from "ReplicatedStorage/ui/store/hooks/useUiProducer" +import Item from "./item" +import Surface from "ReplicatedStorage/ui/components/surface" +import { useMotor } from "@rbxts/pretty-roact-hooks" interface ConfigProps extends Roact.JsxInstanceProperties { shown: boolean @@ -14,20 +13,18 @@ interface ConfigProps extends Roact.JsxInstanceProperties { Change?: Roact.JsxInstanceChangeEvents } -const CONFIG_DEFAULT = [new Spring(1.5, { frequency: 6 })] -const CONFIG_ACTIVE = [new Spring(.5, { frequency: 6 })] +const CONFIG_DEFAULT = new Spring(1.5, { frequency: 6 }) +const CONFIG_ACTIVE = new Spring(.5, { frequency: 6 }) function config(props: ConfigProps): Roact.Element { - const { toggleAcrylic } = useRootProducer() - let { shown } = props const spreadableProps = { ...props } as Partial delete spreadableProps.shown - const [slotPosYMap, setPosYGoal] = useGroupMotor([1.5, 6]) - const slotPosY = slotPosYMap.map((t) => t[0]) + const [configPosY, setConfigGoal] = useMotor(1.5) + // TODO: maybe opt this into our system for inputs? useEffect(() => { const guid = HttpService.GenerateGUID(false) ContextActionService.BindAction( @@ -36,9 +33,9 @@ function config(props: ConfigProps): Roact.Element { if (Enum.UserInputState.Begin === userInputState) { shown = !shown if (shown) { - setPosYGoal(CONFIG_ACTIVE) + setConfigGoal(CONFIG_ACTIVE) } else { - setPosYGoal(CONFIG_DEFAULT) + setConfigGoal(CONFIG_DEFAULT) } } }, @@ -48,65 +45,34 @@ function config(props: ConfigProps): Roact.Element { }) return ( - { + anchor={new Vector2(.5, .5)} + position={ + configPosY.map((posY) => { return new UDim2(.5, 0, posY, 0) }) } - BackgroundTransparency={1} - Size={new UDim2(.4, 0, .7, 0)} - Key={"Config"} + size={new UDim2(.4, 0, .7, 0)} + Key={"config"} > - - - - - - {toggleAcrylic()} - }} - > - - - - - + + + ) } diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx new file mode 100644 index 0000000..43a72fe --- /dev/null +++ b/src/StarterPlayer/StarterPlayerScripts/ui/config/item.tsx @@ -0,0 +1,61 @@ +import Roact from "@rbxts/roact" +import Fill from "ReplicatedStorage/ui/components/fill" +import Text from "ReplicatedStorage/ui/components/text" +import Canvas from "ReplicatedStorage/ui/components/canvas" +import { useRootProducer, useRootSelector } from "ReplicatedStorage/ui/store/hooks/useUiProducer" +import { ConfigState } from "ReplicatedStorage/ui/store/producer/config" + +interface itemProps extends Roact.JsxInstanceProperties { + size: UDim2 + position: UDim2 + text: string + action: keyof ConfigState + + Event?: Roact.JsxInstanceEvents + Change?: Roact.JsxInstanceChangeEvents +} + +function item(props: itemProps): Roact.Element { + const { size, position, text, action } = props + + const { toggleConfig } = useRootProducer() + + const active = useRootSelector((state) => state.configProducer[action]) + + const spreadableProps = { ...props } as Partial + delete spreadableProps.size + delete spreadableProps.position + delete spreadableProps.text + delete spreadableProps.action + + return ( + + + + + + toggleConfig(action) + }} + Size={new UDim2(1, 0, 1, 0)} + Transparency={1} + Text={""} + /> + + ) +} + +export default item \ No newline at end of file diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx index b196570..9b170d6 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx @@ -1,14 +1,37 @@ import Roact from "@rbxts/roact" import Slot from "./slot" import { useWorldContext } from "../contexts/worldContext" -import Padding from "ReplicatedStorage/ui/components/padding" +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,36 +58,27 @@ 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 203d9c9..8f16c56 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx @@ -2,10 +2,10 @@ import Roact from "@rbxts/roact" import { useEffect } from "@rbxts/roact-hooked" import { useWorldContext } from "../contexts/worldContext" import { ContextActionService, HttpService } from "@rbxts/services" -import Padding from "ReplicatedStorage/ui/components/padding" -import Acrylic from "ReplicatedStorage/ui/components/acrylic" +import Text from "ReplicatedStorage/ui/components/text" +import Surface from "ReplicatedStorage/ui/components/surface" import { Spring } from "@rbxts/flipper" -import { useGroupMotor } from "@rbxts/roact-hooked-plus" +import { useMotor } from "@rbxts/pretty-roact-hooks" interface SlotProps extends Roact.JsxInstanceProperties { index: number @@ -16,8 +16,8 @@ interface SlotProps extends Roact.JsxInstanceProperties { Change?: Roact.JsxInstanceChangeEvents } -const SLOT_DEFAULT = [new Spring(.7, { frequency: 6 }), new Spring(6, { frequency: 6 })] -const SLOT_ACTIVE = [new Spring(.5, { frequency: 6 }), new Spring(5, { frequency: 6 })] +const SLOT_DEFAULT = new Spring(6, { frequency: 6 }) +const SLOT_ACTIVE = new Spring(5, { frequency: 6 }) function slot(props: SlotProps): Roact.Element { const { index, keycode, tool } = props @@ -27,13 +27,12 @@ function slot(props: SlotProps): Roact.Element { delete spreadableProps.keycode delete spreadableProps.tool - const [slotBgTransparencyAndSlotRatio, setSlotGoal] = useGroupMotor([.7, 6]) - const slotBgTransparency = slotBgTransparencyAndSlotRatio.map((t) => t[0]) - const slotRatio = slotBgTransparencyAndSlotRatio.map((t) => t[1]) + 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) @@ -59,47 +58,29 @@ function slot(props: SlotProps): Roact.Element { setSlotGoal(SLOT_DEFAULT) }) }) + return ( - - - - - - - - - - + ) } diff --git a/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx b/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx index 755ea44..f508bb7 100644 --- a/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx +++ b/src/StarterPlayer/StarterPlayerScripts/ui/main.tsx @@ -1,7 +1,8 @@ import Roact from "@rbxts/roact" +import { withHookDetection } from "@rbxts/roact-hooked" import Hotbar from "./hotbar/hotbar" import Config from "./config/config" -import { withHookDetection } from "@rbxts/roact-hooked" +import Canvas from "ReplicatedStorage/ui/components/canvas" interface MainProps extends Roact.JsxInstanceEvents { Event?: Roact.JsxInstanceEvents @@ -14,18 +15,22 @@ export default function main(props: MainProps): Roact.Element { withHookDetection(Roact) return ( - - - + + + + + ) } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 73f5dcd..5010b83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -131,6 +131,14 @@ resolved "https://registry.yarnpkg.com/@rbxts/plasma/-/plasma-0.4.1-ts.1.tgz#3d8db367c3220e6b6953cdddbf8af9f087165392" integrity sha512-RhLkC3GQW0KeyqjFwvOUbHhsIJOHmXg+BhcKLp0IgUDVgC5GktShi3zmW6GQ319yod+RlUDG1XHjOnP3Omo4bA== +"@rbxts/pretty-roact-hooks@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@rbxts/pretty-roact-hooks/-/pretty-roact-hooks-3.1.1.tgz#b2729163bfd2c89e1efb91c544d7ddb798054fe0" + integrity sha512-eve1L7GWKZVo6ZLgcmk6c95SDvhTRIjWwR8notAz7g+CQ/jdtOoX+5fVHOQLMYE6HbQ79Bth+LO13WOM4T3WKg== + dependencies: + "@rbxts/services" "^1.5.1" + "@rbxts/set-timeout" "^1.1.2" + "@rbxts/reflex@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@rbxts/reflex/-/reflex-4.2.0.tgz#10d064de5e293f1aea429846d4d8739821cb575a" @@ -141,14 +149,6 @@ resolved "https://registry.yarnpkg.com/@rbxts/rewire/-/rewire-0.3.0.tgz#47f0cd651fe405cf418936799d2a4dac6b1bb7ce" integrity sha512-wChhGZ3kEkEsMK9ZuwKpwRsC7OGVZlvxrYMR3beFgCIPXE58JKLziBLkDACmd709XCCEmsMAqv9HMCMhSTD08Q== -"@rbxts/roact-hooked-plus@^1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@rbxts/roact-hooked-plus/-/roact-hooked-plus-1.8.1.tgz#e0fa32b74c0f958430ae62f249f1b5b52ce27f3b" - integrity sha512-ipJf6pZcQZlx/0hyisQz2eoRECg38knUgjkEvx2dvAHfs0+IDgera7mcwv6zTMACqalaXu00inc4E5dpOrs54A== - dependencies: - "@rbxts/flipper" "^2.0.1" - "@rbxts/services" "^1.2.0" - "@rbxts/roact-hooked@^2.6.0": version "2.6.0" resolved "https://registry.yarnpkg.com/@rbxts/roact-hooked/-/roact-hooked-2.6.0.tgz#cbe3e244e1d52d879083c62b6662c4d082c6d30b" @@ -164,11 +164,18 @@ resolved "https://registry.yarnpkg.com/@rbxts/roact/-/roact-1.4.4-ts.0.tgz#7f297bec03dbea9473bd2d82b148d3ae6e4f6c00" integrity sha512-gn9mBoGG/Clzgv2kyOvLNVd9dh5t6z+jukC3ITv2HnfPqvf/sMbz/VMaBoiB7t5umuiIe0LjW0ctZrkrS+uTOA== -"@rbxts/services@^1.2.0", "@rbxts/services@^1.5.1": +"@rbxts/services@^1.5.1": version "1.5.1" resolved "https://registry.yarnpkg.com/@rbxts/services/-/services-1.5.1.tgz#4536a87932f28797507ed591f0061277c52ea77f" integrity sha512-SRtfIjga0K4YYSXRpK+eH3kcTq7ZXo9OHOt0jszaOOoEOIJloMGlyuRPqesPHyhveh2AMXAZr3TYbRMSD+u+kQ== +"@rbxts/set-timeout@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@rbxts/set-timeout/-/set-timeout-1.1.2.tgz#2adc9d4b5dcb54ca4332eb7ec8d19793932dbd40" + integrity sha512-P/A0IiH9wuZdSJYr4Us0MDFm61nvIFR0acfKFHLkcOsgvIgELC90Up9ugiSsaMEHRIcIcO5UjE39LuS3xTzQHw== + dependencies: + "@rbxts/services" "^1.5.1" + "@rbxts/testez@^0.4.2-ts.0": version "0.4.2-ts.0" resolved "https://registry.yarnpkg.com/@rbxts/testez/-/testez-0.4.2-ts.0.tgz#4475183d317182ac7099bffee6492ffcb7bcaf0b"