Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Fedja Beader
CSM
Commits
b5728d33
Commit
b5728d33
authored
Jul 27, 2021
by
Fedja Beader
Browse files
Add inventory networks CSM, a generic successor to inventory/biofuel.lua
parent
630bf7f7
Changes
2
Hide whitespace changes
Inline
Side-by-side
inventory_networks/init.lua
0 → 100644
View file @
b5728d33
--[[
Minetest+specing Client-Side Mod (CSM) for automatically moving items between inventories
Copyright (C) 2021 Fedja Beader
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
--]]
-- general idea:
-- register multiple locations (node, inventory, detached) hereafter refered to as 'machines'
-- each machine can be either a converter or storage
-- each converter has an associated recipe
-- -> accepts predetermined amount of different items and produces an amount of output items
-- -> for now, we assume that output is only one. (battery recipe has two - bucket and battery)
--
-- in each step, we:
-- 1) pick one machine from the list
-- 2) go through all other machines and collect available amount of input material
-- 3) move as much input material as possible (up to max_stack), such that there will be no recipe leftovers
--[[
register_on_jumpdrive_jump(function (jump)
l:info("translating coordinates on jump")
for i,m in pairs(machines) do
translate_position( jump, m.pos)
end
end)
--]]
local
l
=
Logger
:
new
(
"invnet"
)
local
mod_storage
=
core
.
get_mod_storage
()
local
invnet
=
minetest
.
deserialize
(
mod_storage
:
get_string
(
"network"
))
or
{}
invnet
.
enable
=
invnet
.
enable
or
false
invnet
.
machines
=
invnet
.
machines
or
{}
local
function
invnet_reset
()
invnet
.
enable
=
false
invnet
.
machines
=
{}
end
local
function
invnet_list
()
for
i
,
m
in
pairs
(
invnet
.
machines
)
do
l
:
info
(
"Machine #"
..
i
..
" at "
..
minetest
.
pos_to_string
(
m
.
pos
)
..
": "
)
for
name
,
count
in
pairs
(
m
.
recipe
or
{})
do
l
:
info
(
" recipe consumes "
..
count
..
" of "
..
name
)
end
for
name
,
count
in
pairs
(
m
.
output
or
{})
do
l
:
info
(
" recipe produces "
..
count
..
" of "
..
name
)
end
end
end
local
function
invnet_setup_item_move
()
-- Pick a machine
local
machines
=
invnet
.
machines
local
machine
=
nil
for
_
=
1
,
100
do
local
m_index
=
math.random
(
1
,
#
machines
)
machine
=
machines
[
m_index
]
l
:
debug
(
"Testing machine "
..
m_index
)
if
machine
.
recipe
then
-- skip chests
break
end
end
if
not
machine
or
not
machine
.
recipe
then
return
false
end
l
:
info
(
"Selected machine at "
..
minetest
.
pos_to_string
(
machine
.
pos
))
-- for each input item adjust total max_stack to minimum of them all, then
-- try to move at once as many stacks as there are items in the recipe
local
sources
=
{}
local
max_stack
=
math.huge
-- max transfer size
local
total_stacks
=
0
for
item_name
,
_
in
pairs
(
machine
.
recipe
)
do
max_stack
=
math.min
(
max_stack
,
ItemStack
(
item_name
):
get_stack_max
())
--l:debug(" corrected stack max to " .. max_stack .. " for " .. item_name)
end
l
:
debug
(
" corrected stack max to "
..
max_stack
)
for
item_name
,
count
in
pairs
(
machine
.
recipe
)
do
local
from
=
ItemLocations
:
new
()
for
_
,
src_machine
in
pairs
(
machines
)
do
from
:
collect
(
src_machine
.
pos
,
src_machine
.
output_list_name
,
item_name
)
end
from
:
sort_by_count_dsc
()
-- larger stacks first
for
i
=
1
,
count
do
if
i
>
#
from
.
locations
or
from
.
locations
[
i
].
count
<
max_stack
then
l
:
debug
(
" insufficient stacks for item "
..
item_name
..
", got only "
..
(
i
-
1
))
return
false
end
end
sources
[
item_name
]
=
from
total_stacks
=
total_stacks
+
count
end
-- Do we have enough free slots to deposit items to?
local
to
=
ItemLocations
:
new
()
to
:
collect
(
machine
.
pos
,
machine
.
input_list_name
,
""
)
if
#
to
.
locations
<
total_stacks
then
l
:
debug
(
" insufficient space to deposit "
..
total_stacks
..
" stacks"
)
return
false
end
-- If we made it to here, then we have enough items to craft the recipe => setup moving
-- list of from_loc & to_loc & count
local
move_list
=
{}
local
dst_i
=
1
for
item_name
,
from
in
pairs
(
sources
)
do
local
count
=
machine
.
recipe
[
item_name
]
for
i
=
1
,
count
do
local
src_loc
=
from
.
locations
[
i
]
local
dst_loc
=
to
.
locations
[
dst_i
]
dst_i
=
dst_i
+
1
l
:
debug
(
" will move "
..
max_stack
..
"*"
..
item_name
..
" from "
..
src_loc
:
to_string
()
..
" to "
..
dst_loc
:
to_string
())
table.insert
(
move_list
,
{
src
=
src_loc
,
dst
=
dst_loc
,
count
=
max_stack
})
end
end
-- schedule actual moves
for
i
,
item
in
pairs
(
move_list
)
do
queue
:
prepend
(
function
()
return
queued_move_stack
(
item
.
src
,
item
.
dst
,
item
.
count
)
end
)
if
math
.
mod
(
i
,
5
)
==
4
then
-- add a small delay
queue
:
prepend
(
function
()
return
0
.
2
end
)
end
end
return
true
end
function
invnet_step
()
if
not
invnet
.
enable
then
return
end
--l:debug("inventory network step")
local
my_pos
=
core
.
localplayer
:
get_pos
()
for
_
,
m
in
pairs
(
invnet
.
machines
)
do
local
distance
=
vector
.
distance
(
my_pos
,
m
.
pos
)
if
distance
>
8
then
l
:
info
(
"Too far ("
..
distance
..
") from inventory "
..
minetest
.
pos_to_string
(
m
.
pos
)
..
", waiting"
)
core
.
after
(
15
,
invnet_step
)
-- use after as it takes forever
return
end
end
if
invnet_setup_item_move
()
then
-- setup as many hops as possible
--queue:append(invnet_step)
core
.
after
(
2
,
invnet_step
)
-- use after as it takes forever
queue
:
walk
()
else
core
.
after
(
4
,
invnet_step
)
-- use after as it takes forever
end
end
local
function
get_machine_in_list
(
pos
)
for
i
,
m
in
pairs
(
invnet
.
machines
)
do
if
vector
.
distance
(
m
.
pos
,
pos
)
<
0
.
1
then
return
i
end
end
return
#
invnet
.
machines
+
1
end
local
wait_for_punch
=
false
core
.
register_on_punchnode
(
function
(
pos
,
node
)
if
not
wait_for_punch
then
return
end
local
machine_index
=
get_machine_in_list
(
pos
)
if
node
.
name
==
"biofuel:refinery"
or
node
.
name
==
"biofuel:refinery_active"
then
local
m
=
{}
m
.
recipe
=
{
[
"default:stick"
]
=
4
,
}
m
.
input_list_name
=
"src"
m
.
output
=
{
[
"biofuel:bottle_fuel"
]
=
1
}
m
.
output_list_name
=
"dst"
m
.
pos
=
pos
invnet
.
machines
[
machine_index
]
=
m
l
:
info
(
"Added refinery"
)
elseif
node
.
name
==
"pipeworks:autocrafter"
then
local
inv
=
core
.
get_inventory
(
pos
)
local
item_string
=
inv
[
"output"
][
1
]:
get_name
()
if
item_string
==
""
then
l
:
err
(
"autocrafter unconfigured"
)
else
local
output_gain
=
inv
[
"output"
][
1
]:
get_count
()
local
m
=
{}
m
.
recipe
=
{}
for
_
,
stack
in
pairs
(
inv
[
"recipe"
])
do
local
name
=
stack
:
get_name
()
if
name
~=
""
then
m
.
recipe
[
name
]
=
(
m
.
recipe
[
name
]
or
0
)
+
1
end
end
m
.
input_list_name
=
"src"
m
.
output
=
{
[
item_string
]
=
output_gain
}
m
.
output_list_name
=
"dst"
m
.
pos
=
pos
invnet
.
machines
[
machine_index
]
=
m
l
:
info
(
"Added autocrafter for: "
..
output_gain
..
" of "
..
item_string
)
end
else
l
:
info
(
"Unknown node punched: "
..
node
.
name
..
" adding it as source chest"
)
local
inv
=
core
.
get_inventory
(
pos
)
local
m
=
{}
if
inv
[
"dst"
]
then
m
.
output_list_name
=
"dst"
elseif
inv
[
"main"
]
then
m
.
output_list_name
=
"main"
end
if
m
.
output_list_name
then
m
.
pos
=
pos
invnet
.
machines
[
machine_index
]
=
m
end
end
mod_storage
:
set_string
(
"network"
,
minetest
.
serialize
(
invnet
))
end
)
local
function
help
()
return
".invnet: inventory networks (automatic item moving between inventories), usage:\n"
..
".invnet add -- toggles adding nodes to the network\n"
..
".invnet list -- lists all inventories in the network\n"
..
".invnet reset -- clears the entire network\n"
..
".invnet start -- make other players jealous\n"
..
".invnet stop -- regain use of your chat\n"
end
core
.
register_chatcommand
(
"invnet"
,
{
func
=
function
(
param
)
local
args
=
string
.
split
(
param
,
' '
)
if
args
[
1
]
==
"add"
then
if
wait_for_punch
then
wait_for_punch
=
false
else
l
:
info
(
"punch nodes to add them into inventory network. repeat this command to stop"
)
wait_for_punch
=
true
end
elseif
args
[
1
]
==
"list"
then
invnet_list
()
elseif
args
[
1
]
==
"reset"
then
invnet_reset
()
elseif
args
[
1
]
==
"start"
then
invnet
.
enable
=
true
invnet_step
()
elseif
args
[
1
]
==
"stop"
then
invnet
.
enable
=
false
else
l
:
info
(
help
())
end
end
,
})
inventory_networks/mod.conf
0 → 100644
View file @
b5728d33
name
=
inventory_networks
depends
=
library
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment