442 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			442 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local delaydestroy = require "delaydestroy"
 | |
| local inserter_config = require "inserterconfig"
 | |
| local util = require "util"
 | |
| local version = require "version"
 | |
| 
 | |
| local M = {}
 | |
| 
 | |
| local all_migrations = {}
 | |
| 
 | |
| local function add_migration(migration)
 | |
|   all_migrations[#all_migrations+1] = migration
 | |
| end
 | |
| 
 | |
| function M.on_mod_version_changed(old)
 | |
|   old = version.parse(old)
 | |
|   for _, migration in ipairs(all_migrations) do
 | |
|     if version.between(old, migration.low, migration.high) then
 | |
|       log("running world migration "..migration.name)
 | |
|       migration.task()
 | |
|     end
 | |
|   end
 | |
| end
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_3_0_change_work_queue_name",
 | |
|   low = {0,0,0},
 | |
|   high = {0,3,0},
 | |
|   task = function()
 | |
|     global.unconfigured_loaders = {}
 | |
|     local t = global.unconfigured_loaders
 | |
|     for _, e in ipairs(global.unconfigured_inserters) do
 | |
|       if e.valid then
 | |
|         local loader = e.surface.find_entities_filtered{
 | |
|           type = "container",
 | |
|           position = e.position,
 | |
|           force = e.force,
 | |
|         }[1]
 | |
|         t[#t+1] = loader
 | |
|       end
 | |
|     end
 | |
|     global.unconfigured_inserters = nil
 | |
|     global.unconfigured_inserters_iter = nil
 | |
|     inserter_config.on_load()
 | |
|   end,
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_3_0_add_additional_inserters",
 | |
|   low = {0,0,0},
 | |
|   high = {0,3,0},
 | |
|   task = function()
 | |
|     for _, s in pairs(game.surfaces) do
 | |
|       for _, e in ipairs(s.find_entities_filtered{type = "inserter"}) do
 | |
|         if string.find(e.name, "railu?n?loader%-.*inserter") then
 | |
|           local new_inserter = s.create_entity{
 | |
|             name = e.name,
 | |
|             position = e.position,
 | |
|             direction = e.direction,
 | |
|             force = e.force
 | |
|           }
 | |
|           new_inserter.destructible = false
 | |
|           for i=1,e.filter_slot_count do
 | |
|             new_inserter.set_filter(i, e.get_filter(i))
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end,
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_3_7_add_ghost_registry",
 | |
|   low = {0,0,0},
 | |
|   high = {0,3,7},
 | |
|   task = function()
 | |
|     global.ghosts = {}
 | |
|   end,
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_4_0_add_delayed_destroy_queue",
 | |
|   low = {0,0,0},
 | |
|   high = {0,4,0},
 | |
|   task = function()
 | |
|     global.entities_to_destroy = {}
 | |
|   end,
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_4_0_change_unconfigured_loader_queue_indexing",
 | |
|   low = {0,0,0},
 | |
|   high = {0,4,0},
 | |
|   task = function()
 | |
|     local new = {}
 | |
|     for _, v in pairs(global.unconfigured_loaders) do
 | |
|       if v.valid then
 | |
|         new[v.unit_number] = v
 | |
|       end
 | |
|     end
 | |
|     global.unconfigured_loaders = new
 | |
|     global.unconfigured_loaders_iter = nil
 | |
|   end,
 | |
| }
 | |
| 
 | |
| local function update_proxy_direction(entity)
 | |
|   local is_ns = entity.direction == defines.direction.east or defines.direction.west
 | |
|   entity.direction = is_ns and defines.direction.east or defines.direction.north
 | |
| end
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_4_0_relocate_proxy_ghosts",
 | |
|   low = {0,0,0},
 | |
|   high = {0,4,0},
 | |
|   task = function()
 | |
|     for _, s in pairs(game.surfaces) do
 | |
|       local ghosts = s.find_entities_filtered{
 | |
|         name = "entity-ghost",
 | |
|       }
 | |
|       for _, g in ipairs(ghosts) do
 | |
|         if g.valid and g.ghost_name:find("^railu?n?loader%-placement%-proxy$") then
 | |
|           local old_position_key = util.position_key(g)
 | |
| 
 | |
|           --re-orient
 | |
|           local new_position = util.moveposition(g.position, util.offset(g.direction, 1.5, 0))
 | |
|           g.teleport(new_position)
 | |
|           update_proxy_direction(g)
 | |
| 
 | |
|           -- fix up any recorded circuit connections
 | |
|           local new_position_key = util.position_key(g)
 | |
|           local connections = global.ghosts[old_position_key]
 | |
|           if connections then
 | |
|             global.ghosts[new_position_key] = connections
 | |
|             global.ghosts[old_position_key] = nil
 | |
|           end
 | |
| 
 | |
|           -- remove any underlying rail ghosts
 | |
|           local rail_ghosts = s.find_entities_filtered{
 | |
|             name = "entity-ghost",
 | |
|             ghost_type = "straight-rail",
 | |
|             area = g.bounding_box,
 | |
|           }
 | |
|           for _, rg in ipairs(rail_ghosts) do
 | |
|             rg.destroy()
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| }
 | |
| 
 | |
| --[[
 | |
|   foreach player
 | |
|     foreach inventory
 | |
|       foreach slot
 | |
|   foreach surface
 | |
|     foreach entity
 | |
|       foreach inventory
 | |
|         foreach slot
 | |
| ]]
 | |
| local function all_blueprints()
 | |
|   local next_player
 | |
|   do
 | |
|     local f, s, var = pairs(game.players)
 | |
|     next_player = function()
 | |
|       local player
 | |
|       var, player = f(s, var)
 | |
|       return player
 | |
|     end
 | |
|   end
 | |
|   local next_surface
 | |
|   do
 | |
|     local f, s, var = pairs(game.surfaces)
 | |
|     next_surface = function()
 | |
|       local surface
 | |
|       var, surface = f(s, var)
 | |
|       return surface
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   local max_inventory_id = 1
 | |
|   for _, inventory_id in pairs(defines.inventory) do
 | |
|     if inventory_id > max_inventory_id then
 | |
|       max_inventory_id = inventory_id
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   local done_with_players = false
 | |
|   local entity = next_player()
 | |
|   local entities
 | |
|   local entities_iter
 | |
|   local inventories_iter = 0
 | |
|   local inventory
 | |
|   local inventory_iter -- starting slot of inventory to examine on next execution
 | |
|   local item_inventory
 | |
|   local item_inventory_iter
 | |
| 
 | |
|   local iter
 | |
|   iter = function()
 | |
|     if item_inventory then
 | |
|       for i=item_inventory_iter,#item_inventory do
 | |
|         local stack = item_inventory[i]
 | |
|         if stack.valid_for_read then
 | |
|           log("item-with-inventory slot " .. i .. " contains " .. stack.name)
 | |
|         end
 | |
|         if stack.valid_for_read and stack.name == "blueprint" then
 | |
|           item_inventory_iter = i + 1
 | |
|           return stack
 | |
|         end
 | |
|       end
 | |
|       item_inventory = nil
 | |
|     end
 | |
| 
 | |
|     if inventory then
 | |
|       for i=inventory_iter,#inventory do
 | |
|         local stack = inventory[i]
 | |
|         if stack.valid_for_read then
 | |
|           if stack.name == "blueprint" then
 | |
|             log("inventory slot " .. i .. " contains " .. stack.name)
 | |
|             inventory_iter = i + 1
 | |
|             return stack
 | |
|           elseif stack.is_item_with_inventory then
 | |
|             log("examining item-with-inventory " .. stack.name .. " in slot " .. i)
 | |
|             inventory_iter = i + 1
 | |
|             item_inventory = stack.get_inventory(defines.inventory.item_main)
 | |
|             item_inventory_iter = 1
 | |
|             return iter()
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     -- search for next inventory
 | |
|     if entity then
 | |
|       while true do
 | |
|         inventories_iter = inventories_iter + 1
 | |
|         if inventories_iter > max_inventory_id then
 | |
|           break
 | |
|         end
 | |
|         inventory = entity.get_inventory(inventories_iter)
 | |
|         if inventory and not inventory.is_empty() then
 | |
|           log("examining inventory " .. inventories_iter .. " of entity " .. entity.name .. " (" .. util.position_key(entity) .. ")")
 | |
|           inventory_iter = 1
 | |
|           return iter()
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     -- ran out of inventories, look for next entity
 | |
|     if not done_with_players then
 | |
|       entity = next_player()
 | |
|       if not entity then
 | |
|         done_with_players = true
 | |
|         return iter()
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     if entities then
 | |
|       entities_iter, entity = next(entities, entities_iter)
 | |
|       if entity then
 | |
|         if entity.name == "item-on-ground" and entity.stack.name == "blueprint" then
 | |
|           log("found blueprint on ground (" .. util.position_key(entity) .. ")")
 | |
|           return entity.stack
 | |
|         else
 | |
|           inventories_iter = 0
 | |
|           return iter()
 | |
|         end
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     local surface = next_surface()
 | |
|     if not surface then
 | |
|       return nil
 | |
|     end
 | |
|     entities = surface.find_entities()
 | |
|     return iter()
 | |
|   end
 | |
| 
 | |
|   return iter
 | |
| end
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_4_0_relocate_blueprint_proxies",
 | |
|   low = {0,0,0},
 | |
|   high = {0,4,0},
 | |
|   task = function()
 | |
|     for bp in all_blueprints() do
 | |
|       if bp.is_blueprint_setup() then
 | |
|         local entities = bp.get_blueprint_entities()
 | |
|         if entities then
 | |
|           for _, e in ipairs(entities) do
 | |
|             if e.name:find("^railu?n?%loader%-placement%-proxy") then
 | |
|               log("updating " .. e.name .. " at " .. e.position.x .. "," .. e.position.y)
 | |
|               e.position = util.moveposition(e.position, util.offset(e.direction, 1.5, 0))
 | |
|               update_proxy_direction(e)
 | |
|               for k, e2 in ipairs(entities) do
 | |
|                 local prototype = game.entity_prototypes[e2.name]
 | |
|                 if prototype.type == "straight-rail" then
 | |
|                   if (e.direction == defines.direction.north
 | |
|                       and e2.position.x == e.position.x
 | |
|                       and e2.position.y <= e.position.y + 2
 | |
|                       and e2.position.y >= e.position.y - 2)
 | |
|                     or (e.direction == defines.direction.east
 | |
|                       and e2.position.y == e.position.y
 | |
|                       and e2.position.x <= e.position.x + 2
 | |
|                       and e2.position.x >= e.position.x - 2) then
 | |
|                     log("removing " .. e2.name .. " at " .. e2.position.x .. "," .. e2.position.y)
 | |
|                     entities[k] = nil
 | |
|                   end
 | |
|                 end
 | |
|               end
 | |
|             end
 | |
|           end
 | |
|           bp.set_blueprint_entities(entities)
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_5_0_circuit_connect_inserters",
 | |
|   low = {0,0,0},
 | |
|   high = {0,5,0},
 | |
|   task = function()
 | |
|     for _,s in pairs(game.surfaces) do
 | |
|       for _, chest in ipairs(s.find_entities_filtered{type="container"}) do
 | |
|         local type = util.railloader_type(chest.name)
 | |
|         if type then
 | |
|           for _, inserter_name in ipairs{"rail"..type.."-inserter", "rail"..type.."-universal-inserter"} do
 | |
|             for _, inserter in ipairs(s.find_entities_filtered{name = inserter_name, position = chest.position}) do
 | |
|               for _, wire_type in ipairs{"red", "green"} do
 | |
|                 inserter.connect_neighbour{
 | |
|                   target_entity = chest,
 | |
|                   wire = defines.wire_type[wire_type],
 | |
|                 }
 | |
|               end
 | |
|               local behavior = inserter.get_or_create_control_behavior()
 | |
|               behavior.circuit_condition = {
 | |
|                 condition = {
 | |
|                   comparator = "=",
 | |
|                   first_signal = {type = "virtual", name = "railloader-disable"},
 | |
|                 }
 | |
|               }
 | |
|             end
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v0_5_2_circuit_connect_interface_inserters",
 | |
|   low = {0,0,0},
 | |
|   high = {0,5,2},
 | |
|   task = function()
 | |
|     for _,s in pairs(game.surfaces) do
 | |
|       for _, chest in ipairs(s.find_entities_filtered{type="container"}) do
 | |
|         local type = util.railloader_type(chest.name)
 | |
|         if type then
 | |
|           local inserter_name = "rail"..type.."-interface-inserter"
 | |
|           for _, inserter in ipairs(s.find_entities_filtered{name = inserter_name, position = chest.position}) do
 | |
|             for _, wire_type in ipairs{"red", "green"} do
 | |
|               inserter.connect_neighbour{
 | |
|                 target_entity = chest,
 | |
|                 wire = defines.wire_type[wire_type],
 | |
|               }
 | |
|             end
 | |
|             local behavior = inserter.get_or_create_control_behavior()
 | |
|             behavior.circuit_condition = {
 | |
|               condition = {
 | |
|                 comparator = "=",
 | |
|                 first_signal = {type = "virtual", name = "railloader-disable"},
 | |
|               }
 | |
|             }
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v1_0_6_remove_ghost_registry",
 | |
|   low = {0,0,0},
 | |
|   high = {1,0,6},
 | |
|   task = function()
 | |
|     global.ghosts = nil
 | |
|   end
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "v1_1_0_add_previous_blueprint_global",
 | |
|   low = {0,0,0},
 | |
|   high = {1,1,0},
 | |
|   task = function()
 | |
|     global.previous_opened_blueprint_for = {}
 | |
|   end
 | |
| }
 | |
| 
 | |
| add_migration{
 | |
|   name = "remove_orphan_structures",
 | |
|   low = {0,0,0},
 | |
|   high = {99,0,0},
 | |
|   task = function()
 | |
|     for _,s in pairs(game.surfaces) do
 | |
|       for _,e in ipairs(s.find_entities_filtered{type="simple-entity"}) do
 | |
|         local type = util.railloader_type(e.name)
 | |
|         if type then
 | |
|           local proto = game.entity_prototypes["rail" .. type .. "-chest"]
 | |
|           local brl = s.find_entity(proto.name, e.position)
 | |
|           if not brl then
 | |
|             local area = {
 | |
|               left_top = {
 | |
|                 e.position.x + proto.collision_box.left_top.x,
 | |
|                 e.position.y + proto.collision_box.left_top.y,
 | |
|               },
 | |
|               right_bottom = {
 | |
|                 e.position.x + proto.collision_box.right_bottom.x,
 | |
|                 e.position.y + proto.collision_box.right_bottom.y,
 | |
|               },
 | |
|             }
 | |
|             for _, ent in ipairs(s.find_entities_filtered{area = area}) do
 | |
|               if ent.type == "inserter" then
 | |
|                 ent.destroy()
 | |
|               elseif string.find(ent.name, "^railu?n?loader%-structure") then
 | |
|                 ent.destroy()
 | |
|               elseif ent.type == "straight-rail" then
 | |
|                 local success = ent.destroy()
 | |
|                 if not success then
 | |
|                   delaydestroy.register_to_destroy(ent)
 | |
|                 end
 | |
|               end
 | |
|             end
 | |
|           end
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end,
 | |
| }
 | |
| 
 | |
| return M |