From 266b897404a7e677af9fea0a08adc5bac57dcc67 Mon Sep 17 00:00:00 2001 From: Grocel Date: Tue, 7 Jul 2026 02:37:46 +0200 Subject: [PATCH 1/2] Fixed WMI being broken after engine savegame restore. Turns out engine savegames store the entire entity table, with no way to filter them before hand. This leads to partly applied entity states. Like that entities having certain values but not others such as functions. It results in a broken override state. To fix this I changed the system to also check for certain functions to exist before (re-)applying the custom logic. --- .../info_wiremapinterface/entitycontrol.lua | 4 +++- .../info_wiremapinterface/entityoverride.lua | 8 ++++---- lua/entities/info_wiremapinterface/init.lua | 18 +++++++++++++----- lua/entities/info_wiremapinterface/io.lua | 9 +++++++-- .../info_wiremapinterface/networking.lua | 18 +++++++++++------- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/lua/entities/info_wiremapinterface/entitycontrol.lua b/lua/entities/info_wiremapinterface/entitycontrol.lua index 99ff024b8f..fa1f4a802f 100644 --- a/lua/entities/info_wiremapinterface/entitycontrol.lua +++ b/lua/entities/info_wiremapinterface/entitycontrol.lua @@ -88,7 +88,7 @@ function ENT:AddSingleEntity(wireEnt) local isInList = IsValid(oldWireEnt) and oldWireEnt == wireEnt - if isInList and wireEnt._WireMapInterfaceEnt_HasPorts then + if isInList and wireEnt._WireMapInterfaceEnt_HasPorts and wireEnt._WMI_AddPorts then return end @@ -96,7 +96,9 @@ function ENT:AddSingleEntity(wireEnt) if not self.WireEntsUpdated then self:TriggerHammerOutputSafe("OnWireEntsStartChanging", self) end + end + if not isInList or not wireEnt._WMI_AddPorts then self:OverrideEnt(wireEnt) end diff --git a/lua/entities/info_wiremapinterface/entityoverride.lua b/lua/entities/info_wiremapinterface/entityoverride.lua index 55524255c2..e55c55aaf5 100644 --- a/lua/entities/info_wiremapinterface/entityoverride.lua +++ b/lua/entities/info_wiremapinterface/entityoverride.lua @@ -654,7 +654,7 @@ function WIREENT:_WMI_AddPorts(wireInputRegister, wireOutputRegister) return end - if wireInputRegister and wireInputRegister:hasPorts() then + if wireInputRegister and wireInputRegister.hasPorts and wireInputRegister:hasPorts() then local split = wireInputRegister.wire wmidata.inputs = table.Copy(split) @@ -670,7 +670,7 @@ function WIREENT:_WMI_AddPorts(wireInputRegister, wireOutputRegister) self._WireMapInterfaceEnt_HasPorts = true end - if wireOutputRegister and wireOutputRegister:hasPorts() then + if wireOutputRegister and wireOutputRegister.hasPorts and wireOutputRegister:hasPorts() then local split = wireOutputRegister.wire wmidata.outputs = table.Copy(split) @@ -763,7 +763,7 @@ function ENT:OverrideEnt(wireEnt) return end - if not wireEnt._IsWireMapInterfaceSubEntity then + if not wireEnt._IsWireMapInterfaceSubEntity or not wireEnt._WMI_AddPorts then WIREENT._WMI_OverrideEnt(wireEnt, self) end @@ -777,7 +777,7 @@ local function OverrideEntFromDupe(wireEnt, wireMapInterfaceEntDupeInfo, interfa return end - if wireEnt._IsWireMapInterfaceSubEntity then + if wireEnt._IsWireMapInterfaceSubEntity and wireEnt._WMI_AddPorts then -- Already initialized return end diff --git a/lua/entities/info_wiremapinterface/init.lua b/lua/entities/info_wiremapinterface/init.lua index c9fa5abc6b..1240c336d8 100644 --- a/lua/entities/info_wiremapinterface/init.lua +++ b/lua/entities/info_wiremapinterface/init.lua @@ -272,11 +272,6 @@ function ENT:Initialize() self.PortsUpdated = true - local recipientFilter = RecipientFilter() - recipientFilter:RemoveAllPlayers() - - self.NetworkRecipientFilter = recipientFilter - self.NextNetworkTime = CurTime() + (1 + math.random() * 2) * (self.MIN_THINK_TIME * 4) self:AddDupeHooks() @@ -289,6 +284,19 @@ function ENT:OnReloaded() self:AttachToSaveStateEntity() end +function ENT:OnRestore() + -- Auto repair on engine savegame restore. + + -- Repair wired entities by re-adding them. + self:AddEntitiesByTable(self:GetWiredEntities()) + self.PortsUpdated = true + + -- Make sure networking and hooks are triggered + self:AddDupeHooks() + self:RequestNetworkEntities() + self:AttachToSaveStateEntity() +end + function ENT:IsActive() return self.Active and cvar_allow_interface:GetBool() end diff --git a/lua/entities/info_wiremapinterface/io.lua b/lua/entities/info_wiremapinterface/io.lua index 15e224e487..51fef95734 100644 --- a/lua/entities/info_wiremapinterface/io.lua +++ b/lua/entities/info_wiremapinterface/io.lua @@ -100,7 +100,10 @@ end -- To cleanup and get the in-/outputs information. local function copyAndSanitizeToPortRegister(register, registerTmp) - register = register or newPortRegister() + if not register or not register.empty then + register = newPortRegister() + end + register:empty() if not registerTmp then @@ -130,7 +133,9 @@ function ENT:UpdatePorts() local wireEnts = self:GetWiredEntities() for key, wireEnt in ipairs(wireEnts) do - wireEnt:_WMI_AddPorts(self.WireInputRegister, self.WireOutputRegister) + if wireEnt._WMI_AddPorts then + wireEnt:_WMI_AddPorts(self.WireInputRegister, self.WireOutputRegister) + end end end diff --git a/lua/entities/info_wiremapinterface/networking.lua b/lua/entities/info_wiremapinterface/networking.lua index 9b7a71c584..96b18a09c4 100644 --- a/lua/entities/info_wiremapinterface/networking.lua +++ b/lua/entities/info_wiremapinterface/networking.lua @@ -55,23 +55,24 @@ function ENT:RequestNetworkEntities(ply, networkAtTime) self.NextNetworkTime = networkAtTime end - local recipientFilter = self.NetworkRecipientFilter - if not IsValid(ply) then - recipientFilter:AddAllPlayers() + self.NetworkRecipients = player.GetHumans() return end - recipientFilter:AddPlayer(ply) + local networkRecipients = self.NetworkRecipients or {} + self.NetworkRecipients = networkRecipients + + networkRecipients[#networkRecipients + 1] = ply end function ENT:NetworkWireEntities() -- Network the list and properties of the wire entities. -- We need we know about them on the client. For cable rendering, tools etc. - local recipientFilter = self.NetworkRecipientFilter + local networkRecipients = self.NetworkRecipients - if recipientFilter:GetCount() <= 0 then + if not networkRecipients or #networkRecipients <= 0 then return end @@ -89,8 +90,11 @@ function ENT:NetworkWireEntities() net.WriteUInt(wireEnt:EntIndex(), MAX_EDICT_BITS) end + local recipientFilter = RecipientFilter() + recipientFilter:AddPlayers(networkRecipients) + net.Send(recipientFilter) - recipientFilter:RemoveAllPlayers() + self.NetworkRecipients = nil end From 47e3c2bdf9c9a67240a92ee631175815636fbf1f Mon Sep 17 00:00:00 2001 From: Grocel Date: Wed, 8 Jul 2026 18:19:45 +0200 Subject: [PATCH 2/2] Made spelling more "useful" again. --- lua/entities/info_wiremapinterface/io.lua | 4 ++-- wiremod.fgd | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lua/entities/info_wiremapinterface/io.lua b/lua/entities/info_wiremapinterface/io.lua index 51fef95734..3893ed3ff5 100644 --- a/lua/entities/info_wiremapinterface/io.lua +++ b/lua/entities/info_wiremapinterface/io.lua @@ -179,7 +179,7 @@ function ENT:PrepairOutputGlobals(inputData, wireValue, wireEnt, wireDevice, own return end - -- This can be usefull if a lua_run entity is triggered + -- This can be useful if a lua_run entity is triggered -- Because entity.Fire and entity.AcceptInput are not run synchronously in the same frame, we use them in a custom entity.AcceptInput detour. -- So we store them for later use in a custom entity.AcceptInput detour. @@ -207,7 +207,7 @@ function ENT:PrepairOutputGlobals(inputData, wireValue, wireEnt, wireDevice, own end function ENT:SetupOutputGlobals(globals) - -- This can be usefull if a lua_run entity is triggered + -- This can be useful if a lua_run entity is triggered local G = _G diff --git a/wiremod.fgd b/wiremod.fgd index 6fa4e18a63..46ab556e9f 100644 --- a/wiremod.fgd +++ b/wiremod.fgd @@ -2,7 +2,7 @@ : "Creates an interface between the map and Wiremod." [ wire_entity_name(target_destination) : "Wire Entity" : "" : "The name of an entity or of the entities that will get wire ports." - min_trigger_time(float) : "Minimum Trigger Time" : "0.01" : "Set the minimum time in seconds between two Wiremod input triggers. It's usefull to prevent lags." + min_trigger_time(float) : "Minimum Trigger Time" : "0.01" : "Set the minimum time in seconds between two Wiremod input triggers. It's useful to prevent lags." // Wire Inputs input1_name(string) : "Wire Input 1 Name" : "" : "Sets the name of Wire Input 1."