Merge pull request #46 from penolakushari/master

Contributions from vlazed - Angle snapping fix + Gizmo multiplayer sync fix
This commit is contained in:
penolakushari 2024-08-21 00:45:57 +03:00 committed by GitHub
commit 26fe139c6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 69 additions and 38 deletions

View File

@ -5,6 +5,8 @@
resource.AddSingleFile("resource/localization/en/ragdollmover_tools.properties")
local MAX_EDICT_BITS = 13
local TYPE_ENTITY = 1
local TYPE_NUMBER = 2
local TYPE_VECTOR = 3
@ -74,7 +76,7 @@ function RAGDOLLMOVER.Sync(pl, ...)
local Type = string.lower(type(val))
if Type == "entity" then
net.WriteUInt(TYPE_ENTITY, 3)
net.WriteEntity(val)
net.WriteUInt(val:EntIndex(), MAX_EDICT_BITS)
elseif Type == "number" then
net.WriteUInt(TYPE_NUMBER, 3)
net.WriteFloat(val)
@ -157,7 +159,9 @@ elseif CLIENT then
net.Receive("RAGDOLLMOVER_META", function(len) -- rgmSync
local pl = LocalPlayer()
if not RAGDOLLMOVER[pl] then RAGDOLLMOVER[pl] = {} end
-- See edge case explanation below
if IsValid(pl) and not RAGDOLLMOVER[pl] then RAGDOLLMOVER[pl] = {} end
local count = net.ReadInt(4)
@ -167,7 +171,8 @@ net.Receive("RAGDOLLMOVER_META", function(len) -- rgmSync
local type = net.ReadUInt(3)
local value = nil
if type == TYPE_ENTITY then
value = net.ReadEntity()
-- Read the entity index instead of the entity itself, so we can do our own validation step later
value = net.ReadUInt(MAX_EDICT_BITS)
elseif type == TYPE_NUMBER then
value = net.ReadFloat()
elseif type == TYPE_VECTOR then
@ -177,7 +182,24 @@ net.Receive("RAGDOLLMOVER_META", function(len) -- rgmSync
elseif type == TYPE_BOOL then
value = net.ReadBit() == 1
end
RAGDOLLMOVER[pl][name] = value
-- Sometimes, entities are not available during startup in multiplayer.
if type == TYPE_ENTITY then
timer.Create("RAGDOLLMOVER_VALIDATE_ENTITY", 0.1, 10, function()
-- Edge case: If ragdollmover is already deployed on the player in the server, then the net.Receive callback calls,
-- but the local player is not initialized. We can initialize pl here and also set the RAGDOLLMOVER[pl]
-- table
pl = LocalPlayer()
if not RAGDOLLMOVER[pl] then RAGDOLLMOVER[pl] = {} end
if IsValid(Entity(value)) and IsValid(pl) then
RAGDOLLMOVER[pl][name] = Entity(value)
timer.Remove("RAGDOLLMOVER_VALIDATE_ENTITY")
end
end)
else
RAGDOLLMOVER[pl][name] = value
end
end
end)

View File

@ -654,36 +654,51 @@ do
return result
end
local mfmod = math.fmod
local snapAngle do
local accumulated = 0
local lastStartAngle = 0
local oldLocalAngle = 0
local function snapAngle(localized, startangle, snapamount)
local localAng = mfmod(localized.y, 360)
if localAng > 181 then localAng = localAng - 360 end
if localAng < -181 then localAng = localAng + 360 end
local floor = math.floor
local ceil = math.ceil
local localStart = mfmod(startangle.y, 360)
if localStart > 181 then localStart = localStart - 360 end
if localStart < -181 then localStart = localStart + 360 end
-- Accumulate delta angles per frame until startangle is different (stopped rotating)
-- Allows for correct snapped angles set by the rotation delta
function snapAngle(localized, startangle, snapamount, nonphys)
local localAng = localized.y
if lastStartAngle ~= startangle.y then
accumulated = 0
oldLocalAngle = localAng
lastStartAngle = startangle.y
end
local diff = mfmod(localStart - localAng, 360)
if diff > 181 then diff = diff - 360 end
if diff < -181 then diff = diff + 360 end
-- https://discussions.unity.com/t/can-i-read-from-a-rotation-that-doesnt-wrap-from-360-to-zero/621621/7
while (localAng < oldLocalAngle - 180) do
localAng = localAng + 360
end
while (localAng > oldLocalAngle + 180) do
localAng = localAng - 360
end
-- TODO:
-- Workaround to rotating by 180 degrees by removing normalization step
-- Still buggy, but allows rotating beyond 180 degrees
if snapamount == 180 then
diff = mfmod(localStart - localAng, 360)
local delta = oldLocalAngle - localAng
accumulated = accumulated + delta
oldLocalAngle = localAng
local mathfunc = nil
if accumulated >= 0 then
mathfunc = floor
else
mathfunc = ceil
end
if nonphys then
return -mathfunc(accumulated / snapamount) * snapamount
else
return startangle.y - (mathfunc(accumulated / snapamount) * snapamount)
end
end
local mathfunc = nil
if diff >= 0 then
mathfunc = math.floor
else
mathfunc = math.ceil
end
return startangle.y - (mathfunc(diff / snapamount) * snapamount)
end
function disc:ProcessMovement(_, offang, eyepos, eyeang, ent, bone, ppos, pnorm, movetype, snapamount, startangle, _, nphysangle) -- initially i had a table instead of separate things for initial bone pos and angle, but sync command can't handle tables and i thought implementing a way to handle those would be too much hassle
@ -778,14 +793,7 @@ do
local rotationangle = localized.y
if snapamount ~= 0 then
local localAng = mfmod(localized.y, 360)
if localAng > 181 then localAng = localAng - 360 end
if localAng < -181 then localAng = localAng + 360 end
local mathfunc = math.floor
if localAng < 0 then mathfunc = math.ceil end
rotationangle = mathfunc(localAng / snapamount) * snapamount
rotationangle = snapAngle(localized, startangle, snapamount, true)
end
if self.axistype == 4 then

View File

@ -2720,7 +2720,8 @@ local RGM_NOTIFY = { -- table with info for messages, true for errors
[BONE_UNFROZEN] = false,
}
local pl
-- If we hotload this file, pl gets set to nil, which causes issues when tables attempt to index with this variable; initialize it here
local pl = LocalPlayer()
hook.Add("InitPostEntity", "rgmSetPlayer", function()
pl = LocalPlayer()