Skip to content

Commit 1518524

Browse files
committed
Sync hopper submodule
1 parent e8e36a4 commit 1518524

12 files changed

+233
-375
lines changed

mods/tools/hopper/.luacheckrc

-22
This file was deleted.

mods/tools/hopper/CHANGELOG.md

-21
This file was deleted.

mods/tools/hopper/README.md

+31-45
Original file line numberDiff line numberDiff line change
@@ -4,56 +4,42 @@
44

55
Based on jordan4ibanez's original hoppers mod, optimized by TenPlus1 and FaceDeer, with chutes and sorters by FaceDeer
66

7-
Lucky Blocks: 2
8-
9-
Change log: [CHANGELOG.md](CHANGELOG.md)
10-
11-
### Functionality description
12-
13-
#### Hopper node
14-
15-
Hoppers are nodes that can transfer items to and from the inventories of adjacent nodes. The transfer direction depends on the orientation of the hopper.
16-
17-
The wide end of a hopper is its "input" end, if there is a compatible container (e.g. a chest), one item per second is taken into its own internal inventory. The hopper will also draw in dropped items.
18-
19-
The narrow end of the hopper is its "output" end. It can be either straight or 90° bent, relative to the input. It will attempt to inject items into a compatible container connected to it. On failure, the item is either held back in the hopper inventory or ejected, depending on its configuration.
20-
21-
#### Chute node
7+
Hoppers are nodes that can transfer items to and from the inventories of adjacent nodes. The wide end of a hopper is its "input" end, if there's a chest or other compatible container it will take one item per second into its own internal inventory. It will also draw in items that have been dropped here. The narrow end of the hopper is its "output" end. It will attempt to inject items into a compatible container located at its output end. If there's no compatible container and the hopper's "eject" mode has been enabled it will instead dump the items out into the world.
228

23-
The "chute" node acts as a pipe for items injected by a hopper or sorter. Use a screwdriver tool to achieve the desired rotation.
9+
The location of a hopper relative to a furnace determines which inventory slots the hopper will affect. A hopper directly above a furnace will inject items into the furnace's input slot. A hopper to the furnace's side will inject items into the furnace's fuel slot. A hopper below the furnace will pull items out of the furnace's output slot. Hoppers cannot inject items into inappropriate slots; non-fuel items will not be placed into the furnace's fuel slot and non-cookable items will not be placed into the input slot.
2410

25-
#### Sorter node
11+
Also included in this mod are a "chute" node and a "sorter" node. These allow for items to be routed over short distances and distributed in sophisticated ways.
2612

27-
Item stacks placed into the "filter" grid of the sorter node inventory define how to distribute the incoming items into the two outputs.
13+
A chute simply moves items into adjacent nodes. You'll need to use a hopper or sorter to inject items into it to move along. A screwdriver is a useful tool for getting chutes aimed correctly.
2814

29-
* Matching items are sent into the direction of the large arrow (`V`).
30-
* Other items are sent to the 90° side output.
31-
32-
Special case: The "filter all" option will cause the sorter to attempt to send *all* items in the direction of the large arrow. On failure, they're sent in the direction of the smaller arrow. Use-cases:
33-
34-
* Protection against overflowing containers
35-
* Protection against unaccepted items in the destination slot(s), such as the furnace fuel slot
36-
37-
#### Built-in mod compatibility
38-
39-
The following nodes are supported out-of-the-box. "above"/"below"/"side" describe the location of the hopper.
40-
41-
* `default:furnace`
42-
* Above: routed to the input slot
43-
* Below: routed to the output slots
44-
* Sides: routed to the fuel slot
45-
* `default:chest(_locked)`, `protector:chest`
46-
* All sides: routed to the main slot
47-
* `wine:wine_barrel`
48-
* Above: routed to the destination slots
49-
* Below: routed to the source slot
50-
* Sides: routed to the source slot
15+
A sorter has two different outputs. Its inventory has a "filter" grid; place items in this grid to set the sorter's filter. Items that match the filter will be sent out the output with the large arrow and other items will be sent out the output with the smaller arrow. A "filter all" option will cause the sorter to attempt to send *all* items in the direction of the large arrow and then if that fails send them in the direction of the smaller arrow. This allows you to have an "overflow" storage should the sorter's primary target fill up, or when used in combination with a selective container (like the furnace's fuel slot, for example) it allows the target inventory to do the filtering for you.
5116

5217
### Advanced settings
5318

54-
This mod has several configurable settings. See settings menu or [settingtypes.txt](settingtypes.txt) for details.
55-
56-
* Hopper texture size: 16x16 pixels (default) or 32x32 pixels
57-
* Single craftable item: output is straight or rotated by 90° to the side based on how you place it (default). When disabled, straight and bent hoppers must be crafted separately.
58-
* Eject items button: option to remove the "eject items" button from hoppers
19+
This mod has several configurable settings found in the advanced settings menu.
20+
21+
* Hopper texture size: can be set to 16 pixels (matching most standard Minetest node textures) or 32 pixels
22+
* Single craftable item: When enabled (the default) hoppers are crafted as a single item and then select whether the output has a 90-degree turn to the side based on how you place it. When disabled you can craft straight and bent hoppers as separate items.
23+
* Eject items button: this can be used to remove the "eject items" button from hoppers, if it is not desired.
24+
25+
### Change log
26+
27+
- 0.1 - Initial release from jordan4ibanez
28+
- 0.2 - Fixed tool glitch (wear restored by accident)
29+
- 0.3 - transfer function added
30+
- 0.4 - Supports locked chest and protected chest
31+
- 0.5 - Works with 0.4.13's new shift+click for newly placed Hoppers
32+
- 0.6 - Remove formspec from hopper nodes to improve speed for servers
33+
- 0.7 - Halved hopper capacity, can be dug by wooden pick
34+
- 0.8 - Added Napiophelios' new textures and tweaked code
35+
- 0.9 - Added support for Wine mod's wine barrels
36+
- 1.0 - New furances do not work properly with hoppers so old reverted to abm furnaces
37+
- 1.1 - Hoppers now work with new node timer Furnaces. Reduced Abm's and tidied code.
38+
- 1.2 - Added simple API so that hoppers can work with other containers.
39+
- 1.3 - Hoppers now call on_metadata_inventory_put and on_metadata_inventory_take, triggering furnace timers via their standard callbacks. Updated side hopper rotation handling to allow it to function in any orientation. Added settings options to use 16-pixel or 32-pixel textures. Added settings option to allow explicit crafting of standard/side hoppers or to allow crafting of a single item that selects which type to use on place. Added in-game documentation via optional "doc" mod dependency
40+
- 1.4 - Added intllib support
41+
- 1.5 - Added chutes
42+
- 1.6 - Added "eject items" button to formspecs, "group" support to the API
43+
- 1.7 - Added sorter block to allow for more sophisticated item transfer arrangements
5944

45+
Lucky Blocks: 2

mods/tools/hopper/abms.lua

+19-19
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,32 @@ minetest.register_abm({
55
nodenames = {"hopper:hopper", "hopper:hopper_side"},
66
interval = 1.0,
77
chance = 1,
8-
action = function(pos, _, _, active_object_count_wider)
8+
action = function(pos, node, active_object_count, active_object_count_wider)
99
if active_object_count_wider == 0 then
1010
return
1111
end
12-
12+
1313
local inv = minetest.get_meta(pos):get_inventory()
14-
if not inv then
15-
return
16-
end
14+
local posob
1715

1816
for _,object in pairs(minetest.get_objects_inside_radius(pos, 1)) do
19-
local entity = not object:is_player() and object:get_luaentity()
20-
21-
if entity
22-
and entity.name == "__builtin:item"
23-
and inv:room_for_item("main", ItemStack(entity.itemstring)) then
17+
if not object:is_player()
18+
and object:get_luaentity()
19+
and object:get_luaentity().name == "__builtin:item"
20+
and inv
21+
and inv:room_for_item("main",
22+
ItemStack(object:get_luaentity().itemstring)) then
2423

25-
local posob = object:get_pos()
24+
posob = object:getpos()
2625

2726
if math.abs(posob.x - pos.x) <= 0.5
2827
and posob.y - pos.y <= 0.85
2928
and posob.y - pos.y >= 0.3 then
3029

31-
inv:add_item("main", ItemStack(entity.itemstring))
30+
inv:add_item("main",
31+
ItemStack(object:get_luaentity().itemstring))
3232

33-
entity.itemstring = ""
33+
object:get_luaentity().itemstring = ""
3434
object:remove()
3535
end
3636
end
@@ -85,7 +85,7 @@ minetest.register_abm({
8585
chance = 1,
8686
catch_up = false,
8787

88-
action = function(pos, node, _, _)
88+
action = function(pos, node, active_object_count, active_object_count_wider)
8989
local source_pos, destination_pos, destination_dir
9090
if node.name == "hopper:hopper_side" then
9191
source_pos = vector.add(pos, directions[node.param2].src)
@@ -96,21 +96,21 @@ minetest.register_abm({
9696
source_pos = vector.subtract(pos, destination_dir)
9797
destination_pos = vector.add(pos, destination_dir)
9898
end
99-
99+
100100
local output_direction
101101
if destination_dir.y == 0 then
102102
output_direction = "horizontal"
103103
end
104-
104+
105105
local source_node = minetest.get_node(source_pos)
106106
local destination_node = minetest.get_node(destination_pos)
107107

108-
local registered_source_inventories = hopper.get_registered(source_node.name)
108+
local registered_source_inventories = hopper.get_registered_inventories_for(source_node.name)
109109
if registered_source_inventories ~= nil then
110110
hopper.take_item_from(pos, source_pos, source_node, registered_source_inventories["top"])
111111
end
112-
113-
local registered_destination_inventories = hopper.get_registered(destination_node.name)
112+
113+
local registered_destination_inventories = hopper.get_registered_inventories_for(destination_node.name)
114114
if registered_destination_inventories ~= nil then
115115
if output_direction == "horizontal" then
116116
hopper.send_item_to(pos, destination_pos, destination_node, registered_destination_inventories["side"])

mods/tools/hopper/api.lua

+43-90
Original file line numberDiff line numberDiff line change
@@ -2,107 +2,60 @@ hopper.containers = {}
22
hopper.groups = {}
33
hopper.neighbors = {}
44

5-
local function parse_group(target_node)
6-
local number
7-
local identifier
8-
9-
local equals_index = string.find(target_node, "=")
10-
if equals_index ~= nil then
11-
identifier = string.sub(target_node, 7, equals_index-1)
12-
-- it's possible that the string was of the form "group:blah = 1", in which case we want to trim spaces off the end of the group identifier
13-
local space_index = string.find(identifier, " ")
14-
if space_index ~= nil then
15-
identifier = string.sub(identifier, 1, space_index-1)
16-
end
17-
number = tonumber(string.sub(target_node, equals_index+1, -1))
18-
else
19-
identifier = string.sub(target_node, 7, -1)
20-
number = "all" -- special value to indicate no number was provided
21-
end
22-
23-
return identifier, number
24-
end
25-
26-
local function is_already_in_neighbors(neighbor_node)
27-
for _, value in pairs(hopper.neighbors) do
28-
if value == neighbor_node then
29-
return true
30-
end
31-
end
32-
return false
33-
end
34-
355
-- global function to add new containers
366
function hopper:add_container(list)
377
for _, entry in pairs(list) do
38-
39-
local relative_position = entry[1]
8+
409
local target_node = entry[2]
41-
42-
local inventory_info = entry
43-
inventory_info.inventory_name = entry[3]
44-
table.remove(inventory_info, 1)
45-
table.remove(inventory_info, 1)
46-
table.remove(inventory_info, 1)
47-
4810
local neighbor_node
11+
4912
if string.sub(target_node, 1, 6) == "group:" then
50-
local group_identifier, group_number = parse_group(target_node)
51-
52-
if hopper.groups[group_identifier] == nil then
53-
hopper.groups[group_identifier] = {}
13+
local group_identifier, group_number
14+
local equals_index = string.find(target_node, "=")
15+
if equals_index ~= nil then
16+
group_identifier = string.sub(target_node, 7, equals_index-1)
17+
-- it's possible that the string was of the form "group:blah = 1", in which case we want to trim spaces off the end of the group identifier
18+
local space_index = string.find(group_identifier, " ")
19+
if space_index ~= nil then
20+
group_identifier = string.sub(group_identifier, 1, space_index-1)
21+
end
22+
group_number = tonumber(string.sub(target_node, equals_index+1, -1))
23+
else
24+
group_identifier = string.sub(target_node, 7, -1)
25+
group_number = "all" -- special value to indicate no number was provided
5426
end
55-
if hopper.groups[group_identifier][group_number] == nil then
56-
hopper.groups[group_identifier][group_number] = {}
27+
28+
local group_info = hopper.groups[group_identifier]
29+
if group_info == nil then
30+
group_info = {}
5731
end
58-
if hopper.groups[group_identifier][group_number].extra == nil then
59-
hopper.groups[group_identifier][group_number].extra = {}
32+
if group_info[group_number] == nil then
33+
group_info[group_number] = {}
6034
end
61-
62-
hopper.groups[group_identifier][group_number][relative_position] = inventory_info
35+
group_info[group_number][entry[1]] = entry[3]
36+
hopper.groups[group_identifier] = group_info
6337
neighbor_node = "group:"..group_identifier
38+
-- result is a table of the form groups[group_identifier][group_number][relative_position][inventory_name]
6439
else
65-
if hopper.containers[target_node] == nil then
66-
hopper.containers[target_node] = {}
67-
end
68-
if hopper.containers[target_node].extra == nil then
69-
hopper.containers[target_node].extra = {}
40+
local node_info = hopper.containers[target_node]
41+
if node_info == nil then
42+
node_info = {}
7043
end
71-
72-
hopper.containers[target_node][relative_position] = inventory_info
44+
node_info[entry[1]] = entry[3]
45+
hopper.containers[target_node] = node_info
7346
neighbor_node = target_node
47+
-- result is a table of the form containers[target_node_name][relative_position][inventory_name]
7448
end
75-
76-
if not is_already_in_neighbors(neighbor_node) then
77-
table.insert(hopper.neighbors, neighbor_node)
78-
end
79-
end
80-
end
81-
82-
-- global function for additional information about containers
83-
function hopper:set_extra_container_info(list)
84-
for _, entry in pairs(list) do
85-
local target_node = entry[1]
86-
table.remove(entry, 1) -- only extra information
87-
if string.sub(target_node, 1, 6) == "group:" then
88-
local group_identifier, group_number = parse_group(target_node)
89-
if not is_already_in_neighbors("group:" .. group_identifier) then
90-
minetest.log("error","An attempt to add extra information for " ..
91-
target_node .. " in the absence of the main one")
49+
50+
local already_in_neighbors = false
51+
for _, value in pairs(hopper.neighbors) do
52+
if value == neighbor_node then
53+
already_in_neighbors = true
9254
break
9355
end
94-
hopper.groups[group_identifier][group_number].extra = entry
95-
-- result is a table of the form:
96-
-- groups[group_identifier][group_number]["extra"][list of extra information]
97-
else
98-
if not is_already_in_neighbors(target_node) then
99-
minetest.log("error","An attempt to add extra information for " ..
100-
target_node .. " in the absence of the main one")
101-
break
102-
end
103-
hopper.containers[target_node].extra = entry
104-
-- result is a table of the form:
105-
-- containers[target_node_name]["extra"][list of extra information]
56+
end
57+
if not already_in_neighbors then
58+
table.insert(hopper.neighbors, neighbor_node)
10659
end
10760
end
10861
end
@@ -116,10 +69,10 @@ hopper:add_container({
11669
{"bottom", "hopper:hopper", "main"},
11770
{"side", "hopper:hopper", "main"},
11871
{"side", "hopper:hopper_side", "main"},
119-
72+
12073
{"bottom", "hopper:chute", "main"},
12174
{"side", "hopper:chute", "main"},
122-
75+
12376
{"bottom", "hopper:sorter", "main"},
12477
{"side", "hopper:sorter", "main"},
12578
})
@@ -129,15 +82,15 @@ if minetest.get_modpath("default") then
12982
{"top", "default:chest", "main"},
13083
{"bottom", "default:chest", "main"},
13184
{"side", "default:chest", "main"},
132-
85+
13386
{"top", "default:furnace", "dst"},
13487
{"bottom", "default:furnace", "src"},
13588
{"side", "default:furnace", "fuel"},
136-
89+
13790
{"top", "default:furnace_active", "dst"},
13891
{"bottom", "default:furnace_active", "src"},
13992
{"side", "default:furnace_active", "fuel"},
140-
93+
14194
{"top", "default:chest_locked", "main"},
14295
{"bottom", "default:chest_locked", "main"},
14396
{"side", "default:chest_locked", "main"},

0 commit comments

Comments
 (0)