Don't hard-error a game on a nil value in 'game'

Place to get help with not working mods / modding interface.
Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Don't hard-error a game on a nil value in 'game'

Post by Honktown »

I do my own error handling, so if I access a nil in for example game.item_prototypes, I can act on if it is nil. Instead, the game just goes ERROR and exits the current game, leaving a mod with no options. If I could transfer data from the data-final-fixes state or had another way to store any data.raw information I wanted to, it wouldn't be a pain. Unless there's a mistake I'm making, I wasn't able to transfer from the data-final-fixes stage into whatever stage the game is in when it's running and events are triggerable (like a player_mined_entity).
I have mods! I guess!
Link

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5150
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Klonan »

You can wrap you calls in pcall if you like
https://www.lua.org/pil/8.4.html

Other than that, if there is a script error, we are always going to stop execution

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

nil is not an error. Instead for safety I have to do pairs() over an entry, and if the key matches what I'm looking for, store it, and then check my local variable afterwards. It doesn't save me effort, and it is pretty much the same, but it's not a convention I prefer to use.
I have mods! I guess!
Link

Bilka
Factorio Staff
Factorio Staff
Posts: 3154
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Bilka »

Read the documentation so you don't access non-existent functions/values in "game". Doing that will always be an error.

Your item_prototypes example can be solved with a simple if.
Image
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

That's... what I did. I had if game.item_prototypes[name] and game.item_prototypes[name].attribute instead of [attribute] and it threw an error and quit the game I was playing. Because .attribute didn't exist it said you can't access a nil, instead of returning to me the damn nil.
I have mods! I guess!
Link

Bilka
Factorio Staff
Factorio Staff
Posts: 3154
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Bilka »

Then read the documentation on LuaItemPrototypes and only access properties that exist on the object.

LuaItemPrototype wont error in your face if the property has the value nil, it will only error in your face if the property doesn't exist at all. This means item.laskdjlaskd will error; while item.magazine_size will give back nil for anything that isnt ammo, and the expected value for ammo.

Image
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

nil is when the property doesn't exist. A nil cannot exist in a table. Basic lua there.

Since you're not getting it:
really.png
really.png (61.92 KiB) Viewed 2900 times

Code: Select all

  if game.item_prototypes["coal"] and game.item_prototypes["coal"].attribute then
    log("attribute exists in coal")
  end

Edit: log:

33.656 Error MainLoop.cpp:1195: Exception at tick 329666: The mod Decu caused a non-recoverable error.
Please report this error to the mod author.

Error while running event Decu::on_player_mined_entity (ID 65)
LuaItemPrototype doesn't contain key attribute.
I have mods! I guess!
Link

Bilka
Factorio Staff
Factorio Staff
Posts: 3154
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Bilka »

So read and follow the documentation, it tells you what does and doesn't exist: https://lua-api.factorio.com/latest/Lua ... otype.html

Also, I am curious how your "Instead for safety I have to do pairs() over an entry, and if the key matches what I'm looking for, store it, and then check my local variable afterwards." code works on LuaItemPrototype, care to share?
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

Code: Select all

local item_info = item_info or {}

function item_info.store_info(attribute)
  if attribute == nil or type(attribute) ~= "string" then return end

  local name_exists = false
  local attribute_exists = false

  for _, item in pairs(game.item_prototypes) do
    for key in pairs(item) do
      if type(key) == "string" then
        if key == "name" then
          name_exists = true
        end

        if key == "attribute" then
          attribute_exists = true
        end
      end
    end

    if name_exists and attribute_exists then
      if item_info[item.name] == nil then item_info[item.name] = {} end

      item_info[item.name][attribute] = item[attribute]
    else
      name_exists = false
      attribute_exists = false
    end
  end
end

function item_info.get_item(name)
  return item_info[name]
end

return item_info
I have to test out if name is always the same as the key for the table. I'm using another mod which assumes that's true, but I'd expect it to not to be. Either way in this case it's fine.

Ehh I missed an end somewhere. There, better.
I have mods! I guess!
Link

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

Haha you assholes. Guess I have to find another way to go over the table.
I have mods! I guess!
Link

Bilka
Factorio Staff
Factorio Staff
Posts: 3154
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Bilka »

If only all the attributes were documented or something.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

I found a way to do the thing (I won't tell you how because you'll probably fix it) but uh

Code: Select all

  store_info = ((loadstring or load)("\27LuaR\0\1\4\8\4\8\0\25Ԝ13\n\26\n%\0\0\0=\0\0\0\1\0\n3\0\0\0X\0@\0\23\0\1F@@\0\0\0\0]\0\1X@\0\23\0\0\31\0\0C\0\0\0Ĝ0\0\0ǀ@\0\6\1A\0\7AA\2\7\2\7\2ހ\0\1Ɯ0\0\6\1A\0\7AA\2\7\2\7\2ހ\0\1ǀ@\0\6\1B\0\7AB\2E\1\0\1ˁ\0\0ˁBŊACǜ29\1\1ހ\0\0\31\0\0ƀC\0\6\1A\0\7AA\2ޜ0\1\1\23\2G\1D\3݁\0\8Ȇƒ\0X\0\3\23\0\1F€\0ȁŜ3\6Ã\0@\2\0\0ށ\1ぜ0\0c¼\127\31\0\0\18\0\0\0\0\4\5\0\0\0\0\0\0\0type\0\4\7\0\0\0\0\0\0\0string\0\4\4\0\0\0\0\0\0\0log\0\4\5\0\0\0\0\0\0\0game\0\4\16\0\0\0\0\0\0\0item_prototypes\0\4\16\0\0\0\0\0\0\0dummy-steel-axe\0\4\27\0\0\0\0\0\0\0durability_description_key\0\4\8\0\0\0\0\0\0\0serpent\0\4\6\0\0\0\0\0\0\0block\0\4\8\0\0\0\0\0\0\0comment\0\1\0\4\n\0\0\0\0\0\0\0numformat\0\4\6\0\0\0\0\0\0\0%1.8g\0\4\6\0\0\0\0\0\0\0pairs\0\4\11\0\0\0\0\0\0\0helpstring\0\4\5\0\0\0\0\0\0\0help\0\4\6\0\0\0\0\0\0\0match\0\0\0\0\0\3\0\0\0\0\0\1\1\1\0#\0\0\0\0\0\0\0@__Decu__/utils/item_functions.lua\0003\0\0\0&\0\0\0&\0\0\0&\0\0\0&\0\0\0&\0\0\0&\0\0\0&\0\0\0&\0\0\0(\0\0\0)\0\0\0+\0\0\0+\0\0\0+\0\0\0+\0\0\0+\0\0\0+\0\0\0-\0\0\0-\0\0\0-\0\0\0-\0\0\0-\0\0\0-\0\0\0/\0\0\0/\0\0\0/\0\0\0/\0\0\0/\0\0\0/\0\0\0/\0\0\0/\0\0\0/\0\0\0003\0\0\0005\0\0\0005\0\0\0005\0\0\0005\0\0\0005\0\0\0006\0\0\0006\0\0\0006\0\0\0008\0\0\0008\0\0\0008\0\0\0009\0\0\0009\0\0\0009\0\0\0009\0\0\0009\0\0\0005\0\0\0005\0\0\0=\0\0\0\7\0\0\0\n\0\0\0\0\0\0\0attribute\0\0\0\0\0003\0\0\0\12\0\0\0\0\0\0\0name_exists\0\9\0\0\0003\0\0\0\17\0\0\0\0\0\0\0attribute_exists\0\n\0\0\0003\0\0\0\16\0\0\0\0\0\0\0(for generator)\0$\0\0\0002\0\0\0\12\0\0\0\0\0\0\0(for state)\0$\0\0\0002\0\0\0\14\0\0\0\0\0\0\0(for control)\0$\0\0\0002\0\0\0\5\0\0\0\0\0\0\0item\0%\0\0\0000\0\0\0\3\0\0\0\5\0\0\0\0\0\0\0_ENV\0\12\0\0\0\0\0\0\0build_items\0\n\0\0\0\0\0\0\0item_info\0",'@serialized')),
Serpent reveals some neat stuff sometimes. I could probably inject code with this right?
I have mods! I guess!
Link

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5150
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Klonan »

Honktown wrote:
Sun Dec 08, 2019 2:19 am
Serpent reveals some neat stuff sometimes. I could probably inject code with this right?
What kind of problem are you trying to solve?

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

Klonan wrote:
Sun Dec 08, 2019 8:46 am
Honktown wrote:
Sun Dec 08, 2019 2:19 am
Serpent reveals some neat stuff sometimes. I could probably inject code with this right?
What kind of problem are you trying to solve?
I need stack sizes while the game is running, to limit an increase in rewards that will be affected by during-runtime values.

If you're iterating over things in game.item_prototypes (and probably others which I would like to have access to) if you test to see if a value exists, you get an ERROR, and not nil. I found an ass-backwards way to export valid attributes from data-final-fixes, but I want to just GET NIL IF THE VALUE IS NIL. I don't know whose brilliant idea it was to remove next() too, so not only does the game hard error and exit to the main menu if I try to read a value that may be nil, I can't LOOK to see if the value exists in the table.

To say it clearly, before Bilka repeats themself for the fifth time: NOT EVERY ITEM HAS ALL VALUES DOCUMENTED IN THE API.

I tried saving data during data-final-fixes to global, which I assumed would persist since data.raw changes get processed, but it didn't seem to (the mod I'm changing isn't mine, and it does some weird things with global, so there may be a way to store data and use it later).

Edit: in general, the removal of next() is a huge pain in the ass. I like to use serpent to go over a table, for both reading what a table is and for validating that I've stored information how I intended it to be stored. If I could use serpent on game and global it would make modding so much easier.
I have mods! I guess!
Link

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

I probably need to re-phrase: next and such are Lua functions, and it is probable that the data required for them to work correctly on certain tables in game don't exist. The function exists, and afaik it's not meta-table-overwritable or whatever, but if I could call game.next() or game.pairs() and it could refer to C++ functions that work on game.category values, that'd be super convenient. I assume part of the reason things like next() don't work is because values are optimized for use during runtime, removing what Lua expects to work correctly.
I have mods! I guess!
Link

Bilka
Factorio Staff
Factorio Staff
Posts: 3154
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Bilka »

Honktown wrote:
Sun Dec 08, 2019 7:48 pm
To say it clearly, before Bilka repeats themself for the fifth time: NOT EVERY ITEM HAS ALL VALUES DOCUMENTED IN THE API.
Yes they do. I can 100% guarantee you that every LuaItemPrototype has the properties documented on https://lua-api.factorio.com/latest/Lua ... otype.html. You see to be assuming that data stage properties == control stage properties which is simply false.

As a side note, nobody went and "removed next()". It simply doesn't work with Lua data structures backed by C++ objects. Also, serpent works on global, global is just a normal Lua table.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

Bilka wrote:
Sun Dec 08, 2019 8:32 pm
Honktown wrote:
Sun Dec 08, 2019 7:48 pm
To say it clearly, before Bilka repeats themself for the fifth time: NOT EVERY ITEM HAS ALL VALUES DOCUMENTED IN THE API.
Yes they do. I can 100% guarantee you that every LuaItemPrototypes has the properties documented on https://lua-api.factorio.com/latest/Lua ... otype.html. You see to be assuming that data stage properties == control stage properties which is simply false.
Why not have ALL the properties?

Who would think I wouldn't want to know data.raw properties during runtime? Who would think it's a good idea to error out the game? How do I actually access all the entity properties if not even game.item_prototypes has them?
I have mods! I guess!
Link

Bilka
Factorio Staff
Factorio Staff
Posts: 3154
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Bilka »

Honktown wrote:
Sun Dec 08, 2019 8:49 pm
Who would think I wouldn't want to know data.raw properties during runtime? Who would think it's a good idea to error out the game? How do I actually access all the entity properties if not even game.item_prototypes has them?
If there is a property missing that the data stage item prototype has, but the runtime one doesn't, request it. Examples of such requests for entity prototype properties: 64365, 74581.

It is not "simply all" because they are hand-coded, so people forget to add things etc. Furthermore, graphical-only properties such as sprites are not made available via the prototypes in the control stage; e.g. for an item icon you'd use the sprite path. Generally, if something is missing, just let us know and we will add it. See posts linked above for examples of people doing exactly that.

Note that entity properties are accessed via the entity prototype, not the item prototype.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.

Honktown
Smart Inserter
Smart Inserter
Posts: 1026
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Honktown »

Bilka wrote:
Sun Dec 08, 2019 8:55 pm
Honktown wrote:
Sun Dec 08, 2019 8:49 pm
Who would think I wouldn't want to know data.raw properties during runtime? Who would think it's a good idea to error out the game? How do I actually access all the entity properties if not even game.item_prototypes has them?
If there is a property missing that the data stage item prototypes has, but the runtime ones don't, request it. Examples of such requests for entity prototype properties: 64365, 74581.

It is not "simply all" because they are hand-coded, so people forget to add things etc. Furthermore, graphical-only properties such as sprites are not made available via the prototypes in the control stage; e.g. for an item icon you'd use the sprite path. Generally, if something is missing, just let us know and we will add it. See posts linked above for examples of people doing exactly that.

Note that entity properties are accessed via the entity prototype, not the item prototype.
What a mess. I'll just spoil it: I'm adding all the properties I want from data.raw to a string, stored in dummy-steel-axe (durability_description_key) during data-final-fixes. I then use matching and some control characters to parse the string back into table information during the game. My initial parsing of everything dumped ~785k characters into the string for every string key, not even what the value was, which works fine, funnily enough. It wasn't perfect, and it's still not (I need to store all properties I want into a table first and then turn into the string so I can collect properties from different categories). I may add a section to store the whole structure of data.raw, in a vaguely "compressed" format. If I used a-zA-Y0-9 I can get 65 valid attributes compacted into single characters with a dictionary, and use Z as an extension if I need more. Since not all values are available during runtime, I probably should just store the whole damn data.raw table and compress/decompress it.

I was working under the assumption that there wasn't explicit handling of what was valid and what was not valid, so I'll have to end up storing values too, in the future event I want something like mining result outside of an event. Not gonna store crap like resource probability functions, that'd just be asking for it.
I have mods! I guess!
Link

Bilka
Factorio Staff
Factorio Staff
Posts: 3154
Joined: Sat Aug 13, 2016 9:20 am
Contact:

Re: Don't hard-error a game on a nil value in 'game'

Post by Bilka »

Sounds like you are setting yourself for using unreliable data which needs lots of hacks to be used instead of simply using the existing api.

Aside from that api dev view of it, I as a mod author certainly would rather use the reliable format of the prototype data in control over having to deal with the bullshit that things like data stage recipe products/ingredients format combined with difficulties are.
I'm an admin over at https://wiki.factorio.com. Feel free to contact me if there's anything wrong (or right) with it.

Post Reply

Return to “Modding help”