engine/bin/data/entities/scripts/io.lua

143 lines
3.8 KiB
Lua

local ent = ent
local scene = entities.currentScene()
local metadata = ent:getComponent("Metadata")
-- assign targets
_G.IOTargets = _G.IOTargets or {}
local metadataValve = metadata["valve"] or {}
if metadataValve["targetname"] then
local tname = metadataValve["targetname"]
if not _G.IOTargets[tname] then
_G.IOTargets[tname] = {}
end
local uid = ent:uid()
local exists = false
for _, id in ipairs(_G.IOTargets[tname]) do
if id == uid then exists = true break end
end
if not exists then
table.insert(_G.IOTargets[tname], uid)
end
end
ent:addHook("io:Input.%UID%", function(payload)
local input = payload.input
local param = payload.parameter
-- kill
if input == "Kill" or input == "KillHierarchy" then
entities.destroy(ent)
-- relays
elseif input == "FireUser1" then
ent:callHook("io:FireOutput.%UID%", { output = "OnUser1" })
elseif input == "FireUser2" then
ent:callHook("io:FireOutput.%UID%", { output = "OnUser2" })
elseif input == "FireUser3" then
ent:callHook("io:FireOutput.%UID%", { output = "OnUser3" })
elseif input == "FireUser4" then
ent:callHook("io:FireOutput.%UID%", { output = "OnUser4" })
-- colors
elseif input == "Alpha" then
local alphaVal = tonumber(param) / 255.0
if alphaVal then
-- to-do: apply to instance / material
end
elseif input == "Color" then
local r, g, b = param:match("(%d+) (%d+) (%d+)")
-- to-do: apply to instance / material
else
--print("I/O [(".. ent:uid() ..") " .. ent:name() .. "]: Received Input '" .. input .. "' with param '" .. tostring(param) .. "'")
end
end )
-- no connections defined, bail early
local connections = metadata["connections"]
if not connections then return end
-- define connections
local timer = Timer.new()
if not timer:running() then
timer:start()
end
local timesFired = {}
for i = 1, #connections do
timesFired[i] = 0
end
local pendingOutputs = {}
ent:bind("tick", function(self)
local currentTime = timer:elapsed()
for i = #pendingOutputs, 1, -1 do
local job = pendingOutputs[i]
if currentTime >= job.fireTime then
local targetUIDs = _G.IOTargets[job.target]
if targetUIDs then
for _, targetUID in ipairs(targetUIDs) do
local targetEnt = entities.get(targetUID)
if targetEnt:uid() then
targetEnt:callHook("io:Input." .. targetUID, {
input = job.input,
parameter = job.parameter,
caller = ent:uid()
})
end
end
else
print("I/O Warning: Targetname '" .. job.target .. "' not found!")
end
table.remove(pendingOutputs, i)
end
end
end)
ent:addHook("io:FireOutput.%UID%", function(payload)
local output = payload.output
for i = 1, #connections do
local conn = connections[i]
if conn.output == output then
local limit = conn.times or -1
if limit == -1 or timesFired[i] < limit then
timesFired[i] = timesFired[i] + 1
local delay = conn.delay or 0.0
table.insert(pendingOutputs, {
fireTime = timer:elapsed() + delay,
target = conn.target,
input = conn.input,
parameter = conn.parameter
})
end
end
end
end)
ent:addHook("entity:Destroy.%UID%", function()
if metadataValve["targetname"] then
local tname = metadataValve["targetname"]
if _G.IOTargets[tname] then
for i, id in ipairs(_G.IOTargets[tname]) do
if id == ent:uid() then
table.remove(_G.IOTargets[tname], i)
break
end
end
end
end
end)
ent:addHook("entity:Use.%UID%", function(payload)
if payload.user == ent:uid() then return end
ent:callHook("io:FireOutput.%UID%", { output = "OnPlayerUse" })
ent:callHook("io:FireOutput.%UID%", { output = "OnUse" })
ent:callHook("io:FireOutput.%UID%", { output = "OnPressed" })
ent:callHook("io:FireOutput.%UID%", { output = "OnIn" })
end)