seperated client and server state, input mapper

This commit is contained in:
Reid 2023-07-20 14:48:17 -07:00
parent 44f63f8deb
commit d5b77a9044
10 changed files with 104 additions and 16 deletions

View file

@ -6,7 +6,7 @@ import { Host } from "ReplicatedStorage/hosts"
import { tags } from "./boundTags"
import { Model } from "./components"
import { start as startReplication, stop as stopReplication } from "./replication"
import { State } from "./state"
import { clientState, serverState } from "./state"
import { start as startSystems, stop as stopSystems } from "./systems"
import { start as startTags, stop as stopTags } from "./tags"
@ -22,10 +22,9 @@ let connections:
}
| undefined
export function start(host: Host): [World, State] {
export function start<S extends object>(host: Host, state: S): [World, S] {
if (connections) throw "ECS already running."
const state: State = new State()
const world = new World()
const debug = new Debugger(Plasma)
debug.authorize = authorize
@ -46,11 +45,15 @@ export function start(host: Host): [World, State] {
})
if (host === Host.All || host === Host.Server) {
const _ServerState = state as serverState
startTags(world, tags)
}
if (host === Host.All || host === Host.Client) {
startReplication(world, state)
const ClientState = state as clientState
startReplication(world, ClientState)
const serverDebugger = ReplicatedStorage.FindFirstChild("MatterDebugger")
if (serverDebugger && serverDebugger.IsA("ScreenGui")) {
@ -65,7 +68,7 @@ export function start(host: Host): [World, State] {
UserInputService.InputBegan.Connect((input) => {
if (input.KeyCode === Enum.KeyCode.F4 && authorize(Players.LocalPlayer)) {
debug.toggle()
state.debugEnabled = debug.enabled
ClientState.debugEnabled = debug.enabled
}
})
}

View file

@ -1,7 +1,7 @@
import { AnyEntity, World } from "@rbxts/matter"
import { waitForEvent } from "ReplicatedStorage/remotes"
import * as Components from "./components"
import { State } from "./state"
import { clientState } from "./state"
type ComponentNames = keyof typeof Components
type ComponentConstructors = (typeof Components)[ComponentNames]
@ -16,13 +16,13 @@ let connection: RBXScriptConnection | undefined
* Starts the replication receiver.
*
* @param world - The world to replicate components in
* @param state - The global state for the ECS
* @param ClientState - The client state for the ECS
*/
export function start(world: World, state: State): void {
export function start(world: World, ClientState: clientState): void {
if (connection) return
function debugPrint(message: string, args: () => (string | number)[]): void {
if (state.debugEnabled) {
if (ClientState.debugEnabled) {
print("ECS Replication>", string.format(message, ...args()))
}
}

View file

@ -1,8 +1,21 @@
/* eslint-disable roblox-ts/no-private-identifier */
import { InputKind } from "ReplicatedStorage/inputKind"
/**
* The global ECS state.
* The client ECS state.
*/
export class State {
export class clientState {
[index: string]: unknown,
// eslint-disable-next-line roblox-ts/no-private-identifier
debugEnabled = false
isJumping = false
isRunning = false
lastProcessedCommand?: InputKind
}
/**
* The server ECS state.
*/
export class serverState {
[index: string]: unknown
}

View file

@ -0,0 +1,44 @@
import { useDeltaTime, useEvent, useThrottle, World } from "@rbxts/matter"
import { UserInputService } from "@rbxts/services"
import { clientState } from "ReplicatedStorage/ecs/state"
import { InputKind } from "ReplicatedStorage/inputKind"
let holdDuration = 0
function inputMapper(_: World, client: clientState): void {
for (const [, input, gpe] of useEvent(UserInputService, "InputBegan")) {
if (gpe) return undefined
if (input.KeyCode !== Enum.KeyCode.Unknown) {
client.lastProcessedCommand = InputKind.KeyDown(input.KeyCode)
} else if (input.UserInputType === Enum.UserInputType.MouseButton1) {
if (useThrottle(0.5)) {
client.lastProcessedCommand = InputKind.PointerClick
return undefined
}
client.lastProcessedCommand = InputKind.DoubleClick
}
return undefined
}
for (const [, input, gpe] of useEvent(UserInputService, "InputEnded")) {
if (gpe) return undefined
if (input.KeyCode !== Enum.KeyCode.Unknown) {
client.lastProcessedCommand = InputKind.KeyUp(input.KeyCode)
} else if (input.UserInputType === Enum.UserInputType.MouseButton1) {
client.lastProcessedCommand = InputKind.HoldRelease
}
return undefined
}
if (UserInputService.IsMouseButtonPressed(Enum.UserInputType.MouseButton1)) {
holdDuration += useDeltaTime()
client.lastProcessedCommand = InputKind.Hold(holdDuration)
return
}
holdDuration = 0
client.lastProcessedCommand = undefined
return
}
export = inputMapper

View file

@ -0,0 +1,16 @@
import variantModule, { TypeNames, VariantOf } from "@rbxts/variant"
export const InputKind = variantModule({
// Sub-messages
KeyDown: (key: Enum.KeyCode) => ({ key }),
KeyUp: (key: Enum.KeyCode) => ({ key }),
Hold: (duration: number) => ({ duration }),
// Messages
HoldRelease: {},
DoubleClick: {},
PointerMove: {},
PointerClick: {}
})
export type InputKind<T extends TypeNames<typeof InputKind> = undefined> = VariantOf<typeof InputKind, T>