215 lines
8.6 KiB
Lua
215 lines
8.6 KiB
Lua
local TPlib = require("lib.TPlib")
|
|
|
|
|
|
|
|
local TPcp = {}
|
|
|
|
|
|
--
|
|
-- Custom classes
|
|
--
|
|
local function item_stat_init()
|
|
return {
|
|
used = {},
|
|
insert_failed = {},
|
|
}
|
|
end
|
|
|
|
local function item_stat_used(t, k, v)
|
|
if not t or not t.used then t = item_stat_init() end
|
|
t.used[k] = (t.used[k] or 0) + v
|
|
return t
|
|
end
|
|
|
|
local function item_stat_insert_failed(t, k, v)
|
|
if not t or not t.insert_failed then t = item_stat_init() end
|
|
t.insert_failed[k] = (t.insert_failed[k] or 0) + v
|
|
return t
|
|
end
|
|
|
|
|
|
--
|
|
-- Tool Functions
|
|
--
|
|
function TPcp.get_items_from_source(itemname, desired_amt, itemsource, item_stat, check_only)
|
|
-- OUTPUT: Number of items allowed to get.
|
|
local itemcount = itemsource.get_item_count(itemname)
|
|
local fill_amt = math.min(desired_amt, itemcount)
|
|
if check_only then return fill_amt end
|
|
-- item_used[itemname] = (item_used[itemname] or 0) + fill_amt
|
|
item_stat_used(item_stat, itemname, fill_amt)
|
|
if fill_amt > 0 then
|
|
itemsource.remove_item{name = itemname, count = fill_amt}
|
|
end
|
|
return fill_amt
|
|
end
|
|
|
|
|
|
--
|
|
-- Main Functions
|
|
--
|
|
function TPcp.inventory_filters_clone(source, target)
|
|
if not source or not source.valid or not source.supports_filters() then return end
|
|
if not target or not target.valid or not target.supports_filters()then return end
|
|
-- TPlib.debugprint("Start inventory filters clone.")
|
|
for k = math.min(#source, #target), 1, -1 do
|
|
target.set_filter(k, source.get_filter(k))
|
|
end
|
|
end
|
|
|
|
|
|
function TPcp.inventory_slot_clone_placement(source, target, itemsource, item_stat)
|
|
if not itemsource then return end
|
|
if not source or not source.valid or not source.valid_for_read then return end
|
|
if not target or not target.valid then return end
|
|
-- Skip complex items like armor (Not sure to take identical item)
|
|
if source.count == 1 and ( source.grid or source.is_blueprint or source.is_blueprint_book or source.is_armor or source.is_item_with_inventory or source.is_item_with_entity_data or source.is_deconstruction_item or source.is_upgrade_item ) then
|
|
-- TPlib.debugprint("Item " .. source.name .. " is not cloned, for being a possibly complex item.")
|
|
item_stat_insert_failed(item_stat, source.name, source.count)
|
|
return
|
|
end
|
|
-- TPlib.debugprint("Start inventory slot clone placement.")
|
|
if target.valid_for_read then
|
|
-- TPlib.debugprint(" has item " .. target.name .. " x" .. target.count)
|
|
if source.name == target.name then
|
|
if source.count > target.count then
|
|
local fill_amt = TPcp.get_items_from_source(source.name, source.count - target.count, itemsource, item_stat)
|
|
if fill_amt > 0 then
|
|
-- Successful insert
|
|
target.count = target.count + fill_amt
|
|
end
|
|
end
|
|
else
|
|
-- Cannot insert, occupied by different type of items
|
|
item_stat_insert_failed(item_stat, source.name, source.count)
|
|
end
|
|
else
|
|
-- TPlib.debugprint(" is empty.")
|
|
local fill_amt = TPcp.get_items_from_source(source.name, source.count, itemsource, item_stat, true)
|
|
if fill_amt > 0 then
|
|
if target.set_stack{name = source.name, count = fill_amt} then
|
|
TPcp.get_items_from_source(source.name, source.count, itemsource, item_stat)
|
|
else
|
|
-- Cannot insert, probably due to incompatible slot (esp. fuel or ammo with different category)
|
|
item_stat_insert_failed(item_stat, source.name, fill_amt)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function TPcp.inventory_clone_placement(source, target, itemsource, item_stat)
|
|
if not itemsource then return end
|
|
if not source or not source.valid or source.is_empty() then return end
|
|
if not target or not target.valid then return end
|
|
-- TPlib.debugprint("Start inventory clone placement.")
|
|
for k = math.min(#source, #target), 1, -1 do
|
|
TPcp.inventory_slot_clone_placement(source[k], target[k], itemsource, item_stat)
|
|
end
|
|
end
|
|
|
|
|
|
function TPcp.grid_clone_placement(source, target, itemsource, item_stat)
|
|
if not itemsource then return end
|
|
if not source or not source.valid then return end
|
|
if not target or not target.valid then return end
|
|
-- TPlib.debugprint("Start equipment clone placement.")
|
|
local itemproto = game.item_prototypes
|
|
for _, v in pairs(source.equipment) do
|
|
if v.valid then
|
|
-- local itempt = itemproto[v.name]
|
|
local itemname = nil
|
|
if itemproto[v.name] and itemproto[v.name].place_as_equipment_result.name == v.name then
|
|
-- Placed by item of same name, no need to search
|
|
itemname = v.name
|
|
else
|
|
-- Cannot be placed by item of same name, have to search through prototypes (expensive search)
|
|
-- get_filtered_item_prototypes filters are really difficult to be used, poorly documented
|
|
-- Now skip for breavity
|
|
-- local results = game.get_filtered_item_prototypes({{ filter = "placed-as-equipment-result", elem_filters = {{ filter = "name", name = v.name }} }})
|
|
-- local results = game.get_filtered_item_prototypes({{ filter = "placed-as-equipment-result" }})
|
|
-- for k, itm in pairs(results) do
|
|
-- if itm.place_as_equipment_result.name == v.name then
|
|
-- itemname = itm.name
|
|
-- game.print("Using " .. itemname .. " to insert to equipment " .. v.name)
|
|
-- break
|
|
-- end
|
|
-- end
|
|
if not itemname then
|
|
game.print("Cannot find corresponding item for equipment " .. v.name)
|
|
end
|
|
end
|
|
if itemname then
|
|
local inserted = target.put{name = v.name, position = v.position, by_player = itemsource}
|
|
if inserted then
|
|
local fill_amt = TPcp.get_items_from_source(itemname, 1, itemsource, item_stat)
|
|
if fill_amt > 0 then
|
|
-- Successful insert
|
|
if v.burner and inserted.burner then
|
|
TPcp.inventory_clone_placement(v.burner.inventory, inserted.burner.inventory, itemsource, item_stat)
|
|
end
|
|
else
|
|
-- Usable but out of supply
|
|
target.take{equipment = inserted}
|
|
end
|
|
else
|
|
-- Not compatible / Slot used
|
|
-- Check same position
|
|
local eqpT = target.get(v.position)
|
|
if eqpT and eqpT.name == v.name then
|
|
-- If same equipment, than may clone contents within burner
|
|
if v.burner and eqpT.burner then
|
|
TPcp.inventory_clone_placement(v.burner.inventory, eqpT.burner.inventory, itemsource, item_stat)
|
|
end
|
|
else
|
|
-- TPlib.debugprint({"", "Failed to put ", v.prototype.localised_name, " on ", TPlib.format_position(v.position)})
|
|
item_stat_insert_failed(item_stat, v.name, 1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function TPcp.vehicle_clone_placement(source, target, itemsource)
|
|
-- TPlib.debugprint("You placed a " .. target.name .. " (" .. target.type .. ").")
|
|
if not target.prototype.weight then return end
|
|
if not itemsource then return end
|
|
if not source then return end
|
|
if not target then return end
|
|
local itemproto = game.item_prototypes
|
|
local item_stat = item_stat_init()
|
|
-- Grid clone
|
|
TPcp.grid_clone_placement(source.grid, target.grid, itemsource, item_stat)
|
|
-- Fuel clone
|
|
TPcp.inventory_clone_placement(source.get_fuel_inventory(), target.get_fuel_inventory(), itemsource, item_stat)
|
|
-- Ammo clone
|
|
TPcp.inventory_clone_placement(source.get_inventory(defines.inventory.car_ammo), target.get_inventory(defines.inventory.car_ammo), itemsource, item_stat)
|
|
-- Inventory clone
|
|
TPcp.inventory_filters_clone(source.get_inventory(defines.inventory.car_trunk), target.get_inventory(defines.inventory.car_trunk))
|
|
TPcp.inventory_clone_placement(source.get_inventory(defines.inventory.car_trunk), target.get_inventory(defines.inventory.car_trunk), itemsource, item_stat)
|
|
-- Cargo wagon inventory clone
|
|
TPcp.inventory_filters_clone(source.get_inventory(defines.inventory.cargo_wagon), target.get_inventory(defines.inventory.cargo_wagon))
|
|
TPcp.inventory_clone_placement(source.get_inventory(defines.inventory.cargo_wagon), target.get_inventory(defines.inventory.cargo_wagon), itemsource, item_stat)
|
|
-- Flying text for items placed
|
|
local surface = target.surface
|
|
local position = target.position
|
|
surface.create_entity{name = "flying-text", position = target.position, text = {"description.Schall-flying-text-place"}}
|
|
-- Flying text for items failed to insert
|
|
for k, v in pairs(item_stat.insert_failed) do
|
|
position.y = position.y + 0.5
|
|
TPlib.create_flying_text_insert_failed(surface, position, itemproto[k])
|
|
end
|
|
-- Flying text for items taken from player inventory
|
|
local surface = itemsource.surface
|
|
local position = itemsource.position
|
|
for k, v in pairs(item_stat.used) do
|
|
position.y = position.y + 0.5
|
|
TPlib.create_flying_text_item(surface, position, itemproto[k], -v, itemsource)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
return TPcp |