add custom hotbar
This commit is contained in:
parent
72029047a5
commit
8232eacff2
12 changed files with 304 additions and 8 deletions
|
@ -26,6 +26,7 @@
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
"@typescript-eslint/no-empty-function": "error",
|
"@typescript-eslint/no-empty-function": "error",
|
||||||
"@typescript-eslint/no-empty-interface": "error",
|
"@typescript-eslint/no-empty-interface": "error",
|
||||||
|
"@typescript-eslint/no-empty-pattern": "none",
|
||||||
"@typescript-eslint/no-namespace": "error",
|
"@typescript-eslint/no-namespace": "error",
|
||||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
"@typescript-eslint/no-unused-vars": [
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
"@rbxts/matter": "^0.6.2-ts.6",
|
"@rbxts/matter": "^0.6.2-ts.6",
|
||||||
"@rbxts/plasma": "^0.4.1-ts.1",
|
"@rbxts/plasma": "^0.4.1-ts.1",
|
||||||
"@rbxts/rewire": "^0.3.0",
|
"@rbxts/rewire": "^0.3.0",
|
||||||
|
"@rbxts/roact": "^1.4.4-ts.0",
|
||||||
|
"@rbxts/roact-hooks": "^0.4.1-ts.3",
|
||||||
"@rbxts/services": "^1.5.1",
|
"@rbxts/services": "^1.5.1",
|
||||||
"@rbxts/testez": "^0.4.2-ts.0",
|
"@rbxts/testez": "^0.4.2-ts.0",
|
||||||
"@rbxts/variant": "^1.0.2",
|
"@rbxts/variant": "^1.0.2",
|
||||||
|
|
|
@ -13,6 +13,7 @@ export class clientState {
|
||||||
character: CharacterRigR6,
|
character: CharacterRigR6,
|
||||||
debugEnabled: boolean,
|
debugEnabled: boolean,
|
||||||
isRunning: boolean,
|
isRunning: boolean,
|
||||||
|
backpack: Backpack,
|
||||||
// lastProcessedCommand: Inputkind,
|
// lastProcessedCommand: Inputkind,
|
||||||
|
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
@ -21,6 +22,7 @@ export class clientState {
|
||||||
this.player = player
|
this.player = player
|
||||||
this.debugEnabled = debugEnabled
|
this.debugEnabled = debugEnabled
|
||||||
this.isRunning = isRunning
|
this.isRunning = isRunning
|
||||||
|
this.backpack = backpack
|
||||||
// this.lastProcessedCommand = lastProcessedCommand
|
// this.lastProcessedCommand = lastProcessedCommand
|
||||||
|
|
||||||
this.logger = logger
|
this.logger = logger
|
||||||
|
@ -30,6 +32,7 @@ export class clientState {
|
||||||
character: CharacterRigR6
|
character: CharacterRigR6
|
||||||
debugEnabled: boolean
|
debugEnabled: boolean
|
||||||
isRunning: boolean
|
isRunning: boolean
|
||||||
|
backpack: Backpack
|
||||||
lastProcessedCommand?: InputKind
|
lastProcessedCommand?: InputKind
|
||||||
|
|
||||||
logger: Logger
|
logger: Logger
|
||||||
|
|
33
src/ReplicatedStorage/ui/padding.tsx
Normal file
33
src/ReplicatedStorage/ui/padding.tsx
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import Hooks from "@rbxts/roact-hooks"
|
||||||
|
import Roact from "@rbxts/roact"
|
||||||
|
|
||||||
|
interface PaddingProps extends Roact.JsxInstanceProperties<UIPadding> {
|
||||||
|
Padding?: UDim | Roact.Binding<UDim>
|
||||||
|
PaddingX?: UDim | Roact.Binding<UDim>
|
||||||
|
PaddingY?: UDim | Roact.Binding<UDim>
|
||||||
|
|
||||||
|
Event?: Roact.JsxInstanceEvents<UIPadding>
|
||||||
|
Change?: Roact.JsxInstanceChangeEvents<UIPadding>
|
||||||
|
}
|
||||||
|
|
||||||
|
const padding: Hooks.FC<PaddingProps> = (props, hooks) => {
|
||||||
|
const {} = hooks
|
||||||
|
const { Padding, PaddingX, PaddingY } = props
|
||||||
|
|
||||||
|
const spreadableProps = { ...props } as Partial<PaddingProps>
|
||||||
|
delete spreadableProps.Padding
|
||||||
|
delete spreadableProps.PaddingX
|
||||||
|
delete spreadableProps.PaddingY
|
||||||
|
|
||||||
|
return (
|
||||||
|
<uipadding
|
||||||
|
{...spreadableProps}
|
||||||
|
PaddingBottom={PaddingY ?? Padding}
|
||||||
|
PaddingTop={PaddingY ?? Padding}
|
||||||
|
PaddingLeft={PaddingX || Padding}
|
||||||
|
PaddingRight={PaddingX || Padding}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Hooks(Roact)(padding)
|
|
@ -1,10 +1,11 @@
|
||||||
import { CharacterRigR6 } from "@rbxts/character-promise"
|
import { CharacterRigR6 } from "@rbxts/character-promise"
|
||||||
import Log, { Logger } from "@rbxts/log"
|
import Log, { Logger } from "@rbxts/log"
|
||||||
import { Players } from "@rbxts/services"
|
import { Players, StarterGui } from "@rbxts/services"
|
||||||
import { start } from "ReplicatedStorage/ecs"
|
import { start } from "ReplicatedStorage/ecs"
|
||||||
import { clientState } from "ReplicatedStorage/ecs/state"
|
import { clientState } from "ReplicatedStorage/ecs/state"
|
||||||
import { Host } from "ReplicatedStorage/hosts"
|
import { Host } from "ReplicatedStorage/hosts"
|
||||||
import { setEnvironment } from "ReplicatedStorage/idAttribute"
|
import { setEnvironment } from "ReplicatedStorage/idAttribute"
|
||||||
|
import showGUI from "./showGUI"
|
||||||
|
|
||||||
const HOST = Host.Client
|
const HOST = Host.Client
|
||||||
|
|
||||||
|
@ -17,9 +18,14 @@ const ClientState = new clientState(
|
||||||
(Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6,
|
(Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
Players.LocalPlayer.WaitForChild("Backpack") as Backpack,
|
||||||
|
|
||||||
clientLogger
|
clientLogger
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// no fuck off
|
||||||
|
StarterGui.SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
|
||||||
|
|
||||||
|
const worldAndClientState = start(HOST, ClientState)
|
||||||
|
showGUI(worldAndClientState[0], ClientState)
|
||||||
setEnvironment(HOST)
|
setEnvironment(HOST)
|
||||||
start(HOST, ClientState)
|
|
17
src/StarterPlayer/StarterPlayerScripts/showGUI.tsx
Normal file
17
src/StarterPlayer/StarterPlayerScripts/showGUI.tsx
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { World } from "@rbxts/matter"
|
||||||
|
import { clientState } from "ReplicatedStorage/ecs/state"
|
||||||
|
import WorldProvider from "./ui/contexts/worldContext"
|
||||||
|
import Roact from "@rbxts/roact"
|
||||||
|
import Main from "./ui/main"
|
||||||
|
|
||||||
|
const showGUI = (world: World, state: clientState): void => {
|
||||||
|
const playerGui = state.player.WaitForChild("PlayerGui") as PlayerGui
|
||||||
|
const tree = (
|
||||||
|
<WorldProvider clientState={state} world={world}>
|
||||||
|
<Main/>
|
||||||
|
</WorldProvider>
|
||||||
|
)
|
||||||
|
Roact.mount(tree, playerGui, "gooplerGUI")
|
||||||
|
}
|
||||||
|
|
||||||
|
export default showGUI
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { World } from "@rbxts/matter"
|
||||||
|
import Roact, { createContext } from "@rbxts/roact"
|
||||||
|
import Hooks, { CoreHooks } from "@rbxts/roact-hooks"
|
||||||
|
import { clientState } from "ReplicatedStorage/ecs/state"
|
||||||
|
|
||||||
|
interface WorldContextValue {
|
||||||
|
world: World
|
||||||
|
clientState: clientState
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
world: World
|
||||||
|
clientState: clientState
|
||||||
|
}
|
||||||
|
|
||||||
|
const WorldProviderWithoutHooks: Hooks.FC<Props> = (props) => {
|
||||||
|
const { world, clientState } = props
|
||||||
|
|
||||||
|
return <WorldContext.Provider value={{ world, clientState }}>{props[Roact.Children]}</WorldContext.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
const WorldProvider = new Hooks(Roact)(WorldProviderWithoutHooks)
|
||||||
|
|
||||||
|
export default WorldProvider
|
||||||
|
|
||||||
|
const WorldContext = createContext<WorldContextValue | undefined>(undefined)
|
||||||
|
|
||||||
|
export const useWorldContext = ({ useContext }: CoreHooks): WorldContextValue => {
|
||||||
|
const context = useContext(WorldContext)
|
||||||
|
if (!context) {
|
||||||
|
error("useContext must be called within a Provider")
|
||||||
|
}
|
||||||
|
return context
|
||||||
|
}
|
65
src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx
Normal file
65
src/StarterPlayer/StarterPlayerScripts/ui/hotbar/hotbar.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import Roact from "@rbxts/roact"
|
||||||
|
import Hooks from "@rbxts/roact-hooks"
|
||||||
|
import Slot from "./slot"
|
||||||
|
import { useWorldContext } from "../contexts/worldContext"
|
||||||
|
import Padding from "ReplicatedStorage/ui/padding"
|
||||||
|
|
||||||
|
interface hotbarProps extends Roact.JsxInstanceProperties<Frame> {
|
||||||
|
Event?: Roact.JsxInstanceEvents<Frame>
|
||||||
|
Change?: Roact.JsxInstanceChangeEvents<Frame>
|
||||||
|
}
|
||||||
|
|
||||||
|
const hotbar: Hooks.FC<hotbarProps> = (props, hooks) => {
|
||||||
|
const {} = hooks
|
||||||
|
const {} = props
|
||||||
|
|
||||||
|
const spreadableProps = { ...props } as Partial<hotbarProps>
|
||||||
|
|
||||||
|
const { world, clientState } = useWorldContext(hooks)
|
||||||
|
|
||||||
|
const keycodes: Enum.KeyCode[] = [
|
||||||
|
Enum.KeyCode.One,
|
||||||
|
Enum.KeyCode.Two,
|
||||||
|
Enum.KeyCode.Three,
|
||||||
|
Enum.KeyCode.Four,
|
||||||
|
Enum.KeyCode.Five,
|
||||||
|
Enum.KeyCode.Six,
|
||||||
|
Enum.KeyCode.Seven,
|
||||||
|
Enum.KeyCode.Eight,
|
||||||
|
Enum.KeyCode.Nine
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<frame
|
||||||
|
{...spreadableProps}
|
||||||
|
AutomaticSize={Enum.AutomaticSize.X}
|
||||||
|
AnchorPoint={new Vector2(0.5, 1)}
|
||||||
|
BackgroundTransparency={1}
|
||||||
|
Key="Hotbar"
|
||||||
|
>
|
||||||
|
<frame Size={new UDim2(0, 0, 0.5, 0)} Position={new UDim2(0.5, 0, 0.5, 0)} BackgroundTransparency={1}>
|
||||||
|
<uilistlayout
|
||||||
|
FillDirection={Enum.FillDirection.Horizontal}
|
||||||
|
HorizontalAlignment={Enum.HorizontalAlignment.Center}
|
||||||
|
VerticalAlignment={Enum.VerticalAlignment.Bottom}
|
||||||
|
Padding={new UDim(0, 5)}
|
||||||
|
/>
|
||||||
|
<Padding
|
||||||
|
PaddingY={new UDim(0, 5)}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
clientState.backpack.GetChildren().map((tool, i) => (
|
||||||
|
<Slot
|
||||||
|
index={i + 1}
|
||||||
|
Size={new UDim2(1, 0, 1, 0)}
|
||||||
|
keycode={keycodes[i]}
|
||||||
|
tool={tool as Tool}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</frame>
|
||||||
|
</frame>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Hooks(Roact)(hotbar)
|
97
src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx
Normal file
97
src/StarterPlayer/StarterPlayerScripts/ui/hotbar/slot.tsx
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import Roact from "@rbxts/roact"
|
||||||
|
import Hooks from "@rbxts/roact-hooks"
|
||||||
|
import { useWorldContext } from "../contexts/worldContext"
|
||||||
|
import { ContextActionService, HttpService } from "@rbxts/services"
|
||||||
|
import Padding from "ReplicatedStorage/ui/padding"
|
||||||
|
|
||||||
|
interface slotProps extends Roact.JsxInstanceProperties<Frame> {
|
||||||
|
index: number
|
||||||
|
keycode: Enum.KeyCode
|
||||||
|
tool: Tool
|
||||||
|
|
||||||
|
Event?: Roact.JsxInstanceEvents<Frame>
|
||||||
|
Change?: Roact.JsxInstanceChangeEvents<Frame>
|
||||||
|
}
|
||||||
|
|
||||||
|
const slot: Hooks.FC<slotProps> = (props, hooks) => {
|
||||||
|
const { useEffect } = hooks
|
||||||
|
const { index, keycode, tool } = props
|
||||||
|
|
||||||
|
const spreadableProps = { ...props } as Partial<slotProps>
|
||||||
|
delete spreadableProps.index
|
||||||
|
delete spreadableProps.keycode
|
||||||
|
delete spreadableProps.tool
|
||||||
|
|
||||||
|
const { world, clientState } = useWorldContext(hooks)
|
||||||
|
|
||||||
|
const handleActivated = () => {
|
||||||
|
if (tool.Parent !== clientState.character) {
|
||||||
|
clientState.character.Humanoid.EquipTool(tool)
|
||||||
|
} else {
|
||||||
|
clientState.character.Humanoid.UnequipTools()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// maybe opt this into our system for inputs?
|
||||||
|
useEffect(() => {
|
||||||
|
const guid = HttpService.GenerateGUID(false)
|
||||||
|
ContextActionService.BindAction(
|
||||||
|
guid,
|
||||||
|
(_, userInputState) => {
|
||||||
|
if (Enum.UserInputState.Begin === userInputState) handleActivated()
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
keycode
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<frame {...spreadableProps} BackgroundTransparency={1} SizeConstraint={Enum.SizeConstraint.RelativeYY}>
|
||||||
|
<textbutton
|
||||||
|
Position={new UDim2(0, 0, 0, 0)}
|
||||||
|
Size={new UDim2(1, 0, 1, 0)}
|
||||||
|
BackgroundColor3={new Color3()}
|
||||||
|
BackgroundTransparency={0.3}
|
||||||
|
Text=""
|
||||||
|
Event={{
|
||||||
|
Activated: () => {
|
||||||
|
handleActivated()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<uicorner CornerRadius={new UDim(0.05, 0)}/>
|
||||||
|
<uistroke
|
||||||
|
Thickness={2}
|
||||||
|
Color={new Color3(0.1, 0.1, 0.1)}
|
||||||
|
ApplyStrokeMode={Enum.ApplyStrokeMode.Border}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<textlabel
|
||||||
|
Size={new UDim2(1, 0, 0.2, 0)}
|
||||||
|
Text={tostring(index)}
|
||||||
|
TextXAlignment={Enum.TextXAlignment.Left}
|
||||||
|
BackgroundTransparency={1}
|
||||||
|
TextColor3={new Color3(1, 1, 1)}
|
||||||
|
TextScaled
|
||||||
|
>
|
||||||
|
<uistroke Thickness={1}/>
|
||||||
|
</textlabel>
|
||||||
|
|
||||||
|
<textlabel
|
||||||
|
Size={new UDim2(1, 0, 1, 0)}
|
||||||
|
AnchorPoint={new Vector2(0.5, 0.5)}
|
||||||
|
Position={new UDim2(0.5, 0, 0.5, 0)}
|
||||||
|
BackgroundTransparency={1}
|
||||||
|
TextScaled
|
||||||
|
Text={tool.Name}
|
||||||
|
TextColor3={Color3.fromRGB(255, 255, 255)}
|
||||||
|
>
|
||||||
|
<uistroke Thickness={1}/>
|
||||||
|
<Padding Padding={new UDim(0.05, 0)}/>
|
||||||
|
</textlabel>
|
||||||
|
</textbutton>
|
||||||
|
</frame>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Hooks(Roact)(slot)
|
28
src/StarterPlayer/StarterPlayerScripts/ui/main.tsx
Normal file
28
src/StarterPlayer/StarterPlayerScripts/ui/main.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import Roact from "@rbxts/roact"
|
||||||
|
import Hooks from "@rbxts/roact-hooks"
|
||||||
|
import Hotbar from "./hotbar/hotbar"
|
||||||
|
import { Players } from "@rbxts/services"
|
||||||
|
|
||||||
|
interface mainProps extends Roact.JsxInstanceEvents<ScreenGui> {
|
||||||
|
Event?: Roact.JsxInstanceEvents<ScreenGui>
|
||||||
|
Change?: Roact.JsxInstanceChangeEvents<ScreenGui>
|
||||||
|
}
|
||||||
|
|
||||||
|
const main: Hooks.FC<mainProps> = (props, hooks) => {
|
||||||
|
const {} = props
|
||||||
|
const {} = hooks
|
||||||
|
|
||||||
|
const spreadableProps = { ...props } as Partial<mainProps>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<screengui ResetOnSpawn={false} IgnoreGuiInset {...spreadableProps}>
|
||||||
|
<Hotbar
|
||||||
|
Position={new UDim2(0.5, 0, 1, 0)}
|
||||||
|
AnchorPoint={new Vector2(0.5, 1)}
|
||||||
|
Size={new UDim2(1, 0, 0.2, 0)}
|
||||||
|
/>
|
||||||
|
</screengui>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Hooks(Roact)(main)
|
10
yarn.lock
10
yarn.lock
|
@ -118,6 +118,16 @@
|
||||||
resolved "https://registry.yarnpkg.com/@rbxts/rewire/-/rewire-0.3.0.tgz#47f0cd651fe405cf418936799d2a4dac6b1bb7ce"
|
resolved "https://registry.yarnpkg.com/@rbxts/rewire/-/rewire-0.3.0.tgz#47f0cd651fe405cf418936799d2a4dac6b1bb7ce"
|
||||||
integrity sha512-wChhGZ3kEkEsMK9ZuwKpwRsC7OGVZlvxrYMR3beFgCIPXE58JKLziBLkDACmd709XCCEmsMAqv9HMCMhSTD08Q==
|
integrity sha512-wChhGZ3kEkEsMK9ZuwKpwRsC7OGVZlvxrYMR3beFgCIPXE58JKLziBLkDACmd709XCCEmsMAqv9HMCMhSTD08Q==
|
||||||
|
|
||||||
|
"@rbxts/roact-hooks@^0.4.1-ts.3":
|
||||||
|
version "0.4.1-ts.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rbxts/roact-hooks/-/roact-hooks-0.4.1-ts.3.tgz#af9b549f5912bd50640c2887aa698e21154fadd3"
|
||||||
|
integrity sha512-+8A42hDsSwZNnXDe1XIRpJhjSpxFvkBa8nB5QM1zuL2q5G6h6SGp7augY6vp6euze/gH4/Laho07PUM8bz0RKQ==
|
||||||
|
|
||||||
|
"@rbxts/roact@^1.4.4-ts.0":
|
||||||
|
version "1.4.4-ts.0"
|
||||||
|
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.5.1":
|
"@rbxts/services@^1.5.1":
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rbxts/services/-/services-1.5.1.tgz#4536a87932f28797507ed591f0061277c52ea77f"
|
resolved "https://registry.yarnpkg.com/@rbxts/services/-/services-1.5.1.tgz#4536a87932f28797507ed591f0061277c52ea77f"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue