Server character restructure

This commit is contained in:
2024-04-20 15:05:43 -04:00
parent 4baf7bff51
commit b82606d64c
21 changed files with 2 additions and 2 deletions

View File

@@ -1,81 +0,0 @@
--!optimize 2
--!native
--!strict
type EventFunction = (KeyPressed: Enum.KeyCode) -> ()
type ActionsTCP = RBXScriptConnection
type LocalPlayer = Player
type TCP = RemoteEvent
type EventsDict = {
[Enum.KeyCode]: EventFunction
}
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
Add: (self: ClassConstructor, Key: Enum.KeyCode, f: EventFunction) -> (),
Remove: (self: ClassConstructor, Key: Enum.KeyCode) -> ()
} & Impl_Static_Props
type Constructor_Fun = (LocalPlayer: LocalPlayer) -> ClassConstructor
type Impl_Static_Props = {}
type Constructor_Return_Props = {
Events: EventsDict,
CurrentActionsTCP_Event: ActionsTCP?
}
local Actions = {} :: Impl_Constructor
Actions.__index = Actions
local CharacterShared = _G.include(script, "CharacterShared")
local Remote = Instance.new("RemoteEvent") :: TCP
Remote.Name = "Actions"
Remote.Parent = CharacterShared
local ActionsTCP_Event: ActionsTCP?
function Actions.constructor(LocalPlayer: LocalPlayer)
local Events: EventsDict = {}
if ActionsTCP_Event then
warn("[Server Actions]: TCP event was already created, duplicating...", debug.traceback())
end
ActionsTCP_Event = Remote.OnServerEvent:Connect(function(Messenger: Player, Key: Enum.KeyCode)
if Messenger.UserId == LocalPlayer.UserId then
if typeof(Key) == "EnumItem" then
local switch = Events[Key]
if switch then
switch(Key)
end
else
warn(`[Server Actions]: Got an unknown type, Key="{typeof(Key)}" Value="{Key}" from: "{Messenger.Name}"`)
end
else
Messenger:Kick(`"{Messenger.Name}", {Messenger.UserId} r="{Remote.Name}", 1="{tostring(Key)}"`)
end
end)
return setmetatable({
Events = Events,
CurrentActionsTCP_Event = ActionsTCP_Event
}, Actions)
end
function Actions:Add(Key: Enum.KeyCode, f: EventFunction)
self.Events[Key] = f
end
function Actions:Remove(Key: Enum.KeyCode)
self.Events[Key] = nil
if not next(self.Events) then
(self.CurrentActionsTCP_Event :: ActionsTCP):Disconnect()
print("[Server Actions]: ")
end
end
return Actions

View File

@@ -1,124 +0,0 @@
--!optimize 2
--!native
--!strict
type UDP = UnreliableRemoteEvent
type FlashlightUDP = RBXScriptConnection
type LocalPlayer = Player
type HumanoidRootPart = BasePart
type EulerXYZ_struct = {number}
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
On: (self: ClassConstructor) -> (),
Off: (self: ClassConstructor) -> (),
Toggle: (self: ClassConstructor) -> ()
} & Impl_Static_Props
type Constructor_Fun = (LocalPlayer: LocalPlayer, HumanoidRootPart: HumanoidRootPart) -> ClassConstructor
type Impl_Static_Props = {
Enabled: boolean,
HeadHeight: number
}
type Constructor_Return_Props = {
FlashlightPart: Part,
SpotLight: SpotLight,
ToggleSound: Sound
}
local Flashlight = {} :: Impl_Constructor
Flashlight.__index = Flashlight
Flashlight.Enabled = false
Flashlight.HeadHeight = 1
local CharacterShared = _G.include(script, "CharacterShared")
local Flashlight_UDP = Instance.new("UnreliableRemoteEvent") :: UDP
Flashlight_UDP.Name = "Flashlight"
Flashlight_UDP.Parent = CharacterShared
local FlashlightUDP_Event: FlashlightUDP?
local function FlashlightPart(HumanoidRootPart: HumanoidRootPart): (Part, SpotLight, Sound)
local FlashlightPart = Instance.new("Part") :: Part
FlashlightPart.Size = Vector3.new(.1,.1,.1)
FlashlightPart.CFrame = HumanoidRootPart.CFrame+Vector3.yAxis
FlashlightPart.CanCollide = false
FlashlightPart.CastShadow = false
FlashlightPart.Anchored = true
FlashlightPart.Transparency = 1
local SpotLight = Instance.new("SpotLight") :: SpotLight
SpotLight.Color = Color3.new(1,1,1)
SpotLight.Angle = 80
SpotLight.Range = 30
SpotLight.Brightness = 2
SpotLight.Shadows = true
SpotLight.Enabled = false
SpotLight.Parent = FlashlightPart
local ToggleSound = Instance.new("Sound") :: Sound
ToggleSound.Name = "Flashlight"
ToggleSound.SoundId = "rbxassetid://16454678462"
ToggleSound.Volume = .5
ToggleSound.Parent = FlashlightPart
FlashlightPart.Parent = HumanoidRootPart
return FlashlightPart, SpotLight, ToggleSound
end
function Flashlight.constructor(LocalPlayer: LocalPlayer, HumanoidRootPart: HumanoidRootPart)
local FlashlightPart, SpotLight, ToggleSound = FlashlightPart(HumanoidRootPart)
if FlashlightUDP_Event then
warn("[Server Flashlight]: UDP event was already created, duplicating...", debug.traceback())
end
FlashlightUDP_Event = Flashlight_UDP.OnServerEvent:Connect(function(Messenger: Player, CameraEuler: EulerXYZ_struct)
if Messenger.UserId == LocalPlayer.UserId then
if CameraEuler[4] and CameraEuler[4] == 3 then
local RootPartCFrame = HumanoidRootPart.CFrame
FlashlightPart.CFrame = CFrame.new(
RootPartCFrame.X,
RootPartCFrame.Y+Flashlight.HeadHeight,
RootPartCFrame.Z)*CFrame.Angles(CameraEuler[1], CameraEuler[2], CameraEuler[3])
end
else
Messenger:Kick(`"{Messenger.Name}", {Messenger.UserId} r="{Flashlight_UDP.Name}", 1="{tostring(CameraEuler)}"`)
end
end)
return setmetatable({
FlashlightPart = FlashlightPart,
SpotLight = SpotLight,
ToggleSound = ToggleSound
}, Flashlight)
end
function Flashlight:On()
Flashlight.Enabled = true
self.ToggleSound:Play()
self.SpotLight.Enabled = Flashlight.Enabled
end
function Flashlight:Off()
Flashlight.Enabled = false
self.ToggleSound:Play()
self.SpotLight.Enabled = Flashlight.Enabled
end
function Flashlight:Toggle()
if Flashlight.Enabled then
self:Off()
else
self:On()
end
end
return Flashlight

View File

@@ -1,55 +0,0 @@
--!optimize 2
--!native
--!strict
--This really should be only client
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
PartToggle: (self: ClassConstructor, Instance: BasePart, CastingShadow: boolean) -> (),
Remove: (self: ClassConstructor, Key: Enum.KeyCode) -> (),
on: (self: ClassConstructor) -> (),
off: (self: ClassConstructor) -> ()
}
type Constructor_Fun = (Character: Character) -> ClassConstructor
type Constructor_Return_Props = {
Character: Character
}
local Shadows = {} :: Impl_Constructor
Shadows.__index = Shadows
type Character = Model
function Shadows.constructor(Character: Character)
return setmetatable({
Character = Character
}, Shadows)
end
function Shadows:PartToggle(Instance: BasePart, CastingShadow: boolean)
if Instance:IsA("BasePart") then --not 100%, but im sure types are only in effect on the editor side
Instance.CastShadow = CastingShadow
end
end
local function CharacterShadows(self: ClassConstructor, enabled: boolean)
local CharacterDescendants = self.Character:GetDescendants()
for i = 1, #CharacterDescendants do
self:PartToggle(CharacterDescendants[i] :: BasePart, enabled)
end
end
function Shadows:on()
CharacterShadows(self, true)
end
function Shadows:off()
CharacterShadows(self, false)
end
return Shadows

View File

@@ -1,102 +0,0 @@
--!optimize 2
--!native
--!strict
type Head = BasePart
type UpperTorso = BasePart
type Neck = Motor6D
type Waist = Motor6D
type NeckC0 = CFrame
type WaistC0 = CFrame
type UDP = UnreliableRemoteEvent
type struct_SpineMovement = {
Neck: CFrame,
Waist: CFrame
}
type ClassConstructor = typeof(setmetatable({} :: Constructor_Return_Props, {} :: Impl_Constructor))
type Impl_Constructor = {
__index: Impl_Constructor,
constructor: Constructor_Fun,
--Class functions
Move: (self: ClassConstructor, CameraCFrame: CFrame, IsFirstPerson: boolean) -> ()
} & Impl_Static_Props
type Constructor_Fun = (Head: Head, UpperTorso: UpperTorso) -> ClassConstructor
type Impl_Static_Props = {
Enabled: boolean,
Multiplier: number
}
type Constructor_Return_Props = {
Remote: UDP,
Head: Head,
UpperTorso: UpperTorso,
Neck: Neck,
Waist: Waist,
NeckC0: NeckC0,
WaistC0: WaistC0
}
local Spine = {} :: Impl_Constructor
Spine.__index = Spine
Spine.Enabled = true
Spine.Multiplier = .5
local Remote = Instance.new("UnreliableRemoteEvent") :: UDP
Remote.Name = "SpineStream"
Remote.Parent = _G.include(script, "CharacterShared")
function Spine.constructor(Head: Head, UpperTorso: UpperTorso)
local self = {}
self.Head = Head
self.UpperTorso = UpperTorso
self.Neck = Head:WaitForChild("Neck") :: Motor6D
self.Waist = UpperTorso:WaitForChild("Waist") :: Motor6D
self.Remote = Remote
self.NeckC0 = (self.Neck :: Motor6D).C0
self.WaistC0 = (self.Neck :: Motor6D).C0
return setmetatable(self, Spine)
end
local function SpineMovement(self: ClassConstructor, CameraCFrame: CFrame, IsFirstPerson: boolean): struct_SpineMovement
local HeadCFrame: CFrame = self.Head.CFrame
local TorsoPosition: Vector3 = self.UpperTorso.Position
local TorsoLookVector: Vector3 = self.UpperTorso.CFrame.LookVector
local HeadPosition: Vector3 = HeadCFrame.Position
local CameraPosition: Vector3 = CameraCFrame.Position
local HeadDelta: Vector3 = HeadPosition-CameraPosition
local TorsoDeltaNormal: Vector3 = (TorsoPosition-CameraPosition).Unit
local HeadDeltaNormal: Vector3 = HeadDelta.Unit
local HeadDeltaMagnitude: number = HeadDelta.Magnitude
local arc = Spine.Multiplier*math.asin(HeadDelta.Y/HeadDeltaMagnitude)
local Neck = CFrame.Angles(arc, 0, 0)
local Waist = CFrame.Angles(arc, 0, 0)
if not IsFirstPerson then
--Make this less cringe at some point, combine the dot product into the equation
local LookingAtSelf = CameraCFrame.LookVector:Dot(HeadCFrame.LookVector)<0 --Make our head face the camera if we are looking at ourself
local HeadCrossDelta = Spine.Multiplier*HeadDeltaNormal:Cross(TorsoLookVector).Y
local TorsoCrossDelta = Spine.Multiplier*TorsoDeltaNormal:Cross(TorsoLookVector).Y
Neck*=CFrame.Angles(0, HeadCrossDelta, 0)
Waist*=CFrame.Angles(0, LookingAtSelf and TorsoCrossDelta or -TorsoCrossDelta, 0)
end
return {
Neck = Neck,
Waist = Waist
}
end
function Spine:Move(CameraCFrame: CFrame, IsFirstPerson: boolean)
local SpineIK = SpineMovement(self, CameraCFrame, IsFirstPerson)
self.Neck.C0 = self.Neck.C0:Lerp(self.NeckC0*SpineIK.Neck, .9)
self.Waist.C0 = self.Waist.C0:Lerp(self.WaistC0*SpineIK.Waist, .9)
end
return Spine

View File

@@ -1,91 +0,0 @@
--!optimize 2
--!native
--!strict
type UDP = UnreliableRemoteEvent
type CharacterSharedFolder = Folder
local Players = game:GetService("Players")
local Dir = script.Parent
local Character = Dir.Parent
local preprocessor = {}
--Production--
--if not RS:IsStudio() then
task.wait()
Dir.Parent = nil
--end
--
--Create the character shared directory here
local CharacterShared = Instance.new("Folder")
CharacterShared.Name = "shared"
CharacterShared.Parent = Character
function preprocessor.CharacterShared(): Instance
return CharacterShared :: CharacterSharedFolder
end
_G.include = function(this: LuaSourceContainer, FunName: string, ...)
--its not extremely necessary to have this security on the server-side
if this:IsDescendantOf(script) then --getfenv is being removed
local switch = preprocessor[FunName]
return type(switch) == "function" and switch(...) or switch
else
warn(`Preprocessor append failed "{FunName}"`, debug.traceback())
return nil
end
end
local Shadows = require(script:WaitForChild("Shadows"))
local SpineModule = require(script:WaitForChild("SpineKinematics"))
local FlashlightModule = require(script:WaitForChild("Flashlight"))
local ActionsModule = require(script:WaitForChild("Actions"))
local Head = Character:WaitForChild("Head")
local UpperTorso = Character:WaitForChild("UpperTorso")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local LocalPlayer = Players:GetPlayerFromCharacter(Character)
local CharacterShadows = Shadows.constructor(Character)
local Spine = SpineModule.constructor(Head, UpperTorso)
local Flashlight = FlashlightModule.constructor(LocalPlayer, HumanoidRootPart)
local Actions = ActionsModule.constructor(LocalPlayer, HumanoidRootPart)
local FlashlightDebounce = false
CharacterShadows:off() --I plan having 2 player support and characters block a ton of light
Character.DescendantAdded:Connect(function(Instance)
task.wait() --Wait for the instance to properly replicate?
CharacterShadows:PartToggle(Instance, false)
end)
local FlashlightCooldown = .10
Actions:Add(Enum.KeyCode.F, function(_KeyPressed)
if not FlashlightDebounce then
Flashlight:Toggle()
FlashlightDebounce = true
task.wait(FlashlightCooldown)
FlashlightDebounce = false
end
end);
Spine.Remote.OnServerEvent:Connect(function(Messenger: Player, CameraPosition: CFrame, IsFirstPerson: boolean)
if Messenger.UserId == LocalPlayer.UserId then
if SpineModule.Enabled then
Spine:Move(CameraPosition, IsFirstPerson)
else
--reset
print("TODO reached -", script.Name..".lua")
end
else
Messenger:Kick(`"{Messenger.Name}", {Messenger.UserId} r="{Spine.Remote.Name}", 1="{tostring(CameraPosition)}", 2="{tostring(IsFirstPerson)}"`)
end
end)
_G.include = nil