Working mass-storage that keeps inventory; new worker functions, improvements
This commit is contained in:
parent
195b597504
commit
2fa5e34408
@ -1,4 +1,5 @@
|
||||
# Logistica
|
||||
# WORK IN PROGRESS - PRE-ALPHA STATE
|
||||
|
||||
Logistica is a item transport, distribution and storage mod.
|
||||
|
||||
|
@ -3,4 +3,5 @@ local path = logistica.MODPATH.."/api"
|
||||
dofile(path.."/cables.lua")
|
||||
dofile(path.."/controller.lua")
|
||||
dofile(path.."/mass_storage.lua")
|
||||
dofile(path.."/supplier.lua")
|
||||
dofile(path.."/demander.lua")
|
||||
|
@ -66,7 +66,7 @@ logistica.register_controller("Simple Controller", {
|
||||
description = "Simple Controller",
|
||||
tiles = { "logistica_silver_cable.png" },
|
||||
groups = {
|
||||
oddly_breakable_by_hand = 2,
|
||||
oddly_breakable_by_hand = 1,
|
||||
},
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
paramtype = "light",
|
||||
|
@ -1,4 +1,7 @@
|
||||
|
||||
local META_SERIALIZED_INV = "logistica:ser_inv"
|
||||
local META_ITEM_NAME = "logistica:item_name"
|
||||
|
||||
local function get_mass_storage_upgrade_inv(posForm, numUpgradeSlots)
|
||||
if numUpgradeSlots <= 0 then return "" end
|
||||
local upIconX = 1.5 + 1.25 * (7 - numUpgradeSlots) -- sort of hardcoded
|
||||
@ -34,9 +37,11 @@ end
|
||||
|
||||
-- callbacks
|
||||
|
||||
local function after_place_mass_storage(pos, placer, numSlots, numUpgradeSlots)
|
||||
local function after_place_mass_storage(pos, placer, itemstack, numSlots, numUpgradeSlots)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
if placer and placer:is_player() then
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
end
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("main", 1)
|
||||
inv:set_size("filter", numSlots)
|
||||
@ -44,12 +49,55 @@ local function after_place_mass_storage(pos, placer, numSlots, numUpgradeSlots)
|
||||
inv:set_size("upgrade", numUpgradeSlots)
|
||||
-- and connect to network
|
||||
logistica.on_storage_change(pos)
|
||||
-- restore inventory, if any
|
||||
local itemstackMetaInv = itemstack:get_meta():get_string(META_SERIALIZED_INV)
|
||||
if itemstackMetaInv then
|
||||
local listsTable = logistica.deserialize_inv(itemstackMetaInv)
|
||||
for name, listTable in pairs(listsTable) do
|
||||
inv:set_list(name, listTable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function on_mass_storage_preserve_metadata(pos, oldnode, oldmeta, drops)
|
||||
local drop = drops[1]
|
||||
local meta = minetest.get_meta(pos)
|
||||
if not drop or not meta then return end
|
||||
local inv = meta:get_inventory()
|
||||
local serialized = logistica.serialize_inv(inv)
|
||||
drop:get_meta():set_string(META_SERIALIZED_INV, serialized)
|
||||
-- update description
|
||||
local name = minetest.registered_nodes[oldnode.name].logistica.baseName
|
||||
if inv:is_empty("storage") then
|
||||
name = name.."\n(Empty)"
|
||||
else
|
||||
name = name.."\n(Contains items)" -- TODO set a node name or use a stackname
|
||||
end
|
||||
drop:get_meta():set_string("description", name)
|
||||
end
|
||||
|
||||
local function allow_mass_storage_inv_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player) then return 0 end
|
||||
if listname == "storage" then
|
||||
return logistica.clamp(stack:get_count(), 0, stack:get_stack_max())
|
||||
end
|
||||
if listname == "main" then return stack:get_count() end
|
||||
if listname == "filter" then
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
if not inv:get_stack("storage", index):is_empty() then return 0 end
|
||||
local storageStack = inv:get_stack("filter", index)
|
||||
storageStack:clear()
|
||||
inv:set_stack("filter", index, storageStack)
|
||||
logistica.updateStorageCacheFromPosition(pos)
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_mass_storage_inv_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
if minetest.is_protected(pos, player) then return 0 end
|
||||
if from_list == "main" and to_list == "main" then return count end
|
||||
if from_list == "filter" and to_list == "filter" then return count end
|
||||
if from_list == "upgrade" and to_list == "upgrade" then return count end
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -65,27 +113,12 @@ local function allow_mass_storage_inv_put(pos, listname, index, stack, player)
|
||||
copyStack:set_count(1)
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
inv:set_stack("filter", index, copyStack)
|
||||
logistica.updateStorageCacheFromPosition(pos)
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function allow_mass_storage_inv_take(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player) then return 0 end
|
||||
if listname == "storage" then
|
||||
return logistica.clamp(stack:get_count(), 0, stack:get_stack_max())
|
||||
end
|
||||
if listname == "main" then return stack:get_count() end
|
||||
if listname == "filter" then
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
if not inv:get_stack("storage", index):is_empty() then return 0 end
|
||||
local stack = inv:get_stack("filter", index)
|
||||
stack:clear()
|
||||
inv:set_stack("filter", index, stack)
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function on_mass_storage_inv_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
if minetest.is_protected(pos, player) then return 0 end
|
||||
@ -123,12 +156,6 @@ local function on_mass_storage_right_click(pos, node, clicker, itemstack, pointe
|
||||
)
|
||||
end
|
||||
|
||||
local function on_mass_storage_preserve_metadata(pos, oldnode, oldmeta, drops)
|
||||
local drop = drops[1]
|
||||
if not drop then return end
|
||||
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
-- Public Registration API
|
||||
----------------------------------------------------------------
|
||||
@ -136,21 +163,23 @@ end
|
||||
function logistica.register_mass_storage(simpleName, numSlots, numItemsPerSlot, numUpgradeSlots)
|
||||
local lname = string.lower(string.gsub(simpleName, " ", "_"))
|
||||
local storageName = "logistica:mass_storage_"..lname
|
||||
local grps = {cracky = 3, choppy = 3, oddly_breakable_by_hand = 2}
|
||||
local grps = {cracky = 1, choppy = 1, oddly_breakable_by_hand = 1}
|
||||
numUpgradeSlots = logistica.clamp(numUpgradeSlots, 0, 4)
|
||||
grps[logistica.TIER_ALL] = 1
|
||||
logistica.mass_storage[storageName] = true
|
||||
|
||||
local def = {
|
||||
description = simpleName.." Mass Storage",
|
||||
description = simpleName.." Mass Storage\n(Empty)",
|
||||
tiles = { "logistica_"..lname.."_mass_storage.png" },
|
||||
groups = grps,
|
||||
sounds = default.node_sound_metal_defaults(),
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
after_place_mass_storage(pos, placer, numSlots, numUpgradeSlots)
|
||||
after_place_mass_storage(pos, placer, itemstack, numSlots, numUpgradeSlots)
|
||||
end,
|
||||
after_destruct = logistica.on_storage_change,
|
||||
drop = storageName,
|
||||
logistica = {
|
||||
baseName = simpleName.." Mass Storage",
|
||||
maxItems = numItemsPerSlot,
|
||||
numSlots = numSlots,
|
||||
numUpgradeSlots = numUpgradeSlots,
|
||||
|
0
api/supplier.lua
Normal file
0
api/supplier.lua
Normal file
24
logic/demander.lua
Normal file
24
logic/demander.lua
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
-- Returns a list of ItemStacks from the demandList that are missing in the storageList
|
||||
function logistica.get_demand_based_on_list(demandList, storageList)
|
||||
local missing = {}
|
||||
local storageSize = #storageList
|
||||
for _, demanded in ipairs(demandList) do
|
||||
local remaining = demanded:get_count()
|
||||
local i = 1
|
||||
local checkNext = true
|
||||
while checkNext and i <= storageSize do
|
||||
local stored = storageList[i]
|
||||
if demanded:get_name() == stored:get_name() then
|
||||
remaining = remaining - stored:get_count()
|
||||
end
|
||||
if remaining <= 0 then checkNext = false end
|
||||
end
|
||||
if remaining > 0 then
|
||||
local missingStack = ItemStack(demanded)
|
||||
missingStack:set_count(remaining)
|
||||
table.insert(missing, missingStack)
|
||||
end
|
||||
end
|
||||
return missing
|
||||
end
|
@ -73,4 +73,4 @@ function logistica.do_tiers_match(tiers1, tiers2)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
@ -5,3 +5,5 @@ dofile(path .. "/push_pull.lua")
|
||||
dofile(path .. "/network_logic.lua")
|
||||
dofile(path .. "/controller.lua")
|
||||
dofile(path .. "/storage.lua")
|
||||
dofile(path .. "/supplier.lua")
|
||||
dofile(path .. "/demander.lua")
|
||||
|
@ -5,6 +5,11 @@ local CREATE_NETWORK_STATUS_FAIL_OTHER_NETWORK = -1
|
||||
local CREATE_NETWORK_STATUS_TOO_MANY_NODES = -2
|
||||
local ADD_STORAGE_MULTIPLE_NETWORKS = -1
|
||||
|
||||
logistica.networks = networks
|
||||
|
||||
local p2h = minetest.hash_node_position
|
||||
local h2p = minetest.get_position_from_hash
|
||||
|
||||
local adjecent = {
|
||||
vector.new( 1, 0, 0),
|
||||
vector.new( 0, 1, 0),
|
||||
@ -13,6 +18,7 @@ local adjecent = {
|
||||
vector.new( 0, -1, 0),
|
||||
vector.new( 0, 0, -1),
|
||||
}
|
||||
|
||||
local function has_machine(network, id)
|
||||
if not network then return false end
|
||||
if network.demanders and network.demanders[id] then
|
||||
@ -27,7 +33,7 @@ local function has_machine(network, id)
|
||||
end
|
||||
|
||||
function logistica.get_network_name_or_nil(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
local hash = p2h(pos)
|
||||
for nHash, network in pairs(networks) do
|
||||
if hash == nHash then return network.name end
|
||||
if network.cables[hash] then return network.name end
|
||||
@ -37,7 +43,7 @@ function logistica.get_network_name_or_nil(pos)
|
||||
end
|
||||
|
||||
function logistica.get_network_or_nil(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
local hash = p2h(pos)
|
||||
for nHash, network in pairs(networks) do
|
||||
if hash == nHash then return network end
|
||||
if network.cables[hash] then return network end
|
||||
@ -59,7 +65,7 @@ end
|
||||
local function dumb_remove_from_network(networkName, pos)
|
||||
local network = networks[networkName]
|
||||
if not network then return false end
|
||||
local hashedPos = minetest.hash_node_position(pos)
|
||||
local hashedPos = p2h(pos)
|
||||
if network.cables[hashedPos] then
|
||||
network.cables[hashedPos] = nil
|
||||
return true
|
||||
@ -94,6 +100,14 @@ local function break_logistica_node(pos)
|
||||
logistica.swap_node(pos, node.name .. "_disabled")
|
||||
end
|
||||
|
||||
-- calls updateStorageCache(network) if the current position belongs to a network
|
||||
function logistica.updateStorageCacheFromPosition(pos)
|
||||
local network = logistica.get_network_or_nil(pos)
|
||||
if network then
|
||||
logistica.updateStorageCache(network)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ updates the storage cach which holds where items may be found
|
||||
The cache is in the followiing format:
|
||||
network.storage_cache = {
|
||||
@ -108,11 +122,10 @@ function logistica.updateStorageCache(network)
|
||||
-- for now, do full rescan
|
||||
network.storage_cache = {}
|
||||
for storageHash, _ in pairs(network.mass_storage) do
|
||||
local storagePos = minetest.get_position_from_hash(storageHash)
|
||||
local storagePos = h2p(storageHash)
|
||||
logistica.load_position(storagePos)
|
||||
local meta = minetest.get_meta(storagePos)
|
||||
local inv = meta:get_inventory():get_list("filter")
|
||||
for _, itemStack in pairs(inv) do
|
||||
local filterList = minetest.get_meta(storagePos):get_inventory():get_list("filter") or {}
|
||||
for _, itemStack in pairs(filterList) do
|
||||
local name = itemStack:get_name()
|
||||
if not network.storage_cache[name] then network.storage_cache[name] = {} end
|
||||
network.storage_cache[name][storageHash] = true
|
||||
@ -124,7 +137,7 @@ local function dumb_add_storage_to_network(networkId, pos)
|
||||
local network = networks[networkId]
|
||||
if not network then return false end
|
||||
local node = minetest.get_node(pos)
|
||||
local hashedPos = minetest.hash_node_position(pos)
|
||||
local hashedPos = p2h(pos)
|
||||
if logistica.is_mass_storage(node.name) then
|
||||
network.mass_storage[hashedPos] = true
|
||||
return true
|
||||
@ -139,7 +152,7 @@ local function dumb_add_cable_to_network(networkName, pos)
|
||||
local network = networks[networkName]
|
||||
if not network then return false end
|
||||
local node = minetest.get_node(pos)
|
||||
local hashedPos = minetest.hash_node_position(pos)
|
||||
local hashedPos = p2h(pos)
|
||||
if logistica.is_cable(node.name) then
|
||||
network.cables[hashedPos] = true
|
||||
return true
|
||||
@ -165,7 +178,7 @@ local function recursive_scan_for_nodes_for_controller(network, positions, numSc
|
||||
for _, offset in pairs(adjecent) do
|
||||
local otherPos = vector.add(pos, offset)
|
||||
logistica.load_position(otherPos)
|
||||
local otherHash = minetest.hash_node_position(otherPos)
|
||||
local otherHash = p2h(otherPos)
|
||||
local tiersMatch = isAllTier
|
||||
if tiersMatch ~= true then
|
||||
local otherTiers = logistica.get_item_tiers(minetest.get_node(otherPos).name)
|
||||
@ -203,7 +216,7 @@ local function create_network(controllerPosition)
|
||||
local node = minetest.get_node(controllerPosition)
|
||||
if not node.name:find("_controller") or not node.name:find("logistica:") then return false end
|
||||
local meta = minetest.get_meta(controllerPosition)
|
||||
local controllerHash = minetest.hash_node_position(controllerPosition)
|
||||
local controllerHash = p2h(controllerPosition)
|
||||
local network = {}
|
||||
local networkName = logistica.get_network_name_for(controllerPosition)
|
||||
networks[controllerHash] = network
|
||||
@ -242,7 +255,7 @@ local function rescan_network(networkName)
|
||||
if not network then return false end
|
||||
if not network.controller then return false end
|
||||
local conHash = network.controller
|
||||
local controllerPosition = minetest.get_position_from_hash(conHash)
|
||||
local controllerPosition = h2p(conHash)
|
||||
clear_network(networkName)
|
||||
create_network(controllerPosition)
|
||||
end
|
||||
@ -301,7 +314,7 @@ local function try_to_add_mass_storage_to_network(pos)
|
||||
end
|
||||
|
||||
local function remove_mass_storage_from_network(pos)
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
local hash = p2h(pos)
|
||||
local network = logistica.get_network_or_nil(pos)
|
||||
if not network then return end
|
||||
if not network.mass_storage[hash] then return end
|
||||
@ -361,7 +374,7 @@ function logistica.on_cable_change(pos, oldNode)
|
||||
end
|
||||
|
||||
function logistica.on_controller_change(pos, oldNode)
|
||||
local hashPos = minetest.hash_node_position(pos)
|
||||
local hashPos = p2h(pos)
|
||||
local placed = (oldNode == nil) -- if oldNode is nil, we placed a new one
|
||||
if placed == true then
|
||||
try_to_add_network(pos)
|
||||
@ -377,4 +390,4 @@ function logistica.on_storage_change(pos, oldNode)
|
||||
else
|
||||
remove_mass_storage_from_network(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -55,4 +55,3 @@ function logistica.proq.get_all(pos)
|
||||
end
|
||||
return positions
|
||||
end
|
||||
|
||||
|
@ -66,24 +66,43 @@ function logistica.try_to_add_item_to_storage(pos, inputStack, dryRun)
|
||||
end
|
||||
|
||||
-- takes a list of ItemStacks and returns a single string representation
|
||||
function logistica.inv_to_table(list)
|
||||
local itemStackStrings = {}
|
||||
for _,v in pairs(list) do
|
||||
itemStackStrings:insert(v:to_string())
|
||||
function logistica.inv_list_to_table(list)
|
||||
local itemstackTable = {}
|
||||
for k,v in ipairs(list) do
|
||||
itemstackTable[k] = v and v:to_string() or ""
|
||||
end
|
||||
return itemstackTable
|
||||
end
|
||||
|
||||
function logistica.table_to_inv(string)
|
||||
|
||||
function logistica.table_to_inv_list(table)
|
||||
local list = {}
|
||||
for k,v in ipairs(table) do
|
||||
if v == nil or v == "" then
|
||||
list[k] = ""
|
||||
else
|
||||
list[k] = ItemStack(v)
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
local LIST_SEPARATOR = "L|L"
|
||||
-- takes a inventory and returns a single string represetation
|
||||
function logistica.serliaze_inventory(list)
|
||||
|
||||
-- returns a serialized string of the inventory
|
||||
function logistica.serialize_inv(inv)
|
||||
local lists = inv:get_lists()
|
||||
local invTable = {}
|
||||
for name, list in pairs(lists) do
|
||||
invTable[name] = logistica.inv_list_to_table(list)
|
||||
end
|
||||
return minetest.serialize(invTable)
|
||||
end
|
||||
|
||||
-- takes a inventory and returns a single string represetation
|
||||
function logistica.deserliaze_inventory(list)
|
||||
|
||||
-- takes a inventory serialized string and returns a table
|
||||
function logistica.deserialize_inv(serializedInv)
|
||||
local strTable = minetest.deserialize(serializedInv)
|
||||
if not strTable then return {} end
|
||||
local liveTable = {}
|
||||
for name, listStrTable in pairs(strTable) do
|
||||
liveTable[name] = logistica.table_to_inv_list(listStrTable)
|
||||
end
|
||||
return liveTable
|
||||
end
|
||||
|
38
logic/supplier.lua
Normal file
38
logic/supplier.lua
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
local p2h = minetest.hash_node_position
|
||||
local h2p = minetest.get_position_from_hash
|
||||
|
||||
-- attempts to insert the given itemstack in the network, returns how many items were inserted
|
||||
function logistica.insert_item_in_network(itemstack, networkId)
|
||||
local network = logistica.networks[networkId]
|
||||
if not itemstack or not network then return 0 end
|
||||
|
||||
local workingStack = ItemStack(itemstack)
|
||||
-- check demanders first
|
||||
for hash, _ in pairs(network.demanders) do
|
||||
local pos = h2p(hash)
|
||||
logistica.load_position(pos)
|
||||
local taken = 0 -- logistica.try_to_give_item_to_demander(pos, workingStack)
|
||||
local leftover = workingStack:get_count() - taken
|
||||
if leftover <= 0 then return itemstack:get_count() end -- we took all items
|
||||
workingStack:set_count(leftover)
|
||||
end
|
||||
|
||||
-- check storages
|
||||
local storages = {}
|
||||
if itemstack:get_stack_max() <= 1 then
|
||||
storages = network.item_storage
|
||||
else
|
||||
storages = network.mass_storage
|
||||
end
|
||||
for hash, _ in pairs(storages) do
|
||||
local pos = h2p(hash)
|
||||
logistica.load_position(pos)
|
||||
local taken = logistica.try_to_add_item_to_storage(pos, workingStack)
|
||||
local leftover = workingStack:get_count() - taken
|
||||
if leftover <= 0 then return itemstack:get_count() end -- we took all items
|
||||
workingStack:set_count(leftover)
|
||||
end
|
||||
|
||||
return itemstack:get_count() - workingStack:get_count()
|
||||
end
|
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.1 KiB |
@ -1,3 +1,3 @@
|
||||
logistica.ui = {}
|
||||
|
||||
logistica.ui.background = "bgcolor[#0000]background9[0,0;1,1;logistica_formspec_background.png;true;4]"
|
||||
logistica.ui.background = "no_prepend[]bgcolor[#0000]background9[0,0;1,1;logistica_formspec_background.png;true;8]"
|
Loading…
x
Reference in New Issue
Block a user