Page 1 of 1

Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 6:19 am
by DRY411S
It is bound to be something stupid, but I have been poring over it and cannot see what I'm doing wrong.

I'm trying to change the recipe for the vanilla battery, so that it is hidden. The default is that it is NOT hidden.

At the data stage I have this.

Code: Select all

data.raw.recipe["battery"].normal.hidden = true
data.raw.recipe["battery"].expensive.hidden = true
But if I immediately serpent_block dump the data.raw.recipe["battery"] after this I see that the properties have not changed.
serpent_block dump

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 8:01 am
by bobingabout
when dealing with a difficulty split recipe, some tags go on the normal/expensive tables, where others go directly onto the recipe table.

I am not sure if hidden should be on the recipe table, or the difficulty tables.
Have you tried this to see if it has any effect?

Code: Select all

data.raw.recipe["battery"].hidden = true

EDIT: After looking back at your table block there, it probably should go on the difficulty, but I'll leave this here anyway, it's still worth a try if you haven't already.

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 8:31 am
by DRY411S
bobingabout wrote:when dealing with a difficulty split recipe, some tags go on the normal/expensive tables, where others go directly onto the recipe table.

I am not sure if hidden should be on the recipe table, or the difficulty tables.
Have you tried this to see if it has any effect?

Code: Select all

data.raw.recipe["battery"].hidden = true

EDIT: After looking back at your table block there, it probably should go on the difficulty, but I'll leave this here anyway, it's still worth a try if you haven't already.
I have tried the code without the difficulty included, like you suggested, but that wasn't working either, which is when I started to include the difficulty. I have dumped the table block immediately prior to my code executing, and confirmed that normal.hidden and expensive.hidden are both present, and both false. So I really don't understand why my code isn't changing them to true.

Edit: The recipe prototype documentation says that most properties are read-only, so I'm wondering whether I need to do some table.remove, table.insert, data.extend type of thing, though I've no idea how.

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 9:58 am
by DRY411S
I've partly fixed this:

Code: Select all

local battery = {}
battery = data.raw.recipe.battery
battery.normal.hidden = true
battery.expensive.hidden = true
data.raw.recipe.battery = battery
SERPENT BLOCK OUTPUT
So it appears that data.raw.recipe.normal.hidden IS read-only, but data.raw.recipe.battery is not.

This problem has therefore moved on from a coding error to what happens at run-time

As soon as the game starts. and from the console I type:

Code: Select all

/c game.player.print (game.player.force.recipes["battery"].normal.hidden)
I get an error about LuaRecipe not containing the key normal. This is what I'd expect because the game has decided whether to use normal or expensive recipes.

BUT, when I type

Code: Select all

/c game.player.print (game.player.force.recipes["battery"].hidden)
I am told at the console that the value is once again false. :(

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 10:42 am
by Optera
When I create a new recipe with recipe.hidden = false it will correctly hide the recipe in game.
recipe.difficulty.hidden might be link to recipe.hidden.

Having read only properties during data phase feels odd. Did you try
local battery = table.deepcopy(data.raw.recipe["battery"])
battery.hidden = true
data.raw.recipe["battery"] = battery
table.deepcopy ensures it's a fresh table and not a link to the original. It shouldn't make a difference here but who knows.


Edit just tested it, that doesn't seem to hide the recipe either.

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 11:31 am
by DRY411S
I'm starting to lose the will to live on this. The code I posted earlier:

Code: Select all

local battery = {}
battery = data.raw.recipe.battery
battery.normal.hidden = true
battery.expensive.hidden = true
data.raw.recipe.battery = battery
appears to set the normal and hidden flags to true, but as described in my post above, they've been reset to false at run time.

Bizarrely, if I remove the last line on the above code, namely:

Code: Select all

data.raw.recipe.battery = battery
then at run time the flag IS true!

Here's some similar code that throws an error I cannot explain:

Code: Select all

local newbattery = {}
newbattery = data.raw.recipe.battery
newbattery.normal.hidden = true
newbattery.expensive.hidden = true
newbattery.category = "crafting-with-fluid"
newbattery.name =  "assembler-battery"
data.raw.recipe["assembler-battery"] = newbattery
The error message is:

Code: Select all

Mods to disable:Failed to load mods: Prototype name (assembler-battery) does not match the key name (battery).
But I've just changed the name to "assembler-battery"

I am utterly, utterly confused. I think I'm failing to understand something fundamental about either Lua, the factorio data, or both. :cry:

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 11:38 am
by DRY411S
Optera wrote:<snip><snip>
table.deepcopy ensures it's a fresh table and not a link to the original. It shouldn't make a difference here but who knows.
That is probably the fundamental thing that I was not understanding. I think it IS making a difference, especially in my 2nd code snippet. Thank you!

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 11:54 am
by withers
DRY411S wrote:
Optera wrote:<snip><snip>
table.deepcopy ensures it's a fresh table and not a link to the original. It shouldn't make a difference here but who knows.
That is probably the fundamental thing that I was not understanding. I think it IS making a difference, especially in my 2nd code snippet. Thank you!
I can't answer your original question, it's very puzzling. But to maybe help clear things up for you, when you say

newbattery = data.raw.recipe.battery

That does not create a new table. It just says "newbattery" is a reference to the table that already exists at "data.raw.recipe.battery".

So after this any change to specific variable referenced by newbattery OR data.raw.recipe.battery would change both, since they are both pointing at the same location in memory.

Like you already mentioned, you have to use deepcopy to make a new table.

Re: Can somebody tell me what is wrong with this code?

Posted: Thu Jul 20, 2017 3:14 pm
by DRY411S
Optera wrote:When I create a new recipe with recipe.hidden = false it will correctly hide the recipe in game.
<snip>
That is true unless the recipe prototype has normal and expensive ingredients. Some of the recipes don't have normal and expensive tables in the prototypes, in which case you can just use recipe.hidden. But in my case I am amending the vanilla battery recipe prototype which does have normal and expensive ingredients. Each of the normal and expensive tables have separate hidden properties.
Optera wrote:<snip>Did you try
local battery = table.deepcopy(data.raw.recipe["battery"])
battery.hidden = true
data.raw.recipe["battery"] = battery
table.deepcopy ensures it's a fresh table and not a link to the original. It shouldn't make a difference here but who knows.


Edit just tested it, that doesn't seem to hide the recipe either.
My code is fixed after Optera and withers showed me the way with table.deepcopy. I should have been using this elsewhere in my code.
withers wrote:I can't answer your original question, it's very puzzling. <snip>
It is, and I still cannot explain why it wasn't working. It works now. It's possibly due to not using table.deepcopy elsewhere in my code, but I cannot think how.

So, just to confirm that it IS possible to use data.raw.recipe[name]..., the final working version of the code is this, but using a pointer with a local variable is equally valid.

Code: Select all

-- Hide the vanilla recipe for Chemical Plant batteries
data.raw.recipe.battery.normal.hidden = true
data.raw.recipe.battery.expensive.hidden = true
data.raw.recipe.battery.normal.enabled = false
data.raw.recipe.battery.expensive.enabled = false
Thanks to bobingabout, Optera and withers for helping me see the light and fix this. It was literally keeping me awake at night!