dobrograd-13-06-2022/garrysmod/addons/feature-wire/lua/wire/wire_paths.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

108 lines
2.9 KiB
Lua

-- wire_paths.lua
--
-- This file implements syncing of wire paths, which are the visual
-- component of wires.
--
-- Conceptually, a wire path has a material, a color, and a non-zero width, as
-- well as as a non-empty polyline along the wire. (Each point in the line
-- has both a parent entity, and a local offset from that entity.)
--
if not WireLib then return end
if CLIENT then
net.Receive("WireLib.Paths.TransmitPath", function(length)
local path = {
Path = {}
}
path.Entity = net.ReadEntity()
if not path.Entity:IsValid() then return end
path.Name = net.ReadString()
path.Width = net.ReadFloat()
if path.Width<=0 then
if path.Entity.WirePaths then
path.Entity.WirePaths[path.Name] = nil
end
return
end
path.StartPos = net.ReadVector()
path.Material = net.ReadString()
path.Color = net.ReadColor()
local num_points = net.ReadUInt(16)
for i = 1, num_points do
path.Path[i] = { Entity = net.ReadEntity(), Pos = net.ReadVector() }
end
if path.Entity.WirePaths == nil then path.Entity.WirePaths = {} end
path.Entity.WirePaths[path.Name] = path
end)
return
end
WireLib.Paths = {}
local transmit_queues = setmetatable({}, { __index = function(t,p) t[p] = {} return t[p] end })
util.AddNetworkString("WireLib.Paths.RequestPaths")
util.AddNetworkString("WireLib.Paths.TransmitPath")
net.Receive("WireLib.Paths.RequestPaths", function(length, ply)
local ent = net.ReadEntity()
if ent:IsValid() and ent.Inputs then
for name, input in pairs(ent.Inputs) do
if input.Src then
WireLib.Paths.Add(input, ply)
end
end
end
end)
local function TransmitPath(input, ply)
net.Start("WireLib.Paths.TransmitPath")
local color = input.Color
net.WriteEntity(input.Entity)
net.WriteString(input.Name)
if not input.Src or input.Width<=0 then
net.WriteFloat(0)
else
net.WriteFloat(input.Width)
net.WriteVector(input.StartPos)
net.WriteString(input.Material)
net.WriteColor(Color(color.r or 255, color.g or 255, color.b or 255, color.a or 255))
net.WriteUInt(#input.Path, 16)
for _, point in ipairs(input.Path) do
net.WriteEntity(point.Entity)
net.WriteVector(point.Pos)
end
end
net.Send(ply)
end
local function ProcessQueue()
for ply, queue in pairs(transmit_queues) do
if not ply:IsValid() then transmit_queues[ply] = nil continue end
local nextinqueue = table.remove(queue, 1)
if nextinqueue then
TransmitPath(nextinqueue, ply)
else
transmit_queues[ply] = nil
end
end
if not next(transmit_queues) then
timer.Remove("WireLib.Paths.ProcessQueue")
end
end
-- Add a path to every player's transmit queue
function WireLib.Paths.Add(input, ply)
if ply then
table.insert(transmit_queues[ply], input)
else
for _, player in pairs(player.GetAll()) do
table.insert(transmit_queues[player], input)
end
end
if not timer.Exists("WireLib.Paths.ProcessQueue") then
timer.Create("WireLib.Paths.ProcessQueue", 0, 0, ProcessQueue)
end
end