interface case, acrylic ui, swap to make, lint

This commit is contained in:
Reid 2023-08-15 20:18:59 -07:00
parent f5584a9b0c
commit a5bc77030a
24 changed files with 353 additions and 92 deletions

View file

@ -27,7 +27,6 @@
"@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-namespace": "error", "@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-unused-vars": [ "@typescript-eslint/no-unused-vars": [
"warn", "warn",
{ {

View file

@ -34,6 +34,7 @@
"dependencies": { "dependencies": {
"@rbxts/character-promise": "^1.0.2", "@rbxts/character-promise": "^1.0.2",
"@rbxts/log": "^0.6.3", "@rbxts/log": "^0.6.3",
"@rbxts/make": "^1.0.6",
"@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/reflex": "^4.2.0", "@rbxts/reflex": "^4.2.0",

View file

@ -6,7 +6,7 @@ import { Host } from "ReplicatedStorage/hosts"
import { tags } from "./boundTags" import { tags } from "./boundTags"
import { Model } from "./components" import { Model } from "./components"
import { start as startReplication, stop as stopReplication } from "./replication" import { start as startReplication, stop as stopReplication } from "./replication"
import { clientState, serverState } from "./state" import { ClientState, ServerState } from "./state"
import { start as startSystems, stop as stopSystems } from "./systems" import { start as startSystems, stop as stopSystems } from "./systems"
import { start as startTags, stop as stopTags } from "./tags" import { start as startTags, stop as stopTags } from "./tags"
@ -45,13 +45,13 @@ export function start<S extends object>(host: Host, state: S): [World, S] {
}) })
if (host === Host.All || host === Host.Server) { if (host === Host.All || host === Host.Server) {
const ServerState = state as serverState const ServerState = state as ServerState
startTags(world, tags, ServerState) startTags(world, tags, ServerState)
} }
if (host === Host.All || host === Host.Client) { if (host === Host.All || host === Host.Client) {
const ClientState = state as clientState const ClientState = state as ClientState
startReplication(world, ClientState) startReplication(world, ClientState)

View file

@ -1,7 +1,7 @@
import { AnyEntity, World } from "@rbxts/matter" import { AnyEntity, World } from "@rbxts/matter"
import { waitForEvent } from "ReplicatedStorage/remotes" import { waitForEvent } from "ReplicatedStorage/remotes"
import * as Components from "./components" import * as Components from "./components"
import { clientState } from "./state" import { ClientState } from "./state"
type ComponentNames = keyof typeof Components type ComponentNames = keyof typeof Components
type ComponentConstructors = (typeof Components)[ComponentNames] type ComponentConstructors = (typeof Components)[ComponentNames]
@ -14,7 +14,7 @@ let connection: RBXScriptConnection | undefined
* @param world - The world to replicate components in * @param world - The world to replicate components in
* @param client - The client state for the ECS * @param client - The client state for the ECS
*/ */
export function start(world: World, client: clientState): void { export function start(world: World, client: ClientState): void {
if (connection) return if (connection) return
const replicationEvent = waitForEvent("EcsReplication") const replicationEvent = waitForEvent("EcsReplication")

View file

@ -7,7 +7,7 @@ import { InputKind } from "ReplicatedStorage/inputKind"
/** /**
* The client ECS state. * The client ECS state.
*/ */
export class clientState { export class ClientState {
constructor( constructor(
player: Player, player: Player,
character: CharacterRigR6, character: CharacterRigR6,
@ -41,7 +41,7 @@ export class clientState {
/** /**
* The server ECS state. * The server ECS state.
*/ */
export class serverState { export class ServerState {
constructor( constructor(
logger: Logger logger: Logger
) { ) {
@ -54,4 +54,4 @@ export class serverState {
/** /**
* The shared ECS state. * The shared ECS state.
*/ */
export type sharedState = serverState & clientState export type SharedState = ServerState & ClientState

View file

@ -1,6 +1,6 @@
import { World, useEvent } from "@rbxts/matter" import { World, useEvent } from "@rbxts/matter"
import { StarterGui } from "@rbxts/services" import { StarterGui } from "@rbxts/services"
import { clientState } from "ReplicatedStorage/ecs/state" import { ClientState } from "ReplicatedStorage/ecs/state"
import { getEvent } from "ReplicatedStorage/remotes" import { getEvent } from "ReplicatedStorage/remotes"
const resetButtonCallback = new Instance("BindableEvent") const resetButtonCallback = new Instance("BindableEvent")
@ -8,7 +8,7 @@ StarterGui.SetCore("ResetButtonCallback", resetButtonCallback)
getEvent("resetButton") getEvent("resetButton")
function customReset(_: World, _client: clientState): void { function customReset(_: World, _client: ClientState): void {
const resetButtonEvent = getEvent("resetButton") const resetButtonEvent = getEvent("resetButton")
for (const [,] of useEvent(resetButtonCallback, "Event")) { for (const [,] of useEvent(resetButtonCallback, "Event")) {
resetButtonEvent.FireServer() resetButtonEvent.FireServer()

View file

@ -1,10 +1,10 @@
import { useDeltaTime, useEvent, useThrottle, World } from "@rbxts/matter" import { useDeltaTime, useEvent, useThrottle, World } from "@rbxts/matter"
import { UserInputService } from "@rbxts/services" import { UserInputService } from "@rbxts/services"
import { clientState } from "ReplicatedStorage/ecs/state" import { ClientState } from "ReplicatedStorage/ecs/state"
import { InputKind } from "ReplicatedStorage/inputKind" import { InputKind } from "ReplicatedStorage/inputKind"
let holdDuration = 0 let holdDuration = 0
function inputMapper(_: World, client: clientState): void { function inputMapper(_: World, client: ClientState): void {
for (const [, input, gpe] of useEvent(UserInputService, "InputBegan")) { for (const [, input, gpe] of useEvent(UserInputService, "InputBegan")) {
if (gpe) return undefined if (gpe) return undefined
if (input.KeyCode !== Enum.KeyCode.Unknown) { if (input.KeyCode !== Enum.KeyCode.Unknown) {

View file

@ -1,8 +1,8 @@
import { World } from "@rbxts/matter" import { World } from "@rbxts/matter"
import { match } from "@rbxts/variant" import { match } from "@rbxts/variant"
import { clientState } from "ReplicatedStorage/ecs/state" import { ClientState } from "ReplicatedStorage/ecs/state"
function sprint(_: World, client: clientState): void { function sprint(_: World, client: ClientState): void {
if (client.lastProcessedCommand !== undefined) { if (client.lastProcessedCommand !== undefined) {
match(client.lastProcessedCommand, { match(client.lastProcessedCommand, {
KeyDown: ({ key }) => { KeyDown: ({ key }) => {

View file

@ -2,7 +2,7 @@ import { AnyEntity, Component, World } from "@rbxts/matter"
import { CollectionService } from "@rbxts/services" import { CollectionService } from "@rbxts/services"
import { getIdAttribute } from "ReplicatedStorage/idAttribute" import { getIdAttribute } from "ReplicatedStorage/idAttribute"
import { Model, Transform } from "./components" import { Model, Transform } from "./components"
import { serverState } from "./state" import { ServerState } from "./state"
export type ComponentConstructor<T extends object> = () => Component<T> export type ComponentConstructor<T extends object> = () => Component<T>
@ -17,7 +17,7 @@ const connections: RBXScriptConnection[] = []
export function start( export function start(
world: World, world: World,
bound: ReadonlyMap<string, ComponentConstructor<object>>, bound: ReadonlyMap<string, ComponentConstructor<object>>,
server: serverState server: ServerState
): void { ): void {
function spawnBound<T extends object>( function spawnBound<T extends object>(
instance: Instance, instance: Instance,

View file

@ -1,4 +0,0 @@
import { UseProducerHook, useProducer } from "@rbxts/roact-reflex"
import { rootProducer } from "../producer"
export const useRootProducer: UseProducerHook<rootProducer> = useProducer

View file

@ -1,9 +0,0 @@
import { InferDispatchers, InferState, combineProducers, loggerMiddleware } from "@rbxts/reflex"
export type rootProducer = typeof producer
export type rootState = InferState<rootProducer>
export type rootDispatchers = InferDispatchers<rootProducer>
export const producer = combineProducers({
}).applyMiddleware(loggerMiddleware)

View file

@ -0,0 +1,77 @@
import Make from "@rbxts/make"
export type AcrylicInstance = Model & {
Horizontal: Part & { Mesh: SpecialMesh }
Vertical: Part & { Mesh: SpecialMesh }
TopLeft: Part & { Mesh: SpecialMesh }
TopRight: Part & { Mesh: SpecialMesh }
BottomLeft: Part & { Mesh: SpecialMesh }
BottomRight: Part & { Mesh: SpecialMesh }
}
const fill = {
Color: new Color3(0, 0, 0),
Material: Enum.Material.Glass,
Size: new Vector3(1, 1, 0),
Anchored: true,
CanCollide: false,
Locked: true,
CastShadow: false,
Transparency: 0.999
}
const corner = {
Color: new Color3(0, 0, 0),
Material: Enum.Material.Glass,
Size: new Vector3(0, 1, 1),
Anchored: true,
CanCollide: false,
Locked: true,
CastShadow: false,
Transparency: 0.999
}
export const acrylicInstance = Make("Model", {
Children: [
Make("Part", {
Name: "Horizontal",
Children: [
Make("SpecialMesh", {
MeshType: Enum.MeshType.Brick,
Offset: new Vector3(0, 0, -0.000001)
})
],
...fill
}),
Make("Part", {
Name: "Vertical",
Children: [
Make("SpecialMesh", {
MeshType: Enum.MeshType.Brick,
Offset: new Vector3(0, 0, 0.000001)
})
],
...fill
}),
Make("Part", {
Name: "TopRight",
Children: [Make("SpecialMesh", { MeshType: Enum.MeshType.Cylinder })],
...corner
}),
Make("Part", {
Name: "TopLeft",
Children: [Make("SpecialMesh", { MeshType: Enum.MeshType.Cylinder })],
...corner
}),
Make("Part", {
Name: "BottomRight",
Children: [Make("SpecialMesh", { MeshType: Enum.MeshType.Cylinder })],
...corner
}),
Make("Part", {
Name: "BottomLeft",
Children: [Make("SpecialMesh", { MeshType: Enum.MeshType.Cylinder })],
...corner
})
]
}) as AcrylicInstance

View file

@ -0,0 +1,165 @@
import Roact from "@rbxts/roact"
import { useEffect, useCallback, useMemo, useMutable } from "@rbxts/roact-hooked"
import { acrylicInstance } from "./acrylicInstance"
import { Lighting, Workspace } from "@rbxts/services"
import Make from "@rbxts/make"
const cylinderAngleOffset = CFrame.Angles(0, math.rad(90), 0)
function viewportPointToWorld(location: Vector2, distance: number): Vector3 {
const unitRay = Workspace.CurrentCamera!.ScreenPointToRay(location.X, location.Y)
return unitRay.Origin.add(unitRay.Direction.mul(distance))
}
function map(n: number, min0: number, max0: number, min1: number, max1: number): number {
return min1 + ((n - min0) * (max1 - min1)) / (max0 - min0)
}
function getOffset(): number {
return map(Workspace.CurrentCamera!.ViewportSize.Y, 0, 2560, 8, 56)
}
const DOFEffect = Make("DepthOfFieldEffect", {
FarIntensity: 0,
InFocusRadius: 0.1,
NearIntensity: 1
})
DOFEffect.Parent = Lighting
interface acrylicProps extends Roact.JsxInstanceProperties<Frame> {
radius: number
distance: number
Event?: Roact.JsxInstanceEvents<Frame>
Change?: Roact.JsxInstanceChangeEvents<Frame>
}
function acrylic(props: acrylicProps): Roact.Element {
const { radius, distance } = props
const spreadableProps = { ...props } as Partial<acrylicProps>
delete spreadableProps.radius
delete spreadableProps.distance
const frameInfo = useMutable({
topleft2d: new Vector2(),
topright2d: new Vector2(),
bottomright2d: new Vector2(),
topleftradius2d: new Vector2()
})
const acrylic = useMemo(() => {
const clone = acrylicInstance.Clone()
clone.Parent = Workspace
return clone
}, [])
useEffect(() => {
return () => acrylic.Destroy()
}, [])
const updateFrameInfo = useCallback(
(size: Vector2, position: Vector2) => {
const topleftRaw = position.sub(size.div(2))
const info = frameInfo.current
info.topleft2d = new Vector2(math.ceil(topleftRaw.X), math.ceil(topleftRaw.Y))
info.topright2d = info.topleft2d.add(new Vector2(size.X, 0))
info.bottomright2d = info.topleft2d.add(size)
info.topleftradius2d = info.topleft2d.add(new Vector2(radius, 0))
},
[distance, radius]
)
const updateInstance = useCallback(() => {
const { topleft2d, topright2d, bottomright2d, topleftradius2d } = frameInfo.current
const topleft = viewportPointToWorld(topleft2d, distance)
const topright = viewportPointToWorld(topright2d, distance)
const bottomright = viewportPointToWorld(bottomright2d, distance)
const topleftradius = viewportPointToWorld(topleftradius2d, distance)
const cornerRadius = topleftradius.sub(topleft).Magnitude
const width = topright.sub(topleft).Magnitude
const height = topright.sub(bottomright).Magnitude
const center = CFrame.fromMatrix(
topleft.add(bottomright).div(2),
Workspace.CurrentCamera!.CFrame.XVector,
Workspace.CurrentCamera!.CFrame.YVector,
Workspace.CurrentCamera!.CFrame.ZVector
)
if (radius !== undefined && radius > 0) {
acrylic.Horizontal.CFrame = center
acrylic.Horizontal.Mesh.Scale = new Vector3(width - cornerRadius * 2, height, 0)
acrylic.Vertical.CFrame = center
acrylic.Vertical.Mesh.Scale = new Vector3(width, height - cornerRadius * 2, 0)
} else {
acrylic.Horizontal.CFrame = center
acrylic.Horizontal.Mesh.Scale = new Vector3(width, height, 0)
}
if (radius !== undefined && radius > 0) {
acrylic.TopLeft.CFrame = center
.mul(new CFrame(-width / 2 + cornerRadius, height / 2 - cornerRadius, 0))
.mul(cylinderAngleOffset)
acrylic.TopLeft.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
acrylic.TopRight.CFrame = center
.mul(new CFrame(width / 2 - cornerRadius, height / 2 - cornerRadius, 0))
.mul(cylinderAngleOffset)
acrylic.TopRight.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
acrylic.BottomLeft.CFrame = center
.mul(new CFrame(-width / 2 + cornerRadius, -height / 2 + cornerRadius, 0))
.mul(cylinderAngleOffset)
acrylic.BottomLeft.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
acrylic.BottomRight.CFrame = center
.mul(new CFrame(width / 2 - cornerRadius, -height / 2 + cornerRadius, 0))
.mul(cylinderAngleOffset)
acrylic.BottomRight.Mesh.Scale = new Vector3(0, cornerRadius * 2, cornerRadius * 2)
}
}, [radius, distance])
useEffect(() => {
updateInstance()
const posHandle = Workspace.CurrentCamera!.GetPropertyChangedSignal("CFrame").Connect(updateInstance)
const fovHandle = Workspace.CurrentCamera!.GetPropertyChangedSignal("FieldOfView").Connect(updateInstance)
const viewportHandle = Workspace.CurrentCamera!.GetPropertyChangedSignal("ViewportSize").Connect(updateInstance)
return () => {
posHandle.Disconnect()
fovHandle.Disconnect()
viewportHandle.Disconnect()
}
}, [updateInstance])
return (
<frame
Change={{
AbsoluteSize: (rbx): void => {
const blurOffset = getOffset()
const size = rbx.AbsoluteSize.sub(new Vector2(blurOffset, blurOffset))
const position = rbx.AbsolutePosition.add(rbx.AbsoluteSize.div(2))
updateFrameInfo(size, position)
task.spawn(updateInstance)
},
AbsolutePosition: (rbx): void => {
const blurOffset = getOffset()
const size = rbx.AbsoluteSize.sub(new Vector2(blurOffset, blurOffset))
const position = rbx.AbsolutePosition.add(rbx.AbsoluteSize.div(2))
updateFrameInfo(size, position)
task.spawn(updateInstance)
}
}}
Size={new UDim2(1, 0, 1, 0)}
BackgroundTransparency={1}
/>
)
}
export default acrylic

View file

@ -1,4 +1,3 @@
import Hooks from "@rbxts/roact-hooked"
import Roact from "@rbxts/roact" import Roact from "@rbxts/roact"
interface paddingProps extends Roact.JsxInstanceProperties<UIPadding> { interface paddingProps extends Roact.JsxInstanceProperties<UIPadding> {

View file

@ -1,3 +1,4 @@
import Make from "@rbxts/make"
import { World, useEvent } from "@rbxts/matter" import { World, useEvent } from "@rbxts/matter"
import { Model, PlayerCharacter } from "ReplicatedStorage/ecs/components" import { Model, PlayerCharacter } from "ReplicatedStorage/ecs/components"
@ -15,19 +16,22 @@ function playersRagdollOnDeath(world: World): void {
for (const [_] of useEvent(playerCharacter.humanoid, "Died")) { for (const [_] of useEvent(playerCharacter.humanoid, "Died")) {
model.model.GetDescendants().forEach((v, _) => { model.model.GetDescendants().forEach((v, _) => {
if (v.IsA("Motor6D")) { if (v.IsA("Motor6D")) {
const attachment0 = new Instance("Attachment") const attachment0 = Make("Attachment", {
const attachment1 = new Instance("Attachment") CFrame: v.C0,
attachment0.CFrame = v.C0 Parent: v.Part0
attachment1.CFrame = v.C1 })
attachment0.Parent = v.Part0 const attachment1 = Make("Attachment", {
attachment1.Parent = v.Part1 CFrame: v.C1,
Parent: v.Part1
})
const ballSocketConstraint = new Instance("BallSocketConstraint") Make("BallSocketConstraint", {
ballSocketConstraint.Attachment0 = attachment0 Attachment0: attachment0,
ballSocketConstraint.Attachment1 = attachment1 Attachment1: attachment1,
ballSocketConstraint.LimitsEnabled = true LimitsEnabled: true,
ballSocketConstraint.TwistLimitsEnabled = true TwistLimitsEnabled: true,
ballSocketConstraint.Parent = v.Parent Parent: v.Parent
})
v.Destroy() v.Destroy()
} }

View file

@ -1,7 +1,7 @@
import { useEvent, World } from "@rbxts/matter" import { useEvent, World } from "@rbxts/matter"
import { Players } from "@rbxts/services" import { Players } from "@rbxts/services"
import * as Components from "ReplicatedStorage/ecs/components" import * as Components from "ReplicatedStorage/ecs/components"
import { serverState } from "ReplicatedStorage/ecs/state" import { ServerState } from "ReplicatedStorage/ecs/state"
import { getEvent } from "ReplicatedStorage/remotes" import { getEvent } from "ReplicatedStorage/remotes"
type ComponentName = keyof typeof Components type ComponentName = keyof typeof Components
@ -21,7 +21,7 @@ const replicatedComponents: ReadonlySet<ComponentConstructor> = REPLICATED_COMPO
getEvent("EcsReplication") getEvent("EcsReplication")
function replication(world: World, server: serverState): void { function replication(world: World, server: ServerState): void {
const replicationEvent = getEvent("EcsReplication") const replicationEvent = getEvent("EcsReplication")
let payload: Map<string, Map<ComponentName, { data?: Components.GooplerComponent }>> | undefined let payload: Map<string, Map<ComponentName, { data?: Components.GooplerComponent }>> | undefined

View file

@ -1,6 +1,6 @@
import Log, { Logger } from "@rbxts/log" import Log, { Logger } from "@rbxts/log"
import { start } from "ReplicatedStorage/ecs" import { start } from "ReplicatedStorage/ecs"
import { serverState } from "ReplicatedStorage/ecs/state" import { ServerState } 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 { getEvent } from "ReplicatedStorage/remotes" import { getEvent } from "ReplicatedStorage/remotes"
@ -12,7 +12,7 @@ const serverLogger = Logger.configure()
.WriteTo(Log.RobloxOutput()) .WriteTo(Log.RobloxOutput())
.Create() .Create()
const ServerState = new serverState( const serverState = new ServerState(
serverLogger serverLogger
) )
@ -21,4 +21,4 @@ const ServerState = new serverState(
getEvent("EcsReplication") getEvent("EcsReplication")
setEnvironment(HOST) setEnvironment(HOST)
start(HOST, ServerState) start(HOST, serverState)

View file

@ -1,8 +1,8 @@
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, Workspace } 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" import showGUI from "./showGUI"
@ -13,7 +13,7 @@ const clientLogger = Logger.configure()
.WriteTo(Log.RobloxOutput()) .WriteTo(Log.RobloxOutput())
.Create() .Create()
const ClientState = new clientState( const clientState = new ClientState(
Players.LocalPlayer, Players.LocalPlayer,
(Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6, (Players.LocalPlayer.Character || Players.LocalPlayer.CharacterAdded.Wait()[0]) as CharacterRigR6,
false, false,
@ -23,6 +23,10 @@ const ClientState = new clientState(
clientLogger clientLogger
) )
const worldAndClientState = start(HOST, ClientState) const worldAndClientState = start(HOST, clientState)
showGUI(worldAndClientState[0], ClientState) showGUI(worldAndClientState[0], clientState)
setEnvironment(HOST) setEnvironment(HOST)
task.delay(10, () => {
print(Workspace.CurrentCamera?.GetChildren())
})

View file

@ -1,12 +1,12 @@
import { World } from "@rbxts/matter" import { World } from "@rbxts/matter"
import { clientState } from "ReplicatedStorage/ecs/state" import { ClientState } from "ReplicatedStorage/ecs/state"
import { WorldContext } from "./ui/contexts/worldContext" import { WorldContext } from "./ui/contexts/worldContext"
import Roact from "@rbxts/roact" import Roact from "@rbxts/roact"
import Main from "./ui/main" import Main from "./ui/main"
import { ReflexProvider } from "@rbxts/roact-reflex" import { ReflexProvider } from "@rbxts/roact-reflex"
import { producer } from "ReplicatedStorage/ui/store/producer" import { producer } from "ReplicatedStorage/ui/store/producer"
const showGUI = (world: World, state: clientState): void => { const showGUI = (world: World, state: ClientState): void => {
const playerGui = state.player.WaitForChild("PlayerGui") as PlayerGui const playerGui = state.player.WaitForChild("PlayerGui") as PlayerGui
const tree = ( const tree = (
<WorldContext.Provider value={{ world: world, clientState: state }}> <WorldContext.Provider value={{ world: world, clientState: state }}>

View file

@ -1,16 +1,16 @@
import { World } from "@rbxts/matter" import { World } from "@rbxts/matter"
import Roact from "@rbxts/roact" import Roact from "@rbxts/roact"
import { useContext } from "@rbxts/roact-hooked" import { useContext } from "@rbxts/roact-hooked"
import { clientState } from "ReplicatedStorage/ecs/state" import { ClientState } from "ReplicatedStorage/ecs/state"
interface worldContextProps { interface WorldContextProps {
world: World world: World
clientState: clientState clientState: ClientState
} }
export const WorldContext = Roact.createContext<worldContextProps | undefined>(undefined) export const WorldContext = Roact.createContext<WorldContextProps | undefined>(undefined)
export function useWorldContext(): worldContextProps { export function useWorldContext(): WorldContextProps {
const context = useContext(WorldContext) const context = useContext(WorldContext)
if (!context) { if (!context) {
error("useContext must be called within a Provider") error("useContext must be called within a Provider")

View file

@ -4,15 +4,15 @@ import { useWorldContext } from "../contexts/worldContext"
import Padding from "ReplicatedStorage/ui/components/padding" import Padding from "ReplicatedStorage/ui/components/padding"
import { StarterGui } from "@rbxts/services" import { StarterGui } from "@rbxts/services"
interface hotbarProps extends Roact.JsxInstanceProperties<Frame> { interface HotbarProps extends Roact.JsxInstanceProperties<Frame> {
Event?: Roact.JsxInstanceEvents<Frame> Event?: Roact.JsxInstanceEvents<Frame>
Change?: Roact.JsxInstanceChangeEvents<Frame> Change?: Roact.JsxInstanceChangeEvents<Frame>
} }
StarterGui.SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false) StarterGui.SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
function hotbar(props: hotbarProps): Roact.Element { function hotbar(props: HotbarProps): Roact.Element {
const spreadableProps = { ...props } as Partial<hotbarProps> const spreadableProps = { ...props } as Partial<HotbarProps>
const { clientState } = useWorldContext() const { clientState } = useWorldContext()

View file

@ -3,8 +3,9 @@ import { useEffect } from "@rbxts/roact-hooked"
import { useWorldContext } from "../contexts/worldContext" import { useWorldContext } from "../contexts/worldContext"
import { ContextActionService, HttpService } from "@rbxts/services" import { ContextActionService, HttpService } from "@rbxts/services"
import Padding from "ReplicatedStorage/ui/components/padding" import Padding from "ReplicatedStorage/ui/components/padding"
import Acrylic from "ReplicatedStorage/ui/components/acrylic"
interface slotProps extends Roact.JsxInstanceProperties<Frame> { interface SlotProps extends Roact.JsxInstanceProperties<Frame> {
index: number index: number
keycode: Enum.KeyCode keycode: Enum.KeyCode
tool: Tool tool: Tool
@ -13,10 +14,10 @@ interface slotProps extends Roact.JsxInstanceProperties<Frame> {
Change?: Roact.JsxInstanceChangeEvents<Frame> Change?: Roact.JsxInstanceChangeEvents<Frame>
} }
function slot(props: slotProps): Roact.Element { function slot(props: SlotProps): Roact.Element {
const { index, keycode, tool } = props const { index, keycode, tool } = props
const spreadableProps = { ...props } as Partial<slotProps> const spreadableProps = { ...props } as Partial<SlotProps>
delete spreadableProps.index delete spreadableProps.index
delete spreadableProps.keycode delete spreadableProps.keycode
delete spreadableProps.tool delete spreadableProps.tool
@ -48,16 +49,21 @@ function slot(props: slotProps): Roact.Element {
<frame <frame
BackgroundColor3={Color3.fromHex("#11111b")} BackgroundColor3={Color3.fromHex("#11111b")}
BackgroundTransparency={ BackgroundTransparency={
.7 .75
} }
Size={new UDim2(1, 0, 1, 0)} Size={new UDim2(1, 0, 1, 0)}
> >
<Acrylic
radius={0}
distance={0.0001}
/>
<uiaspectratioconstraint <uiaspectratioconstraint
AspectRatio={6} AspectRatio={6}
/> />
<uicorner <uicorner
CornerRadius={new UDim(0, 8)} CornerRadius={new UDim(0, 8)}
/> />
<frame BackgroundTransparency={1} Size={new UDim2(1, 0, 1, 0)}>
<Padding <Padding
paddingY={new UDim(.3, 0)} paddingY={new UDim(.3, 0)}
/> />
@ -80,6 +86,7 @@ function slot(props: slotProps): Roact.Element {
TextScaled TextScaled
/> />
</frame> </frame>
</frame>
) )
} }

View file

@ -2,13 +2,13 @@ import Roact from "@rbxts/roact"
import Hotbar from "./hotbar/hotbar" import Hotbar from "./hotbar/hotbar"
import { withHookDetection } from "@rbxts/roact-hooked" import { withHookDetection } from "@rbxts/roact-hooked"
interface mainProps extends Roact.JsxInstanceEvents<ScreenGui> { interface MainProps extends Roact.JsxInstanceEvents<ScreenGui> {
Event?: Roact.JsxInstanceEvents<ScreenGui> Event?: Roact.JsxInstanceEvents<ScreenGui>
Change?: Roact.JsxInstanceChangeEvents<ScreenGui> Change?: Roact.JsxInstanceChangeEvents<ScreenGui>
} }
export default function main(props: mainProps): Roact.Element { export default function main(props: MainProps): Roact.Element {
const spreadableProps = { ...props } as Partial<mainProps> const spreadableProps = { ...props } as Partial<MainProps>
withHookDetection(Roact) withHookDetection(Roact)

View file

@ -86,6 +86,11 @@
dependencies: dependencies:
"@rbxts/validate-tree" "^2.0.1" "@rbxts/validate-tree" "^2.0.1"
"@rbxts/compiler-types@^1.2.3-types.1":
version "1.2.3-types.1"
resolved "https://registry.yarnpkg.com/@rbxts/compiler-types/-/compiler-types-1.2.3-types.1.tgz#d7945531c917d62bafadd2b5aa6c2f2e88a2036a"
integrity sha512-SXXIBazyJ7N6d2xcy471/kqZZpCv7EDOWrRJ45jcv3g00VQaZwYl4Elr10woqRloIblQanwJ7yUqGXAsWv7iuQ==
"@rbxts/compiler-types@^2.1.1-types.0": "@rbxts/compiler-types@^2.1.1-types.0":
version "2.1.1-types.0" version "2.1.1-types.0"
resolved "https://registry.yarnpkg.com/@rbxts/compiler-types/-/compiler-types-2.1.1-types.0.tgz#a1f02b57402dffec474dd6656ec1d8a897b9756b" resolved "https://registry.yarnpkg.com/@rbxts/compiler-types/-/compiler-types-2.1.1-types.0.tgz#a1f02b57402dffec474dd6656ec1d8a897b9756b"
@ -98,6 +103,14 @@
dependencies: dependencies:
"@rbxts/message-templates" "^0.3.1" "@rbxts/message-templates" "^0.3.1"
"@rbxts/make@^1.0.6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@rbxts/make/-/make-1.0.6.tgz#9fbed42cd263b6ce997cdb6a840f77fdeb9e6b36"
integrity sha512-ZL1FMxDqWv1TIzE064JFen75rgybV7ulQHTUVqXuvngDBa3lP3btFiIdUO2MMJAOZpHKinC9jFudcCenrprcPg==
dependencies:
"@rbxts/compiler-types" "^1.2.3-types.1"
"@rbxts/types" "^1.0.537"
"@rbxts/matter@^0.6.2-ts.6": "@rbxts/matter@^0.6.2-ts.6":
version "0.6.4" version "0.6.4"
resolved "https://registry.yarnpkg.com/@rbxts/matter/-/matter-0.6.4.tgz#49ff6ce56bada1ce7c5e2715a05daaa3fb7615e6" resolved "https://registry.yarnpkg.com/@rbxts/matter/-/matter-0.6.4.tgz#49ff6ce56bada1ce7c5e2715a05daaa3fb7615e6"
@ -148,6 +161,11 @@
resolved "https://registry.yarnpkg.com/@rbxts/testez/-/testez-0.4.2-ts.0.tgz#4475183d317182ac7099bffee6492ffcb7bcaf0b" resolved "https://registry.yarnpkg.com/@rbxts/testez/-/testez-0.4.2-ts.0.tgz#4475183d317182ac7099bffee6492ffcb7bcaf0b"
integrity sha512-8Q+OG9ddTD2P3aARCuRKpPqUBvuifgSnHvQMZ6jBMqUzxhIysnb0l4c3vnnaQnvdyZ1OW9tKxcdEHMGTb67uOw== integrity sha512-8Q+OG9ddTD2P3aARCuRKpPqUBvuifgSnHvQMZ6jBMqUzxhIysnb0l4c3vnnaQnvdyZ1OW9tKxcdEHMGTb67uOw==
"@rbxts/types@^1.0.537":
version "1.0.709"
resolved "https://registry.yarnpkg.com/@rbxts/types/-/types-1.0.709.tgz#645bd5547ccebed748c167e1c43d3ff62a788db3"
integrity sha512-lvglSXxGNSNgZNvccnh70USvhSn6yYO+yQTA4m0ePjNjyJ8DueVLfuT5Ge0NDFYOlTtx1vJuxd2wlFqCBJAXVw==
"@rbxts/types@^1.0.707": "@rbxts/types@^1.0.707":
version "1.0.707" version "1.0.707"
resolved "https://registry.yarnpkg.com/@rbxts/types/-/types-1.0.707.tgz#8007f5eb0f0368ec25ff1c4d313bd80c30bbed33" resolved "https://registry.yarnpkg.com/@rbxts/types/-/types-1.0.707.tgz#8007f5eb0f0368ec25ff1c4d313bd80c30bbed33"