Don't worry anymore, i finished the mod and so far at least in singleplayer everything is working as i hoped. Again a big thank you for making this mod possible. As i said, i thanked you in the mod description, eradicator (
https://mods.factorio.com/mod/logistic-chest-overflow). I've learned some lessons, if i don't know what to do about a problem, i'll ask for help instead of stating it a bug and i'll only ask for help if i really need help instead of everytime there's a problem i can't solve in a few hours. In case anybody wants to know without downloading the mod, this is my final code for version 0.1.0:
Code: Select all
--setting up the globals. We need all modded chests and their request slots.
script.on_init(function()
if global.reqtable == nil then
global.reqtable = {}
end
global.chests = game.surfaces.find_entities_filtered{type = "logistic-container", name = {"logistic-chest-overflow", "logistic-chest-overflow-provider"}} or {}
end)
--fast replace a chest with another and delete the old one from global.chests We need to do this manually because create_entity won't call on_script_raised_destroy.
function switchchests(fromchest, toname, frompos, key)
if fromchest.valid == true then
global.chests[key] = nil
return fromchest.surface.create_entity{name=toname, position=frompos, force=fromchest.force, fast_replace=true, raise_built=true, player=nil, spill=false}
end
end
-- the main logic
function main(event)
--every 30 ticks which means twice a second
if event.tick % 30 == 0 then
--check all chests
if global.chests ~= nil then
for k, chest in pairs(global.chests) do
if chest.valid == true then
if chest.to_be_deconstructed(chest.force) == false then
local pos = {chest.position.x, chest.position.y}
local i = 0
local chestID = chest.unit_number
if chest.name == "logistic-chest-overflow" then
for slot = 1, 12 do
if chest.get_request_slot(slot) ~= nil then
--has the request been satisfied?
if chest.get_request_slot(slot).count <= chest.get_item_count(chest.get_request_slot(slot).name) then
i = 1
break
end
end
end
end
if chest.name == "logistic-chest-overflow-provider" then
for slot = 1, 12 do
if global.reqtable[chestID] ~= nil then
if global.reqtable[chestID][slot] ~= nil then
--has the request been satisfied?
if global.reqtable[chestID][slot][2] <= chest.get_item_count(global.reqtable[chestID][slot][1]) then
i = 1
break
end
end
end
end
end
--if it has been satisfied, switch it to a provider chest and save the request with unit_number or end
if i == 1 then
if chest.name == "logistic-chest-overflow" then
local request = {}
for slot = 1, 12 do
if chest.get_request_slot(slot) ~= nil then
request[slot] = {chest.get_request_slot(slot).name, chest.get_request_slot(slot).count}
end
end
local newchest = switchchests(chest, "logistic-chest-overflow-provider", pos, k)
global.reqtable[newchest.unit_number] = request
end
end
--if not, switch it back and set the saved slots again or end
if i == 0 then
if chest.name == "logistic-chest-overflow-provider" then
local newchest = switchchests(chest, "logistic-chest-overflow", pos, k)
for slot = 1, 12 do
if global.reqtable[chestID] ~= nil then
if global.reqtable[chestID][slot] ~= nil then
newchest.set_request_slot({name=global.reqtable[chestID][slot][1], count=global.reqtable[chestID][slot][2]}, slot)
end
end
end
--delete the saved requests to prevent reqtable from getting massive
global.reqtable[chestID] = nil
end
end
end
end
end
end
end
end
script.on_event({defines.events.on_tick}, main)
--check for new chests
function built(event)
local entity = event.entity or event.created_entity
if (entity.name == "logistic-chest-overflow") or (entity.name == "logistic-chest-overflow-provider") then
table.insert(global.chests, entity)
end
end
script.on_event(defines.events.on_built_entity, built)
script.on_event(defines.events.on_robot_built_entity, built)
script.on_event(defines.events.script_raised_built, built)
--check for deleted chests
function mined(event)
local entity = event.entity
if (entity.name == "logistic-chest-overflow") or (entity.name == "logistic-chest-overflow-provider") then
for key, ent in pairs(global.chests) do
if ent == entity then
table.remove(global.chests, key)
break
end
end
end
if entity.name == "logistic-chest-overflow-provider" then
table.remove(global.reqtable, entity.unit_number)
end
end
script.on_event(defines.events.on_player_mined_entity, mined)
script.on_event(defines.events.on_robot_mined_entity, mined)
script.on_event(defines.events.script_raised_destroy, mined)
--check for new created blueprints
function blueprint_set(event)
local blueprint = game.players[event.player_index].blueprint_to_setup
if not blueprint or not blueprint.valid_for_read then
blueprint = game.players[event.player_index].cursor_stack
end
local ents = blueprint.get_blueprint_entities()
local cursedmapping = event.mapping.get()
local cleanmapping = {}
for key, entity in pairs(ents) do
if not entity.name == "logistic-chest-overflow-provider" then
table.remove(ents, key)
end
if entity.name == "logistic-chest-overflow-provider" then
--here comes the tricky part. get_blueprint_entities does not contain class LuaEntity but blueprint entity instead. This class is not listed in lua-api.factorio.com. To get the inner structure of the mentioned entity specific fields nothing else helps than abusing the game.surfaces[].print command and testing.
cleanmapping[entity] = cursedmapping[entity.entity_number].unit_number
entity.name = "logistic-chest-overflow"
local b = {}
local c = 1
local d = {index = nil, name = nil, count = nil}
for slot = 1, 12 do
if global.reqtable[cleanmapping[entity]] ~= nil then
if global.reqtable[cleanmapping[entity]][slot] ~= nil then
d["index"] = slot
d["name"] = global.reqtable[cleanmapping[entity]][slot][1]
d["count"] = global.reqtable[cleanmapping[entity]][slot][2]
table.insert(b, c, d)
c=c+1
end
end
end
entity["request_filters"] = b
end
end
blueprint.set_blueprint_entities(ents)
end
script.on_event(defines.events.on_player_setup_blueprint, blueprint_set)