Strange problem with the "Ruin maker" mod

Place to get help with not working mods / modding interface.
Keysivi
Fast Inserter
Fast Inserter
Posts: 110
Joined: Mon Feb 07, 2022 5:29 pm
Contact:

Strange problem with the "Ruin maker" mod

Post by Keysivi »

This is a continuation of the topic viewtopic.php?f=25&t=124422

I'm trying to revive the Ruin maker mod https://mods.factorio.com/mod/ruin-maker

I fixed all the errors that the game showed. But the mod doesn't work!!!!

The description says that after selecting the "ruin-maker" tool, you need to select the necessary objects with a frame using Shift + left mouse button. After that, a window with settings should appear...

But the window does not appear after selecting the frame - what did I do wrong?!!!!!!!!

Edited files:

Data.lua:

Code: Select all

data:extend
{
  {
    type = "selection-tool",
    name = "ruin-maker",
    icon = "__ruin-maker__/graphics/ruin-maker.png",
    icon_size = 64,
    stack_size = 1,
  select = {
    border_color = { r = 1, g = 1, b = 1 },
    cursor_box_type = "entity",  -- Green
    mode = {"blueprint"},
    entity_type_filters = {},
  },
  alt_select = {
    border_color = { r = 1},
    cursor_box_type = "train-visualization",  -- Red
    mode = {"any-tile", "any-entity"},
    entity_type_filters = {},
  },
    always_include_tiles = true,
    flags = {"spawnable"}
  },
  {
    type = "shortcut",
    name = "give-ruin-maker",
    order = "b[blueprints]-d[give-ruin-maker]",	
    action = "spawn-item",
    item_to_spawn = "give-ruin-maker",
    -- localised_name = {"shortcut.give-ruin-maker"},
    associated_control_input = "give-ruin-maker",
    icon = "__ruin-maker__/graphics/ruin-maker-shortcut.png",
    icon_size = 32,
	small_icon = "__ruin-maker__/graphics/ruin-maker-shortcut.png",		
	small_icon_size = 32
  }
}
Control.lua:

Code: Select all

local util = require("utilities")
local output_selection = require("output")

local function discard_selection(player_index)
  for _, render in pairs(storage.selection[player_index].renders) do
    rendering.destroy(render)
  end
  storage.selection[player_index] = nil
end

local function confirm_selection(player_index, name)
  local data = storage.selection[player_index]
  output_selection(data.entities, data.tiles, data.tile_filter, data.center, name ~= "" and name or "unknown", data["ruin-maker-damage"], data["ruin-maker-items"], data["ruin-maker-fluids"], player_index)
  discard_selection(player_index)
end

script.on_event(defines.events.on_gui_click, function(event)
  if event.element.name == "ruin-maker-confirm" then
    confirm_selection(event.player_index, storage.selection[event.player_index].name.text)
    game.get_player(event.player_index).gui.screen["ruin-maker-main"].destroy()
  elseif event.element.name == "ruin-maker-cancel" then
    discard_selection(event.player_index)
    game.get_player(event.player_index).gui.screen["ruin-maker-main"].destroy()
  end
end)

script.on_event(defines.events.on_gui_checked_state_changed, function(event)
  if event.element.parent and event.element.parent.name == "ruin-maker-tile-filter" then
    storage.selection[event.player_index].tile_filter[event.element.name] = event.element.state
  elseif event.element.parent and event.element.parent.name == "ruin-maker-config" then
    storage.selection[event.player_index][event.element.name] = event.element.state
  end
end)

script.on_event(defines.events.on_gui_confirmed, function(event)
  if not storage.selection[event.player_index] then return end
  if event.element == storage.selection[event.player_index].name then
    confirm_selection(event.player_index, event.element.text)
    game.get_player(event.player_index).gui.screen["ruin-maker-main"].destroy()
  end
end)

local function config_gui(player, tile_names, area)
  local gui = player.gui.screen.add{type = "frame", caption = {"gui.ruin-maker-config"}, direction = "vertical", name = "ruin-maker-main"}
  gui.force_auto_center()
  gui = gui.add{type = "frame", style = "inside_shallow_frame_with_padding"}
  gui = gui.add{type = "table", name = "ruin-maker-config", style = "bordered_table", column_count = 1}

  do
    local w = area.right_bottom.x - area.left_top.x
    local h = area.right_bottom.y - area.left_top.y
    local name = "too big"
    if w <= 8 and h <= 8 then
      name = "small"
    elseif w <= 16 and h <= 16 then
      name = "medium"
    elseif w <= 32 and h <= 32 then
      name = "large"
    end

    local flow = gui.add{type="flow", direction = "vertical"}
    flow.add{type = "label", caption = {"gui.ruin-maker-size", name, w, h}}
  end

  do
    local flow = gui.add{type="flow", direction = "vertical"}
    flow.add{type = "label", caption = {"gui.ruin-maker-name"}}
    storage.selection[player.index].name = flow.add{type = "textfield"}
    storage.selection[player.index].name.focus()
  end

  if next(tile_names) ~= nil then
    local frame = gui.add{type="flow", name = "ruin-maker-tile-filter", direction = "vertical"}
    frame.add{type = "label", caption = {"gui.ruin-maker-tile-filter"}}
    for tile_name in pairs(tile_names) do
      frame.add{type = "checkbox", name = tile_name, caption = tile_name, state = true}
    end
  end

  gui.add{type = "checkbox", name = "ruin-maker-damage", caption = {"gui.ruin-maker-damage"}, state = true}
  gui.add{type = "checkbox", name = "ruin-maker-items", caption = {"gui.ruin-maker-items"}, state = true}
  gui.add{type = "checkbox", name = "ruin-maker-fluids", caption = {"gui.ruin-maker-fluids"}, state = true}

  gui.add{type = "button", name = "ruin-maker-cancel", caption = {"gui.ruin-maker-cancel"}}
  gui.add{type = "button", name = "ruin-maker-confirm", caption = {"gui.ruin-maker-confirm"}}
end

local function configure_selection(entities, tiles, area, center, player_index, renders)
  local tile_names = {}
  for _, tile in pairs(tiles) do
    tile_names[tile.name] = true
  end

  storage.selection[player_index] = {
    entities = entities,
    tiles = tiles,
    tile_filter = tile_names,
    center = center,
    renders = renders,
    ["ruin-maker-damage"] = true,
    ["ruin-maker-items"] = true,
    ["ruin-maker-fluids"] = true
  }

  config_gui(game.get_player(player_index), tile_names, area)
end

local function render_selection(area, center, surface)
  local renders = {}
  renders[#renders+1] = rendering.draw_line(
  {
    from = {center.x + 0.5, center.y},
    to = {center.x - 0.5, center.y},
    width = 4,
    color = {1, 1, 1},
    surface = surface
  })
  renders[#renders+1] = rendering.draw_line(
  {
    from = {center.x, center.y + 0.5},
    to = {center.x, center.y - 0.5},
    width = 4,
    color = {1, 1, 1},
    surface = surface
  })
  renders[#renders+1] = rendering.draw_rectangle(
  {
    left_top = area.left_top,
    right_bottom  = area.right_bottom,
    filled = false,
    width = 4,
    color = {1, 1, 1},
    surface = surface
  })
  return renders
end

script.on_event({defines.events.on_player_selected_area, defines.events.on_player_alt_selected_area}, function(event)
  if event.item ~= "ruin-maker" then return end
  if storage.selection[event.player_index] ~= nil then
    game.get_player(event.player_index).print({"error.ruin-maker-already-in-progress"})
    return
  end

  local area = util.expand_area_to_tile_border(event.area)
  local center = util.get_center_of_area(area)

  local renders = render_selection(area, center, event.surface)

  configure_selection(event.entities, event.tiles, area, center, event.player_index, renders)
end)

script.on_init(function()
  storage.selection = {}
end)
User avatar
IsaacOscar
Filter Inserter
Filter Inserter
Posts: 843
Joined: Sat Nov 09, 2024 2:36 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by IsaacOscar »

After comparing your code to the original code, I noticed in your data.lua:
You changed the line

Code: Select all

item_to_spawn = "ruin-maker",
to

Code: Select all

item_to_spawn = "give-ruin-maker",
But there's no such item as give-ruin-maker.

(You also removed style = "blue" and added associated_control_input = "give-ruin-maker", but they shouldn't make much difference).
Keysivi
Fast Inserter
Fast Inserter
Posts: 110
Joined: Mon Feb 07, 2022 5:29 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by Keysivi »

You were right. My damned carelessness!!!!

I returned back

Code: Select all

item_to_spawn = "ruin-maker"
and

Code: Select all

style = "blue"
But left

Code: Select all

associated_control_input = "give-ruin-maker"
The window opened but when I clicked "Confirm, output ruin to file" an error appeared

Code: Select all

The mod Ruin maker (0.1.3) caused a non-recoverable error.
Please report this error to the mod author.

Error while running event ruin-maker::on_gui_click (ID 1)
LuaEntity API call when LuaEntity was invalid.
stack traceback:
 [C]: in function '__index'
 __ruin-maker__/output.lua:37: in function 'create_entity'
 __ruin-maker__/output.lua:87: in function 'output_selection'
 __ruin-maker__/control.lua:13: in function 'confirm_selection'
 __ruin-maker__/control.lua:19: in function <__ruin-maker__/control.lua:17>
Keysivi
Fast Inserter
Fast Inserter
Posts: 110
Joined: Mon Feb 07, 2022 5:29 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by Keysivi »

I don't think I changed anything in output.lua. Here are the functions the game complains about

Code: Select all

 for _, entity in pairs(entities) do
    local vec = util.vector_from_center(entity.position, center)

    out[#out+1] = "    {\"" .. entity.name .. "\", "
    out[#out+1] = "{x = " .. vec.x .. ", y = " .. vec.y .. "}, "

    out[#out+1] = "{" -- extra options start

    local dir = entity.direction
    if dir ~= defines.direction.north then
      out[#out+1] = "dir = \"" .. util.direction_to_str(dir) .. "\", "
    end
    if entity.is_entity_with_owner then
      if entity.force.name ~= "player" and entity.force.name ~= "neutral" then
        out[#out+1] = "force = \"enemy\", "
      end
    end
    if damage and entity.is_entity_with_health and (entity.get_health_ratio() ~= 1) then
      local dmg = math.floor(entity.prototype.max_health - entity.health)
      out[#out+1] = "dmg = {dmg = " .. dmg .. "}, "
    end
    if items and entity.has_items_inside() then
      local inv = nil
      if entity.type == "container" or entity.type == "logistic-container" then
        inv = entity.get_inventory(defines.inventory.chest)
      elseif entity.type == "ammo-turret" then
        inv = entity.get_inventory(defines.inventory.turret_ammo)
      end
      if inv then
        out[#out+1] = "items = " .. serpent.line(inv.get_contents()) .. ", "
      end
    end
    if fluids and entity.get_fluid_count() > 0 then
      out[#out+1] = "fluids = " .. serpent.line(entity.get_fluid_contents()) .. ", "
    end
    if entity.type == "assembling-machine" then
      local recipe = entity.get_recipe()
      if recipe then
        out[#out+1] = "recipe = \"" .. recipe.name .. "\", "
      end
    end
    out[#out+1] = "}},\n" -- extra options and entity end
  end

  out[#out+1] = "  },\n"
end

output = function(entities, tiles, tile_filter, center, name, damage, items, fluids, player_index)
  local out = {}
  out[1] = "return\n"
  out[2] = "{\n"
  create_entity(entities, center, damage, items, fluids, out)
  set_tiles(tiles, tile_filter, center, out)

  if out[3] == nil then
    game.get_player(player_index).print("Nothing selected")
    return
  end

  out[#out+1] = "}\n"
  game.write_file("ruins/" .. name .. ".lua", table.concat(out))
end

But in control.lua I changed 'global' to 'storage'

Code: Select all

local function confirm_selection(player_index, name)
  local data = storage.selection[player_index]
  output_selection(data.entities, data.tiles, data.tile_filter, data.center, name ~= "" and name or "unknown", data["ruin-maker-damage"], data["ruin-maker-items"], data["ruin-maker-fluids"], player_index)
  discard_selection(player_index)
end

script.on_event(defines.events.on_gui_click, function(event)
  if event.element.name == "ruin-maker-confirm" then
    confirm_selection(event.player_index, storage.selection[event.player_index].name.text)
    game.get_player(event.player_index).gui.screen["ruin-maker-main"].destroy()
  elseif event.element.name == "ruin-maker-cancel" then
    discard_selection(event.player_index)
    game.get_player(event.player_index).gui.screen["ruin-maker-main"].destroy()
  end
end)
User avatar
IsaacOscar
Filter Inserter
Filter Inserter
Posts: 843
Joined: Sat Nov 09, 2024 2:36 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by IsaacOscar »

Keysivi wrote: Tue Dec 17, 2024 4:08 pm I don't think I changed anything in output.lua. Here are the functions the game complains about

Code: Select all

 for _, entity in pairs(entities) do
    local vec = util.vector_from_center(entity.position, center)

    out[#out+1] = "    {\"" .. entity.name .. "\", "
    out[#out+1] = "{x = " .. vec.x .. ", y = " .. vec.y .. "}, "

    out[#out+1] = "{" -- extra options start

    local dir = entity.direction
    if dir ~= defines.direction.north then
      out[#out+1] = "dir = \"" .. util.direction_to_str(dir) .. "\", "
    end
    if entity.is_entity_with_owner then
      if entity.force.name ~= "player" and entity.force.name ~= "neutral" then
        out[#out+1] = "force = \"enemy\", "
      end
    end
    if damage and entity.is_entity_with_health and (entity.get_health_ratio() ~= 1) then
      local dmg = math.floor(entity.prototype.max_health - entity.health)
      out[#out+1] = "dmg = {dmg = " .. dmg .. "}, "
    end
    if items and entity.has_items_inside() then
      local inv = nil
      if entity.type == "container" or entity.type == "logistic-container" then
        inv = entity.get_inventory(defines.inventory.chest)
      elseif entity.type == "ammo-turret" then
        inv = entity.get_inventory(defines.inventory.turret_ammo)
      end
      if inv then
        out[#out+1] = "items = " .. serpent.line(inv.get_contents()) .. ", "
      end
    end
    if fluids and entity.get_fluid_count() > 0 then
      out[#out+1] = "fluids = " .. serpent.line(entity.get_fluid_contents()) .. ", "
    end
    if entity.type == "assembling-machine" then
      local recipe = entity.get_recipe()
      if recipe then
        out[#out+1] = "recipe = \"" .. recipe.name .. "\", "
      end
    end
    out[#out+1] = "}},\n" -- extra options and entity end
  end

  out[#out+1] = "  },\n"
end

output = function(entities, tiles, tile_filter, center, name, damage, items, fluids, player_index)
  local out = {}
  out[1] = "return\n"
  out[2] = "{\n"
  create_entity(entities, center, damage, items, fluids, out)
  set_tiles(tiles, tile_filter, center, out)

  if out[3] == nil then
    game.get_player(player_index).print("Nothing selected")
    return
  end

  out[#out+1] = "}\n"
  game.write_file("ruins/" .. name .. ".lua", table.concat(out))
end

But in control.lua I changed 'global' to 'storage'

Code: Select all

local function confirm_selection(player_index, name)
  local data = storage.selection[player_index]
  output_selection(data.entities, data.tiles, data.tile_filter, data.center, name ~= "" and name or "unknown", data["ruin-maker-damage"], data["ruin-maker-items"], data["ruin-maker-fluids"], player_index)
  discard_selection(player_index)
end

script.on_event(defines.events.on_gui_click, function(event)
  if event.element.name == "ruin-maker-confirm" then
    confirm_selection(event.player_index, storage.selection[event.player_index].name.text)
    game.get_player(event.player_index).gui.screen["ruin-maker-main"].destroy()
  elseif event.element.name == "ruin-maker-cancel" then
    discard_selection(event.player_index)
    game.get_player(event.player_index).gui.screen["ruin-maker-main"].destroy()
  end
end)
Hey, can you just attach your output.lua file here please?
Keysivi
Fast Inserter
Fast Inserter
Posts: 110
Joined: Mon Feb 07, 2022 5:29 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by Keysivi »

I'm attaching the file. I didn't change anything in it though.
Attachments
output.lua
(3.08 KiB) Downloaded 17 times
User avatar
IsaacOscar
Filter Inserter
Filter Inserter
Posts: 843
Joined: Sat Nov 09, 2024 2:36 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by IsaacOscar »

Keysivi wrote: Tue Dec 17, 2024 4:03 pm The window opened but when I clicked "Confirm, output ruin to file" an error appeared

Code: Select all

The mod Ruin maker (0.1.3) caused a non-recoverable error.
Please report this error to the mod author.

Error while running event ruin-maker::on_gui_click (ID 1)
LuaEntity API call when LuaEntity was invalid.
stack traceback:
 [C]: in function '__index'
 __ruin-maker__/output.lua:37: in function 'create_entity'
 __ruin-maker__/output.lua:87: in function 'output_selection'
 __ruin-maker__/control.lua:13: in function 'confirm_selection'
 __ruin-maker__/control.lua:19: in function <__ruin-maker__/control.lua:17>
Very strange. I couldn't see anything wrong with the code, so I tried to load it in factorio and couldn't reproduce your error. Can you zip your mod up and post it here so I can test it?

Also in control.lua you need to change

Code: Select all

rendering.destroy(render)
to

Code: Select all

render.destroy()

Keysivi wrote: Tue Dec 17, 2024 4:08 pm I don't think I changed anything in output.lua. Here are the functions the game complains about
I checked, and you didn't change anything, but you should have changed:

Code: Select all

game.write_file
to

Code: Select all

helpers.write_file
Keysivi wrote: Tue Dec 17, 2024 4:08 pm But in control.lua I changed 'global' to 'storage'
Yes, that is the correct thing to do.
Keysivi
Fast Inserter
Fast Inserter
Posts: 110
Joined: Mon Feb 07, 2022 5:29 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by Keysivi »

Very strange. I couldn't see anything wrong with the code, so I tried to load it in factorio and couldn't reproduce your error. Can you zip your mod up and post it here so I can test it?
Here is the archive with the mod. I haven't made your edits yet.

As for the rest, I'll make your edits now and test it.
Attachments
ruin-maker_0.1.3.zip
(51.76 KiB) Downloaded 16 times
User avatar
IsaacOscar
Filter Inserter
Filter Inserter
Posts: 843
Joined: Sat Nov 09, 2024 2:36 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by IsaacOscar »

Ok, so I can't reproduce your error.
My guess is it doesn't like whatever entities you are selecting.
User avatar
IsaacOscar
Filter Inserter
Filter Inserter
Posts: 843
Joined: Sat Nov 09, 2024 2:36 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by IsaacOscar »

You can put a check that entity.valid holds in that loop to skip problematic entities.
if you want to know exactly what code to write
Keysivi
Fast Inserter
Fast Inserter
Posts: 110
Joined: Mon Feb 07, 2022 5:29 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by Keysivi »

I made the corrections you suggested - the error disappeared. The selected ruins were saved to the file.

Now I will try to test with mods, and then run the resulting file in the game.
Keysivi
Fast Inserter
Fast Inserter
Posts: 110
Joined: Mon Feb 07, 2022 5:29 pm
Contact:

Re: Strange problem with the "Ruin maker" mod

Post by Keysivi »

Sorry for the delay. I created a few test ruins, tested them - everything works. I didn't find any more bugs.

There was one hitch, but it turned out to be related to the settings of one entity...

Thank you very much for your help and patience! I wouldn't have managed it myself.

Unfortunately, the author of the mod - Bilka - ignores my requests. So I decided to post the updated mods as a fork.
Post Reply

Return to “Modding help”