Adjusting One Table Seems to Affect a Different Table

Place to get help with not working mods / modding interface.
Post Reply
DARKHAWX
Burner Inserter
Burner Inserter
Posts: 6
Joined: Thu May 10, 2018 10:19 am
Contact:

Adjusting One Table Seems to Affect a Different Table

Post by DARKHAWX »

So in my mod I add inputs to one table and outputs to another. I also have a third table which is a total of the two. So when I add something to the inputs table I also add it to the total table. When I add something to the outputs table I also add it (subtract) to the total table. I've noticed a weird issue with this. If I don't add anything from the outputs to the total table everything is fine, but if I add the outputs to the total table, the input table also gets changed.

Here is some relevant code for adding the inputs and outputs:

Code: Select all

local function addInput(itemSignal)
	-- Add to inputs
	itemSignal.index = global.PSCInputIndex
	local signal_found = false
	for _, p in pairs( global.PSCInputSignals ) do
		if p.signal.name == itemSignal.signal.name then
			p.count = p.count + itemSignal.count
			signal_found = true
			break
		end
	end
	if not signal_found then 
		table.insert( global.PSCInputSignals, itemSignal )
		global.PSCInputIndex = global.PSCInputIndex + 1
	end
	
	-- Add to total
	local itemSignalT = itemSignal
	itemSignalT.index = global.PSCTotalIndex
	local signal_found = false			
	for _, p in pairs( global.PSCTotalSignals ) do
		if p.signal.name == itemSignalT.signal.name then
			p.count = p.count + itemSignalT.count
			signal_found = true
			break
		end
	end
	if not signal_found then 
		table.insert( global.PSCTotalSignals, itemSignalT ) 
		global.PSCTotalIndex = global.PSCTotalIndex + 1
	end
	
	-- Add to percentage
	local itemSignalP = itemSignal
	itemSignalP.index = global.PSCPercentageIndex
	local signal_found = false			
	for _, p in pairs( global.PSCPercentageSignals ) do
		if p.signal.name == itemSignalP.signal.name then
			p.count = p.count + itemSignalP.count
			signal_found = true
			break
		end
	end
	if not signal_found then 
		table.insert( global.PSCPercentageSignals, itemSignalP ) 
		global.PSCPercentageIndex = global.PSCPercentageIndex + 1
	end
end

local function addOutput(itemSignal)
	-- Add to outputs
	itemSignal.index = global.PSCOutputIndex
	local signal_found = false			
	for _, p in pairs( global.PSCOutputSignals ) do
		if p.signal.name == itemSignal.signal.name then
			p.count = p.count + itemSignal.count
			signal_found = true
			break
		end
	end
	if not signal_found then 
		table.insert( global.PSCOutputSignals, itemSignal )
		global.PSCOutputIndex = global.PSCOutputIndex + 1							
	end
	
	-- Add to total
	local itemSignalT = itemSignal
	itemSignalT.index = global.PSCTotalIndex
	local signal_found = false			
	for _, p in pairs( global.PSCTotalSignals ) do
		if p.signal.name == itemSignalT.signal.name then
			p.count = p.count - itemSignalT.count
			signal_found = true
			break
		end
	end
	if not signal_found then 
		table.insert( global.PSCTotalSignals, itemSignalT )
		global.PSCTotalIndex = global.PSCTotalIndex + 1
	end
	
	-- Add to percentage
	local itemSignalP = itemSignal
	itemSignalP.index = global.PSCPercentageIndex
	itemSignalP.count = -itemSignalP.count
	local signal_found = false			
	for _, p in pairs( global.PSCPercentageSignals ) do
		if p.signal.name == itemSignalP.signal.name then
			if itemSignalP.count > 0 then
				p.count = ((p.count / itemSignalP.count) - 1) * 100
			elseif p.count > 0 and itemSignalP.count == 0 then
				p.count = 100
			end
			signal_found = true
			break
		end
	end
	if not signal_found then 
		itemSignalP.count = -100
		table.insert( global.PSCPercentageSignals, itemSignalP ) 
		global.PSCPercentageIndex = global.PSCPercentageIndex + 1
	end
end
And here is the code that actually calls those functions

Code: Select all

-- Item Production Input
				for itemName, itemCount in pairs (force.item_production_statistics.input_counts) do					
					local itemSignal = { signal = { type = "item", name = itemName }, count = itemCount, index = global.PSCInputIndex }
					local temp = itemCount
					
					-- Init array value
					if global.PSCInputPrevious[itemName] == nil then
						global.PSCInputPrevious[itemName] = itemCount
					end
					
					-- Modify count to represent change over time
					itemSignal.count = (itemSignal.count - global.PSCInputPrevious[itemName]) * multiplier
					global.PSCInputPrevious[itemName] = temp
					
					-- Add Input
					addInput(itemSignal)					
				end
				
				-- Item Production Output
				for itemName, itemCount in pairs (force.item_production_statistics.output_counts) do
					local itemSignal = { signal = { type = "item", name = itemName }, count = itemCount, index = global.PSCOutputIndex }
					local temp = itemCount
					
					-- Init array value
					if global.PSCOutputPrevious[itemName] == nil then
						global.PSCOutputPrevious[itemName] = itemCount
					end
					
					-- Modify count to represent change over time
					itemSignal.count = (itemSignal.count - global.PSCOutputPrevious[itemName]) * multiplier
					global.PSCOutputPrevious[itemName] = temp
					itemSignal.count = -itemSignal.count
				
					-- Output
					addOutput(itemSignal)
				end

-- More code

                        -- Apply Signals
			for i, c in pairs (global.PSCEntitiesInput) do
				if c then
					local behavior = c.get_or_create_control_behavior()
					if #global.PSCInputSignals > 0 then
						behavior.parameters = { parameters = global.PSCInputSignals }
					end
				end
			end
If you look at the code, what happens is we loop over all the input production statistics and output production statistics, get the difference over time (i.e. since the last update how much has changed) and then call either addInput or addOutput. Each of these first checks if the item already exists in the table, if it does then it simply adds the count to the existing amount, otherwise it inserts the count into the table. As you can see the addOutput function never touches the global.PSCInputSignals table, but still it messes up. If I comment out the lines in addOutput that related to global.PSCTotalSignals and global.PSCPercentageSignals it works fine. So there's some weird issue with the code that I don't understand.

Does anyone see the issue?


Side-question: is there anything special I need to do to make my GUI closable when pressing esc? Because right now esc does nothing and I can only close the GUI my opening another GUI.

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Adjusting One Table Seems to Affect a Different Table

Post by eradicator »

Going from your title because i don't want to try to pick through your code atm... do you understand that in lua all tables are passed by ref, as opposed to numbers and strings that are copy on pass?

I.e.:

a = 'one'
b = a
b = 'two'
print(a)
> this will print 'one'

but

a = {'one'}
b = a
b[1] = 'two'
print(a)
> this will print 'two' because b is a reference to the same table as a is. If you want b to be a different table you need to first make a copy of it via:

require util
b = util.tabl.deepcopy(a)

or in this example
b = {a[1]}
would also work.

But you should probably read this up in a proper lua guide that has better examples.

@GUI:
You need to assign your gui as the players opened gui: LuaPlayer.opened = LuaGuiElement

Mobius1
Fast Inserter
Fast Inserter
Posts: 191
Joined: Thu Feb 09, 2017 12:05 am
Contact:

Re: Adjusting One Table Seems to Affect a Different Table

Post by Mobius1 »

so lets say we have:

Code: Select all

a = {modded-entity-1}
b = table.deepcopy(data.raw["modded-entity-1"])
b.name = "edit"
print(a.name)
> edit
why that happens?
to make it a little clearer I'm doing something like this:

Code: Select all

local entity = table.deepcopy(data.raw["iron-pipe"])
local entity_override = {
  name = "custom-pipe",
  fluid_box = {
    base_area = 2000
  }
}
for k, v in pairs(entity_override) do 
   entity[k] = v
end
That way I make a perfect copy of the entity and only change the things I want from it, keeping the code clear instead of creating it all again, the problem is: its replacing the original itemtable with my itemtable, it only happens with modded entities. Regular Entities it doesn't happen, as I have "iron-pipe" and "modded-iron-pipe" when I do it with vanilla pipe, but when I do with "tungsten-pipe" my "modded-tungsten-pipe" replaces the original "tungsten-pipe"

EDIT: Found the issue, it was a technology issue that was locking the item where it shouldn't be.

Post Reply

Return to “Modding help”