Skip to content
The Chat Archive
gpt-4-0314· OpenAI WildChat-4.8M (AI2)

Heres some LUA code of a Factorio mod. Can you find some mistakes and fix it? It is…

  1. User

    Heres some LUA code of a Factorio mod. Can you find some mistakes and fix it? It is supposed to create chests which are linked together based on an ID set in the inventories input field.

  2. Assistant

    As an AI language model, I can't interactively troubleshoot or directly see your code. Please copy and paste the relevant LUA code here, and I'll help you identify mistakes and suggest possible improvements.

  3. User

    require "util" -- Initialize the global table if it doesn't exist if not global then global = {} end

    local GRAPHICS = "linked-6-chests/graphics" local ICONS = GRAPHICS .. "/icons" local BASE_LINKED_CHEST = GRAPHICS .. "/entity/linked-chests"

    local LINKED_CHEST_BASED = "iron-chest"

    -- Define global table to hold linked chest entities global.linked_chests = {}

    -- Function to create a new linked chest based on the given name and ID local function new_linked_chest(name, id) local chest_id = "linked-chest-" .. id .. "-" .. name local icon = ICONS .. "/linked-chest-" .. name .. "-icon.png"

    local item = util.table.deepcopy(data.raw["item"][LINKED_CHEST_BASED])
    item.name = chest_id
    item.icon = icon
    item.place_result = chest_id
    
    local entity = util.table.deepcopy(data.raw["container"][LINKED_CHEST_BASED])
    entity.type = "linked-container"
    entity.name = chest_id
    entity.minable.result = chest_id
    entity.circuit_wire_connection_point = nil
    entity.circuit_connector_sprites = nil
    entity.circuit_wire_max_distance = nil
    entity.inventory_size = 5000
    entity.icon = icon
    entity.picture = {
    	layers = {
    		{
    			filename = BASE_LINKED_CHEST .. "/linked-chest-" .. name .. ".png",
    			priority = "extra-high",
    			width = 34,
    			height = 38,
    			frame_count = 7,
    			shift = util.by_pixel(0, -2),
    			hr_version = {
    				filename = BASE_LINKED_CHEST .. "/hr-linked-chest-" .. name .. ".png",
    				priority = "extra-high",
    				width = 66,
    				height = 74,
    				frame_count = 7,
    				shift = util.by_pixel(0, -2),
    				scale = 0.5
    			}
    		},
    		{
    			filename = BASE_LINKED_CHEST .. "/linked-chest-shadow.png",
    			priority = "extra-high",
    			width = 56,
    			height = 24,
    			repeat_count = 7,
    			shift = util.by_pixel(12, 5),
    			draw_as_shadow = true,
    			hr_version = {
    				filename = BASE_LINKED_CHEST .. "/hr-linked-chest-shadow.png",
    				priority = "extra-high",
    				width = 112,
    				height = 46,
    				repeat_count = 7,
    				shift = util.by_pixel(12, 4.5),
    				draw_as_shadow = true,
    				scale = 0.5
    			}
    		}
    	},
    }
    
    local recipe = {
    	type = "recipe",
    	name = chest_id,
    	result = chest_id,
    	icon = icon,
    	icon_size = 64,
    	enabled = true,
    	ingredients = { {LINKED_CHEST_BASED, 1} },
    }
    
    return item, entity, recipe
    

    end

    -- Define a new event handler for the 'on_built_entity' and 'on_robot_built_entity' events local function on_built_linked_chest(event) local entity = event.created_entity

    -- If the entity is a linked chest
    if entity.name:find("linked%-chest%-.+") then
        -- Check if there is an inventory in the chest table with the same ID
        local linked_chest_id = entity.linked_chest_id
        if linked_chest_id then
            local linked_chests = global.linked_chests[entity.force.name]
            for _, chest in pairs(linked_chests) do
                if chest ~= entity and chest.valid then
                    local chest_id = chest.linked_chest_id
                    if chest_id and chest_id == linked_chest_id then
                        -- If a linked chest with the same ID is found, link the two chests
                        entity.linked_chest = chest
                        chest.linked_chest = entity
                        break
                    end
                end
            end
        end
    end
    

    end

    script.on_event({defines.events.on_built_entity, defines.events.on_robot_built_entity}, on_built_linked_chest)

    -- Check if there is an inventory in the chest table with the same ID for _, chest in pairs(linked_chests) do if chest ~= entity and chest.valid then local inv = chest.get_inventory(inventory.get_inventory(defines.inventory.chest)) if inv and inv ~= inventory then inventory.set_filter(1, inv.get_filter(1)) inventory.set_bar(inv.get_bar()) inv.set_filter(1, nil) inv.set_bar(nil) inventory.set_linked_chest(chest) break end end end

    -- Add the new chest to the inventory table table.insert(linked_chests, entity)

  4. Assistant

    I have identified some potential issues and improvements in your code. Here is the revised code with corrections:

    require "util"
    
    -- Initialize the global table for linked chests if it doesn't exist
    if not global.linked_chests then
      global.linked_chests = {}
    end
    
    local GRAPHICS = "__linked-6-chests__/graphics"
    local ICONS = GRAPHICS .. "/icons"
    local BASE_LINKED_CHEST = GRAPHICS .. "/entity/linked-chests"
    
    local LINKED_CHEST_BASED = "iron-chest"
    
    -- Define global table to hold linked chest entities for each force
    for _, force in pairs(game.forces) do
      if not global.linked_chests[force.name] then
        global.linked_chests[force.name] = {}
      end
    end
    
    -- Function to create a new linked chest based on the given name and ID
    local function new_linked_chest(name, id)
      -- (existing code remains unchanged)
    end
    
    -- Define a new event handler for the 'on_built_entity' and 'on_robot_built_entity' events
    local function on_built_linked_chest(event)
      local entity = event.created_entity
    
      -- If the entity is a linked chest
      if entity.name:find("linked%-chest%-.+") then
        local force_name = entity.force.name
    
        -- Check if there is an inventory in the chest table with the same ID
        local linked_chest_id = entity.linked_chest_id
    
        if linked_chest_id then
          local linked_chests = global.linked_chests[force_name]
    
          for _, chest in pairs(linked_chests) do
            if chest ~= entity and chest.valid then
              local chest_id = chest.linked_chest_id
              if chest_id and chest_id == linked_chest_id then
                -- If a linked chest with the same ID is found, link the two chests
                entity.linked_chest = chest
                chest.linked_chest = entity
                break
              end
            end
          end
    
          -- Add the new chest to the inventory table
          table.insert(global.linked_chests[force_name], entity)
        end
      end
    end
    
    script.on_event({defines.events.on_built_entity, defines.events.on_robot_built_entity}, on_built_linked_chest)
    
    -- Remove the following redundant piece of code
    
    --[[
    for _, chest in pairs(linked_chests) do
      if chest ~= entity and chest.valid then
        local inv = chest.get_inventory(inventory.get_inventory(defines.inventory.chest))
        if inv and inv ~= inventory then
          inventory.set_filter(1, inv.get_filter(1))
          inventory.set_bar(inv.get_bar())
          inv.set_filter(1, nil)
          inv.set_bar(nil)
          inventory.set_linked_chest(chest)
          break
        end
      end
    end
    
    -- Add the new chest to the inventory table
    table.insert(linked_chests, entity)
    ]]
    

    Summary of changes:

    1. Add a loop to initialize the global.linked_chests table for each force in the game.
    2. Replace linked_chests with global.linked_chests[force_name] throughout the code, to properly index linked chests by force name.
    3. Move the code for adding the new chest to the inventory table within the on_built_linked_chest function after checking for existing linked chests with the same ID. This ensures that the new chest is properly added to the global table.
    4. Remove the redundant piece of code at the end of the script, as this logic has been moved to the on_built_linked_chest function.
  5. User

    I've done the recommended changes. But now I get this error 1.247 Error ModManager.cpp:1560: Failed to load mod "linked-6-chests": __linked-6-chests__/data.lua:3: attempt to index global 'global' (a nil value) stack traceback: __linked-6-chests__/data.lua:3: in main chunk

  6. Assistant

    My apologies for the confusion. The global variable is not available during data phase; it's only available during runtime. To properly initialize the linked chests data, you should do that in the on_load and on_configuration_changed events. Here is the updated code:

    require "util"
    
    local GRAPHICS = "__linked-6-chests__/graphics"
    local ICONS = GRAPHICS .. "/icons"
    local BASE_LINKED_CHEST = GRAPHICS .. "/entity/linked-chests"
    
    local LINKED_CHEST_BASED = "iron-chest"
    
    -- Function to create a new linked chest based on the given name and ID
    local function new_linked_chest(name, id)
      -- (existing code remains unchanged)
    end
    
    -- Define a new event handler for the 'on_built_entity' and 'on_robot_built_entity' events
    local function on_built_linked_chest(event)
      -- (existing code remains unchanged)
    end
    
    script.on_event({defines.events.on_built_entity, defines.events.on_robot_built_entity}, on_built_linked_chest)
    
    -- Initialize the global table for linked chests for each force in the given forces
    local function create_linked_chests(forces)
        for _, force in pairs(forces) do
            if not global.linked_chests[force.name] then
                global.linked_chests[force.name] = {}
            end
        end
    end
    
    local function on_load()
        if not global.linked_chests then
            global.linked_chests = {}
        end
    end
    
    -- Event handler to initialize the linked chest data or update the data for new forces
    local function on_configuration_changed(event)
        if not global.linked_chests then
            global.linked_chests = {}
        end
    
        local forces = event and event.new_forces or game.forces
        create_linked_chests(forces)
    end
    
    script.on_load(on_load)
    script.on_configuration_changed(on_configuration_changed)
    

    Summary of changes:

    1. Remove the initialization of the global.linked_chests table at the top of the script.
    2. Add on_load() function to create the global.linked_chests table if it doesn't exist.
    3. Add on_configuration_changed(event) function to initialize or update the global.linked_chests table for new forces.
    4. Register on_load() and on_configuration_changed(event) functions with the script.on_load() and script.on_configuration_changed() events, respectively.

    This way, the code ensures that the global.linked_chests table is properly initialized during the runtime phase instead of the data phase.