InputHandler completed, compilation errors fixed
This commit is contained in:
parent
f48eff5f67
commit
1564575a7f
5 changed files with 110 additions and 75 deletions
|
@ -3,7 +3,7 @@ export function bindToServerMessage(functionToBind: Callback) {
|
||||||
assert(Output?.IsA("RemoteEvent"), 'Remote event "Input" is of incorrect class or nil');
|
assert(Output?.IsA("RemoteEvent"), 'Remote event "Input" is of incorrect class or nil');
|
||||||
Output.OnClientEvent.Connect(functionToBind);
|
Output.OnClientEvent.Connect(functionToBind);
|
||||||
}
|
}
|
||||||
export function messageServer(messageType: clientMessageType, messageContent?: unknown) {
|
export function messageServer(messageType: string, messageContent?: unknown) {
|
||||||
assert(Input?.IsA("RemoteEvent"), 'Remote event "Output" is of incorrect class or nil');
|
assert(Input?.IsA("RemoteEvent"), 'Remote event "Output" is of incorrect class or nil');
|
||||||
Input.FireServer(messageType, messageContent);
|
Input.FireServer(messageType, messageContent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,28 +5,49 @@ const Workspace = game.GetService("Workspace");
|
||||||
const CAMERA = Workspace.CurrentCamera as Camera;
|
const CAMERA = Workspace.CurrentCamera as Camera;
|
||||||
assert(CAMERA, 'Camera of "' + Players.LocalPlayer.DisplayName + '"does not exist! (HOW???)');
|
assert(CAMERA, 'Camera of "' + Players.LocalPlayer.DisplayName + '"does not exist! (HOW???)');
|
||||||
|
|
||||||
export type inputBindings = {
|
function enumTypeIs<EnumAsType>(value: unknown, EnumAsObject: Enum): value is EnumAsType {
|
||||||
[input in keyof controlBindings]?: [((argument1?: unknown, argument2?: unknown) => void), unknown, unknown];
|
if (typeIs(value, "EnumItem")) {
|
||||||
};
|
return value.Name in EnumAsObject
|
||||||
|
} else {
|
||||||
export interface inputBinder {
|
return false
|
||||||
assignControlBindings: (controlBindings: controlBindings) => void;
|
}
|
||||||
assignInputBindings: (inputBindings: inputBindings) => void;
|
}
|
||||||
removeInputBindings: (inputBindings: inputBindings) => void;
|
type validInput = Enum.KeyCode // + Include controller "keys"
|
||||||
}
|
function isValidInput(value: unknown): value is validInput {
|
||||||
|
return enumTypeIs<Enum.KeyCode>(value, Enum.KeyCode)
|
||||||
interface inputHandler extends inputBinder {
|
}
|
||||||
controlHandler: (actionName: string, state: Enum.UserInputState, inputObject: InputObject) => void;
|
const actionAssignmentsReference: string[] = [
|
||||||
controlBindings?: controlBindings
|
"clicker1", // What is used to click on things (enemies in game, UI elements)
|
||||||
boundInputs: inputBindings
|
"diamond1", // Diamond controls
|
||||||
storedInput?: string // + compound inputs
|
"diamond2",
|
||||||
|
"diamond3",
|
||||||
|
"diamond4",
|
||||||
|
"special1", // Special controls
|
||||||
|
"special2",
|
||||||
|
]
|
||||||
|
export interface actionAssignments { // Based on the reference array
|
||||||
|
clicker1?: validInput; // What is used to click on things (enemies in game, UI elements)
|
||||||
|
diamond1?: validInput; // Diamond controls
|
||||||
|
diamond2?: validInput;
|
||||||
|
diamond3?: validInput;
|
||||||
|
diamond4?: validInput;
|
||||||
|
special1?: validInput; // Special controls
|
||||||
|
special2?: validInput;
|
||||||
|
}
|
||||||
|
type action = keyof actionAssignments
|
||||||
|
function isValidAction(value: string): value is keyof actionAssignments {
|
||||||
|
return value in actionAssignmentsReference; // uh oh
|
||||||
|
}
|
||||||
|
type actionBinding = [action, ((actionName?: string, state?: Enum.UserInputState, inputObject?: InputObject) => void)];
|
||||||
|
type unknownTable = {[numberKey: number]: unknown, [stringKey: string]: unknown}
|
||||||
|
export function isUnknownTable(thing: unknown): thing is unknownTable {
|
||||||
|
return typeIs(thing, "table")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMouseLocation(filterDescendantsInstances: any[]): [Vector3, Vector3, Instance | undefined] { // May be unnecessary
|
||||||
const hitParams = new RaycastParams();
|
const hitParams = new RaycastParams();
|
||||||
//hitParams.FilterDescendantsInstances = {efFolder,Plr.Character}
|
|
||||||
hitParams.FilterType = Enum.RaycastFilterType.Blacklist;
|
hitParams.FilterType = Enum.RaycastFilterType.Blacklist;
|
||||||
function getMouseLocation(): [Vector3, Vector3, Instance | undefined] {
|
hitParams.FilterDescendantsInstances = filterDescendantsInstances
|
||||||
//hitParams.FilterDescendantsInstances = {efFolder,Plr.Character}
|
|
||||||
const mouseLocation = UserInputService.GetMouseLocation();
|
const mouseLocation = UserInputService.GetMouseLocation();
|
||||||
const unitRay = CAMERA.ViewportPointToRay(mouseLocation.X, mouseLocation.Y);
|
const unitRay = CAMERA.ViewportPointToRay(mouseLocation.X, mouseLocation.Y);
|
||||||
const cast = Workspace.Raycast(unitRay.Origin, unitRay.Direction.mul(1000), hitParams);
|
const cast = Workspace.Raycast(unitRay.Origin, unitRay.Direction.mul(1000), hitParams);
|
||||||
|
@ -37,51 +58,65 @@ function getMouseLocation(): [Vector3, Vector3, Instance | undefined] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidInput(controlBindings: controlBindings, value: string): value is keyof controlBindings {
|
export function translateInputState(state: any) {
|
||||||
return value in controlBindings; // uh oh
|
if (enumTypeIs<Enum.UserInputState>(state, Enum.UserInputState)) {
|
||||||
|
// + Translate to simple boolean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//function(actionName: string, state: Enum.UserInputState, inputObject: InputObject) {
|
|
||||||
// inputParameters[0](inputParameters[1])
|
|
||||||
//}
|
|
||||||
|
|
||||||
export function makeInputHandler() {
|
export interface actionBinder {
|
||||||
const t: inputHandler = {//return {
|
assignInputsToActions: (actionAssignments: unknownTable) => void; // The client gets these from the server (the player saves them to datastores)
|
||||||
assignControlBindings: function(controlBindings: controlBindings) {
|
bindFunctionsToActions: (actionBindings: actionBinding[]) => void;
|
||||||
this.controlBindings = controlBindings // WOW!!!!!
|
unbindFunctionsFromActions: (actions: action[]) => void;
|
||||||
},
|
|
||||||
assignInputBindings: function(inputBindings: inputBindings) {
|
|
||||||
const controlBindings = this.controlBindings;
|
|
||||||
if (controlBindings) {
|
|
||||||
for (let input in inputBindings) {
|
|
||||||
if (isValidInput(controlBindings, input)) {
|
|
||||||
// + Check for this.boundInputs[input]
|
|
||||||
const inputParameters = inputBindings[input]
|
|
||||||
if (inputParameters) {
|
|
||||||
this.boundInputs[input] = inputParameters;
|
|
||||||
const controlArray = controlBindings[input];
|
|
||||||
for (const control of controlArray) {
|
|
||||||
ContextActionService.BindAction(input, this.controlHandler, false, control)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
removeInputBindings: function(inputBindings: inputBindings) {},
|
|
||||||
controlHandler: function(actionName: string, state: Enum.UserInputState, inputObject: InputObject) {
|
|
||||||
const controlBindings = this.controlBindings;
|
|
||||||
if (controlBindings) {
|
|
||||||
if (isValidInput(controlBindings, actionName)) {
|
|
||||||
const inputParameters = this.boundInputs[actionName]
|
|
||||||
if (inputParameters) {
|
|
||||||
inputParameters[0](inputParameters[1], inputParameters[2])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
boundInputs: {}
|
class actionHandler implements actionBinder { // + Needs a semaphore if concurrency issues arise
|
||||||
} //as inputHandler;
|
constructor() {
|
||||||
|
// Fortnite
|
||||||
|
}
|
||||||
|
assignInputsToActions(actionAssignments: unknownTable) {
|
||||||
|
let newActionAssignments: actionAssignments = {}
|
||||||
|
actionAssignmentsReference.forEach(action => {
|
||||||
|
const input: unknown = actionAssignments[action]
|
||||||
|
if (isValidAction(action) && isValidInput(input)) {
|
||||||
|
newActionAssignments[action] = input
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
bindFunctionsToActions(actionBindings: actionBinding[]) {
|
||||||
|
const actionAssignments = this.actionAssignments;
|
||||||
|
const boundActions = this.boundActions;
|
||||||
|
if (actionAssignments) {
|
||||||
|
actionBindings.forEach(actionBinding => {
|
||||||
|
const action = actionBinding[0]
|
||||||
|
const input = actionAssignments[action];
|
||||||
|
if (!boundActions[action] && input) {
|
||||||
|
boundActions[action] = true;
|
||||||
|
ContextActionService.BindAction(action, actionBinding[1], false, input);
|
||||||
|
} else {
|
||||||
|
// ???
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unbindFunctionsFromActions(actions: action[]) {
|
||||||
|
const boundActions = this.boundActions
|
||||||
|
actions.forEach(action => {
|
||||||
|
if (boundActions[action]) {
|
||||||
|
boundActions[action] = undefined;
|
||||||
|
ContextActionService.UnbindAction(action);
|
||||||
|
} else {
|
||||||
|
// ???
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
actionAssignments?: actionAssignments;
|
||||||
|
boundActions: {[action: string]: boolean | undefined} = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function makeActionBinder(): actionBinder {
|
||||||
|
return new actionHandler();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
function handleInput(input: InputObject, otherInteraction: boolean) {
|
function handleInput(input: InputObject, otherInteraction: boolean) {
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
|
||||||
|
interface modeLocal {
|
||||||
|
//aura?: [effectEntry, bodyPart?, number?][]; // effect, part it is attached to (default root), how many times it should be called per frame (default 1)
|
||||||
|
}
|
||||||
export const gamer: { [modeId: string]: modeLocal } = {
|
export const gamer: { [modeId: string]: modeLocal } = {
|
||||||
["Flawless"]: {
|
["Flawless"]: {
|
||||||
//aura: [[["Ball"]]], // Will come back to this later
|
//aura: [[["Ball"]]], // Will come back to this later
|
||||||
|
|
|
@ -4,6 +4,7 @@ const RunService = game.GetService("RunService");
|
||||||
import { bindToServerMessage, messageServer } from "./ClientMessenger";
|
import { bindToServerMessage, messageServer } from "./ClientMessenger";
|
||||||
import { handleGuiInput, drawGui, closeGui } from "./GuiHandler";
|
import { handleGuiInput, drawGui, closeGui } from "./GuiHandler";
|
||||||
import { makeEffectRunner, effectRunner } from "./EffectMaker";
|
import { makeEffectRunner, effectRunner } from "./EffectMaker";
|
||||||
|
import { makeActionBinder, actionBinder, isUnknownTable } from "./InputHandler";
|
||||||
const LOCALPLAYER = Players.LocalPlayer;
|
const LOCALPLAYER = Players.LocalPlayer;
|
||||||
const PLAYERGUI = LOCALPLAYER.WaitForChild("PlayerGui", 1) as PlayerGui;
|
const PLAYERGUI = LOCALPLAYER.WaitForChild("PlayerGui", 1) as PlayerGui;
|
||||||
assert(
|
assert(
|
||||||
|
@ -18,7 +19,7 @@ function openMainMenu(playerGui: PlayerGui) {
|
||||||
for (const mainMenuButton of mainMenuButtons) {
|
for (const mainMenuButton of mainMenuButtons) {
|
||||||
mainMenuButton[0].Activated.Connect(function () {
|
mainMenuButton[0].Activated.Connect(function () {
|
||||||
handleGuiInput(messageServer, mainMenuButton[1][0], mainMenuButton[1][1]);
|
handleGuiInput(messageServer, mainMenuButton[1][0], mainMenuButton[1][1]);
|
||||||
}); // + Good ETC extension - Add support for other controller types
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +30,14 @@ function handleServerMessage(messageType: unknown, messageContent: unknown) {
|
||||||
} else if (messageType === "enterGame") {
|
} else if (messageType === "enterGame") {
|
||||||
closeGui(PLAYERGUI, "MainMenu");
|
closeGui(PLAYERGUI, "MainMenu");
|
||||||
inMainMenu = false;
|
inMainMenu = false;
|
||||||
|
} else if (messageType === "bindActions") {
|
||||||
|
if (isUnknownTable(messageContent)) {
|
||||||
|
mainActionBinder.assignInputsToActions(messageContent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Bind functions
|
// Bind functions
|
||||||
|
|
||||||
bindToServerMessage(handleServerMessage);
|
|
||||||
|
|
||||||
const effectRunners: effectRunner[] = [];
|
const effectRunners: effectRunner[] = [];
|
||||||
// + Put stuff in the effectRunners table
|
// + Put stuff in the effectRunners table
|
||||||
|
@ -42,3 +46,7 @@ RunService.RenderStepped.Connect(function(deltaTime) {
|
||||||
effectRunner.runEffects(deltaTime)
|
effectRunner.runEffects(deltaTime)
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const mainActionBinder: actionBinder = makeActionBinder()
|
||||||
|
|
||||||
|
bindToServerMessage(handleServerMessage);
|
12
src/services.d.ts
vendored
12
src/services.d.ts
vendored
|
@ -8,20 +8,8 @@ type meshType = "Ball";
|
||||||
type effectState = [CFrame, Vector3, Color3, number]; // The number is transparency
|
type effectState = [CFrame, Vector3, Color3, number]; // The number is transparency
|
||||||
type effectEntry = [meshType, EnumItem, effectState[]]; // The enumitem is material
|
type effectEntry = [meshType, EnumItem, effectState[]]; // The enumitem is material
|
||||||
|
|
||||||
interface modeLocal {
|
|
||||||
aura?: [effectEntry, bodyPart?, number?][]; // effect, part it is attached to (default root), how many times it should be called per frame (default 1)
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
// Genuinely require being on both sides - but in the services file? No shot!
|
// Genuinely require being on both sides - but in the services file? No shot!
|
||||||
type acceptedControls = Enum.KeyCode[] // + Include controller "keys"
|
|
||||||
interface controlBindings {
|
|
||||||
clicker1: acceptedControls; // What is used to click on things (enemies in game, UI elements)
|
|
||||||
diamond1: acceptedControls; // Diamond controls
|
|
||||||
diamond2: acceptedControls;
|
|
||||||
diamond3: acceptedControls;
|
|
||||||
diamond4: acceptedControls;
|
|
||||||
special1: acceptedControls; // Special controls
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*interface hookInEntry {
|
/*interface hookInEntry {
|
||||||
|
|
Loading…
Reference in a new issue