teverse/core/archived/client/characterController.lua

182 lines
4.6 KiB
Lua

--[[
Copyright 2020 Teverse
@File core/client/characterController.lua
@Author(s) Jay
--]]
print("loading chars")
local controller = {}
-- set to false for debugging purposes.
local CLIENT_PREDICTION = false
controller.character = nil -- server creates this
controller.camera = require("tevgit:core/client/cameraController.lua")
local forward = quaternion:setEuler(0, controller.camera.cameraRotation:getEuler().y, 0)
local function setupCharacterLocally(client, char)
local nameTag = engine.construct("guiTextBox", engine.interface, {
name = client.id,
size = guiCoord(0, 100, 0, 16),
align = enums.align.middle,
text = client.name,
textColour = colour(1, 1, 1),
backgroundAlpha = 0,
fontSize = 16,
fontFile = "local:moskBold.ttf"
})
workspace.camera:onSync("changed", function()
local inFrontOfCamera, screenPos = workspace.camera:worldToScreen(char.position + vector3(0,char.size.y/2,0))
if inFrontOfCamera then
nameTag.visible = true
nameTag.position = guiCoord(0, screenPos.x - 50, 0, screenPos.y)
else
nameTag.visible = false
end
end)
end
local function characterSpawnedHandler(newClientId)
print('waiting for mne')
repeat wait() until engine.networking.me
if engine.networking.me.id == newClientId then
print("Waiting for my character")
repeat wait() until workspace[engine.networking.me.id]
print('GOT my CHAR')
controller.character = workspace[engine.networking.me.id]
setupCharacterLocally(engine.networking.me, controller.character)
print('set up')
-- controller.character.physics=false
if controller.camera then
-- controller.character.opacity = 0
--controller.camera.camera.position = vector3(0,90,0)
--controller.camera.camera:lookAt(vector3(0,0,0))
controller.camera.setTarget(controller.character)
end
else
print("Waiting for other character")
repeat wait() until workspace[newClientId]
print("got other character")
local client = engine.networking.clients:getClientFromId(newClientId)
setupCharacterLocally(client, workspace[newClientId])
end
end
engine.networking.clients:clientConnected(function (client)
characterSpawnedHandler(client.id)
end)
for _,v in pairs(engine.networking.clients.children)do
characterSpawnedHandler(v.id)
end
controller.keyBinds = {
[enums.key.w] = 1,
[enums.key.up] = 1,
[enums.key.s] = 2,
[enums.key.down] = 2,
[enums.key.a] = 3,
[enums.key.left] = 3,
[enums.key.d] = 4,
[enums.key.right] = 4,
[enums.key.space] = 5
}
controller.keyBindsDir = {
vector3(0,0,1), --w
vector3(0,0,-1), --s
vector3(-1,0,0), --a
vector3(1,0,0) -- d
}
controller.keys = {
false,
false,
false,
false,
false
}
local isPredicting = false
local updatePrediction = function()
local totalForce = vector3()
local moved = false
for i, pressed in pairs(controller.keys) do
if pressed then
moved=true
totalForce = totalForce + (forward * controller.keyBindsDir[i])
end
end
if CLIENT_PREDICTION and moved then
--controller.character:applyImpulse(totalForce * 10)
local f = totalForce*10
f.y = controller.character.linearVelocity.y
local lv = vector3(f.x, 0, f.z)
if lv ~= vector3(0,0,0) then
print(lv)
controller.character.rotation = quaternion:setLookRotation(lv:normal())
end
controller.character.linearVelocity = f
end
return moved
end
-- The purpose of this function is to predict how the server will move the character
-- based on the input we send.
local function predictServerMovementOnClient(direction)
if not controller.character then return end
if direction == 5 then
controller.character:applyImpulse(0,300,0)
return nil
elseif controller.keys[direction] == nil then
return nil
end
controller.keys[direction] = true
if not isPredicting then
isPredicting = true
print("Predicting")
engine.graphics:onSync("frameDrawn",function()
if not updatePrediction() then
print("Ending prediction")
isPredicting =false
self:disconnect() -- no input from user.
end
end)
end
end
engine.input:keyPressed(function (inputObj)
if controller.keyBinds[inputObj.key] then
forward = quaternion:setEuler(0, controller.camera.cameraRotation:getEuler().y + math.rad(180), 0)
if CLIENT_PREDICTION then
predictServerMovementOnClient(controller.keyBinds[inputObj.key])
end
engine.networking:toServer("characterSetInputStarted", controller.keyBinds[inputObj.key], controller.camera.cameraRotation)
end
end)
engine.input:keyReleased(function (inputObj)
if controller.keyBinds[inputObj.key] then
engine.networking:toServer("characterSetInputEnded", controller.keyBinds[inputObj.key])
controller.keys[controller.keyBinds[inputObj.key]] = false
end
end)
return controller