Yokmp / Ingredient_Scrap

A small Mod for Factorio built around Scrap.
MIT License
0 stars 3 forks source link

Fix for bobplates referencing aluminium twice and support for Clowns-Extended-Minerals. #1

Closed nihilistzsche closed 3 years ago

nihilistzsche commented 3 years ago

bobplates was referencing aluminium twice, and was not referencing tungsten, so I replaced the second instance with tungsten.

I also added support for Clowns-Extended-Minerals, as Ive never actually gotten far enough to get to the mixed types the colors are a best guess from the information I was able to find while researching, but its fine if you update them if you find something that works better.

Yokmp commented 3 years ago

I merged your request butdidn't upload to the mod-portal. After i downloaded the required mods for Clowns-Extended-Minerals and also the needed angel mods i added in bobplates and ores but it seems that some items (plates in particular) aren't needed for anything? Am i missing some mods?

Yokmp commented 3 years ago

Besides the small icon bug there is a reason that no osmium (and others) scrap is generated. it checks if data.raw.item[_types.."-".._results] exists and creates a type.."-scrap" item. But since clowns items are named like "clowns-plate-osmium" it will check for osmium-plate which doesn't exists. I could check for _results.."-".._types too if it fails to find in the first place but then it would fail again if a mod adds in an osmium-plate since i first look for osmium in the name ...

I think it is easier (and safer) to write some specific recipes for clowns mods.

I will think about it but also i don't think i will find a (practical) solution in the forseeable future. :/

nihilistzsche commented 3 years ago

I would think checking for _results.."-".._type to match Clowns would work, someone installing another mod on top of that which referenced osmium-plate would be a user error, but also why not just look at both instead of just one?

Yokmp commented 3 years ago

After writing all this i realized that i just can't exactly explain the problem without writing a book ^^ So i try to give you an insight of the sctructure of the code and how things work so you can get to the bottom of the bug yourself: The current logic is like this (line 45):

local scrap_types = {"iron", "copper", "steel"}
local item_types = {"plate"}

local function filter_scrap_types()
  local _t1, _t2 = {}, {}
  for _, s_type in ipairs(scrap_types) do  -- we loop through our scrap-types
    for _, i_type in ipairs(item_types) do -- and here through the items-types
      if data.raw.item[s_type.."-"..i_type] then -- if scrap..-..item does exist 
        _t1[s_type] = s_type                     -- we add the scrap to the new table
      end
    end
  end
  for _, _type in pairs(_t1) do
    _t2[#_t2+1] = _type
  end

  scrap_types = _t2 -- here we overwrite the array with the new content
  return _t2

This is to be shure we later (line 425) only construct scrap items and recycle recipes only if there can be a result (which works most of the time). Now assume we have a iron-plate and a modded-plates-iron item. Adding "modded-plates" to _scrap_types and "iron" to _item_types. The table extend function will add the new (mod specific) values to a new table and concatenate the old ones at the end so that modded items will be found first later in the code (to manipulate the 'loadorder' if necessary). So we end up with something like this:

local scrap_types = {"modded-plates", "iron", "copper", "steel"}
local item_types = {"iron", "copper", "plate"}

This will pass the filter (you can log the return value to check) The main loop start at line 432 where we loop through all recipes. And here (line 126) is where the script will 'fail' with the above changes:

function get_recipe_ingredient_types(recipe_name)
...
  for _, ingredient in ipairs(_return.recipe.ingredients) do -- loop through the ingredients
    for _, _type in ipairs(scrap_types) do                   -- and scrap types
      if string.find(ingredient.name, _type, 0, true) and get_scrap_types(_type, item_types) then
...

(String.find won't let us get osmium-plate in combination with the filter function and how names are constructed.)

Lets say we currently check iron-plate which won't match modded-plates but ironso we add iron-scrap to it. Now we check modded-plates-iron which will match modded-plates and we break out of the loop because we only need one match (if we dont it would also match iron) So far so good unless we add in modded-plates-copper. Now we also would match stuff and all goes well until we hit the item and recipe construction. Now we create modded-plates-scrap and recycle-modded-plates-scrap with the result of modded-plates-iron. After that we then try to create the same for modded-plates-copper wich unfortunately will have the same name but a different result.

As you may see the underlying problem(s) goes so deep that i had to rewrite the majority of the code just to catch some exceptions. It would be easier to just hsrd code the items and recipes for these mods.

Fixing the item and recipe names is pretty easy but catching "malformed" names isn't. This is because of how string.find() works. It will search for the given pattern at any position in the given string so that iron-plate and modded-plates-iron is the same for that function. This is bad in this case but it makes my mod compatible with most modded items/recipes. I will write a custom match logic and a name/item/recipe constructor (or an alternative to them which are used if such a mod is active) at some point but atm i just don't have enough time to do and test that.

Yokmp commented 3 years ago

First i filter all types and results (this will work if we add (switch) osmium to item_types and clowns-plates to scrap_types) Then I loop through all scrap_types and create the items and recipes bsaed on that. (this is where things get weird) Now i loop through all recipes and call get_recipe_ingredient_types(recipe_name) in which i also loop through all scrap_types. I then check if string.find() finds something (which it does for osmium) and if get_scrap_types(_type, item_types) returns a result (which it can't because of the "malformed" naming. I could change this function to also check in reverse in case it won't find anything.

As i mentioned i don't have much time atm and everything is just assuming or loud thinking.