2017-01-17 16:50:56 +00:00
|
|
|
|
|
|
|
|
2017-01-27 11:42:05 +00:00
|
|
|
local chest = minetest.get_content_id("mcl_chests:chest")
|
2017-01-17 16:50:56 +00:00
|
|
|
|
2017-01-17 17:41:25 +00:00
|
|
|
local mcl_hoppers_formspec =
|
2017-01-17 17:17:53 +00:00
|
|
|
"size[9,7]"..
|
2017-01-17 17:41:25 +00:00
|
|
|
"background[-0.19,-0.25;9.41,10.48;mcl_hoppers_inventory.png]"..
|
2017-02-17 22:06:52 +00:00
|
|
|
mcl_vars.inventory_header..
|
2017-01-17 17:17:53 +00:00
|
|
|
"list[current_name;main;2,0.5;5,1;]"..
|
|
|
|
"list[current_player;main;0,2.5;9,3;9]"..
|
|
|
|
"list[current_player;main;0,5.74;9,1;]"..
|
|
|
|
"listring[current_name;main]"..
|
|
|
|
"listring[current_player;main]"
|
2017-01-17 16:50:56 +00:00
|
|
|
|
2017-01-17 17:41:25 +00:00
|
|
|
minetest.register_node("mcl_hoppers:hopper", {
|
2017-02-22 13:00:58 +00:00
|
|
|
description = "Hopper",
|
|
|
|
inventory_image = "mcl_hoppers_item.png",
|
|
|
|
wield_image = "mcl_hoppers_item.png",
|
2017-02-27 00:33:34 +00:00
|
|
|
groups = {pickaxey=1, container=2,deco_block=1,},
|
2017-01-17 16:50:56 +00:00
|
|
|
drawtype = "nodebox",
|
|
|
|
paramtype = "light",
|
2017-02-06 16:33:43 +00:00
|
|
|
tiles = {"mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_inside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png"},
|
2017-01-17 16:50:56 +00:00
|
|
|
selection_box = {type="regular"},
|
|
|
|
node_box = {
|
|
|
|
type = "fixed",
|
|
|
|
fixed = {
|
|
|
|
--funnel walls
|
|
|
|
{-0.5, 0.0, 0.4, 0.5, 0.5, 0.5},
|
|
|
|
{0.4, 0.0, -0.5, 0.5, 0.5, 0.5},
|
|
|
|
{-0.5, 0.0, -0.5, -0.4, 0.5, 0.5},
|
|
|
|
{-0.5, 0.0, -0.5, 0.5, 0.5, -0.4},
|
|
|
|
--funnel base
|
|
|
|
{-0.5, 0.0, -0.5, 0.5, 0.1, 0.5},
|
|
|
|
--spout
|
|
|
|
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3},
|
|
|
|
{-0.15, -0.3, -0.15, 0.15, -0.5, 0.15},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
on_construct = function(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
2017-01-17 17:41:25 +00:00
|
|
|
meta:set_string("formspec", mcl_hoppers_formspec)
|
2017-01-17 16:50:56 +00:00
|
|
|
local inv = meta:get_inventory()
|
2017-01-17 17:17:53 +00:00
|
|
|
inv:set_size("main", 5)
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
2017-02-22 13:00:58 +00:00
|
|
|
|
2017-02-22 13:15:06 +00:00
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
|
|
local upos = pointed_thing.under
|
|
|
|
local apos = pointed_thing.above
|
2017-02-22 13:00:58 +00:00
|
|
|
|
2017-03-02 15:09:13 +00:00
|
|
|
local uposnode = minetest.get_node(upos)
|
|
|
|
local uposnodedef = minetest.registered_nodes[uposnode.name]
|
|
|
|
|
|
|
|
-- Use pointed node's on_rightclick function first, if present
|
|
|
|
if placer and not placer:get_player_control().sneak then
|
|
|
|
if uposnodedef and uposnodedef.on_rightclick then
|
|
|
|
return uposnodedef.on_rightclick(pointed_thing.under, uposnode, placer, itemstack) or itemstack
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-02-22 13:15:06 +00:00
|
|
|
local bpos
|
|
|
|
if uposnodedef.buildable_to then
|
|
|
|
bpos = upos
|
|
|
|
else
|
|
|
|
local aposnodedef = minetest.registered_nodes[minetest.get_node(apos).name]
|
|
|
|
if aposnodedef.buildable_to then
|
|
|
|
bpos = apos
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if bpos == nil then
|
|
|
|
return itemstack
|
|
|
|
end
|
|
|
|
|
|
|
|
local x = upos.x - apos.x
|
|
|
|
local y = upos.y - apos.y
|
|
|
|
local z = upos.z - apos.z
|
2017-02-22 13:00:58 +00:00
|
|
|
|
|
|
|
if x == -1 then
|
2017-02-22 13:15:06 +00:00
|
|
|
minetest.set_node(bpos, {name="mcl_hoppers:hopper_side", param2=0})
|
2017-02-22 13:00:58 +00:00
|
|
|
elseif x == 1 then
|
2017-02-22 13:15:06 +00:00
|
|
|
minetest.set_node(bpos, {name="mcl_hoppers:hopper_side", param2=2})
|
2017-02-22 13:00:58 +00:00
|
|
|
elseif z == -1 then
|
2017-02-22 13:15:06 +00:00
|
|
|
minetest.set_node(bpos, {name="mcl_hoppers:hopper_side", param2=3})
|
2017-02-22 13:00:58 +00:00
|
|
|
elseif z == 1 then
|
2017-02-22 13:15:06 +00:00
|
|
|
minetest.set_node(bpos, {name="mcl_hoppers:hopper_side", param2=1})
|
|
|
|
else
|
|
|
|
minetest.set_node(bpos, {name="mcl_hoppers:hopper", param2=0})
|
|
|
|
end
|
|
|
|
if not minetest.setting_getbool("creative_mode") then
|
|
|
|
itemstack:take_item()
|
2017-02-22 13:00:58 +00:00
|
|
|
end
|
2017-02-22 13:15:06 +00:00
|
|
|
return itemstack
|
2017-02-22 13:00:58 +00:00
|
|
|
end,
|
|
|
|
|
2017-01-17 17:30:35 +00:00
|
|
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local meta2 = meta
|
|
|
|
meta:from_table(oldmetadata)
|
2017-01-17 16:50:56 +00:00
|
|
|
local inv = meta:get_inventory()
|
2017-01-17 17:30:35 +00:00
|
|
|
for i=1,inv:get_size("main") do
|
|
|
|
local stack = inv:get_stack("main", i)
|
|
|
|
if not stack:is_empty() then
|
|
|
|
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
|
|
|
minetest.add_item(p, stack)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
meta:from_table(meta2:to_table())
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
|
|
|
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
|
|
minetest.log("action", player:get_player_name()..
|
2017-01-17 17:41:25 +00:00
|
|
|
" moves stuff in mcl_hoppers at "..minetest.pos_to_string(pos))
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
|
|
|
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
|
|
minetest.log("action", player:get_player_name()..
|
2017-01-17 17:41:25 +00:00
|
|
|
" moves stuff to mcl_hoppers at "..minetest.pos_to_string(pos))
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
|
|
|
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
|
|
minetest.log("action", player:get_player_name()..
|
2017-01-17 17:41:25 +00:00
|
|
|
" takes stuff from mcl_hoppers at "..minetest.pos_to_string(pos))
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
2017-02-11 17:46:23 +00:00
|
|
|
sounds = mcl_sounds.node_sound_metal_defaults(),
|
2017-02-22 15:03:59 +00:00
|
|
|
_mcl_blast_resistance = 24,
|
2017-02-27 00:33:34 +00:00
|
|
|
_mcl_hardness = 3,
|
2017-01-17 16:50:56 +00:00
|
|
|
})
|
|
|
|
|
2017-01-17 17:41:25 +00:00
|
|
|
minetest.register_node("mcl_hoppers:hopper_side", {
|
2017-01-17 16:56:18 +00:00
|
|
|
description = "Hopper (Side)",
|
2017-02-22 13:00:58 +00:00
|
|
|
drop = "mcl_hoppers:hopper",
|
2017-02-27 00:33:34 +00:00
|
|
|
groups = {pickaxey=1, container=2,not_in_creative_inventory=1},
|
2017-01-17 16:50:56 +00:00
|
|
|
drawtype = "nodebox",
|
|
|
|
paramtype = "light",
|
|
|
|
paramtype2 = "facedir",
|
2017-02-06 16:33:43 +00:00
|
|
|
tiles = {"mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_inside.png", "mcl_hoppers_hopper_outside.png", "mcl_hoppers_hopper_outside.png"},
|
2017-01-17 16:50:56 +00:00
|
|
|
selection_box = {type="regular"},
|
|
|
|
node_box = {
|
|
|
|
type = "fixed",
|
|
|
|
fixed = {
|
|
|
|
--funnel walls
|
|
|
|
{-0.5, 0.0, 0.4, 0.5, 0.5, 0.5},
|
|
|
|
{0.4, 0.0, -0.5, 0.5, 0.5, 0.5},
|
|
|
|
{-0.5, 0.0, -0.5, -0.4, 0.5, 0.5},
|
|
|
|
{-0.5, 0.0, -0.5, 0.5, 0.5, -0.4},
|
|
|
|
--funnel base
|
|
|
|
{-0.5, 0.0, -0.5, 0.5, 0.1, 0.5},
|
|
|
|
--spout
|
|
|
|
{-0.3, -0.3, -0.3, 0.3, 0.0, 0.3},
|
|
|
|
{-0.7, -0.3, -0.15, 0.15, 0.0, 0.15},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
on_construct = function(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
2017-01-17 17:41:25 +00:00
|
|
|
meta:set_string("formspec", mcl_hoppers_formspec)
|
2017-01-17 16:50:56 +00:00
|
|
|
local inv = meta:get_inventory()
|
2017-01-17 17:17:53 +00:00
|
|
|
inv:set_size("main", 5)
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
2017-02-22 13:00:58 +00:00
|
|
|
|
2017-01-17 17:30:35 +00:00
|
|
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local meta2 = meta
|
|
|
|
meta:from_table(oldmetadata)
|
2017-01-17 16:50:56 +00:00
|
|
|
local inv = meta:get_inventory()
|
2017-01-17 17:30:35 +00:00
|
|
|
for i=1,inv:get_size("main") do
|
|
|
|
local stack = inv:get_stack("main", i)
|
|
|
|
if not stack:is_empty() then
|
|
|
|
local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5}
|
|
|
|
minetest.add_item(p, stack)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
meta:from_table(meta2:to_table())
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
|
|
|
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
|
|
|
minetest.log("action", player:get_player_name()..
|
2017-01-17 17:41:25 +00:00
|
|
|
" moves stuff in mcl_hoppers at "..minetest.pos_to_string(pos))
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
|
|
|
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
|
|
|
minetest.log("action", player:get_player_name()..
|
2017-01-17 17:41:25 +00:00
|
|
|
" moves stuff to mcl_hoppers at "..minetest.pos_to_string(pos))
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
|
|
|
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
|
|
minetest.log("action", player:get_player_name()..
|
2017-01-17 17:41:25 +00:00
|
|
|
" takes stuff from mcl_hoppers at "..minetest.pos_to_string(pos))
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
2017-02-11 17:46:23 +00:00
|
|
|
sounds = mcl_sounds.node_sound_metal_defaults(),
|
2017-02-22 15:03:59 +00:00
|
|
|
_mcl_blast_resistance = 24,
|
2017-02-27 00:33:34 +00:00
|
|
|
_mcl_hardness = 3,
|
2017-01-17 16:50:56 +00:00
|
|
|
})
|
2017-02-14 00:37:30 +00:00
|
|
|
|
|
|
|
-- Make hoppers suck in dropped items
|
2017-01-17 16:50:56 +00:00
|
|
|
minetest.register_abm({
|
2017-01-17 17:41:25 +00:00
|
|
|
nodenames = {"mcl_hoppers:hopper","mcl_hoppers:hopper_side"},
|
2017-01-17 16:50:56 +00:00
|
|
|
interval = 1.0,
|
|
|
|
chance = 1,
|
|
|
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
2017-02-14 00:37:30 +00:00
|
|
|
local abovenode = minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z})
|
|
|
|
-- Don't bother checking item enties if node above is a container (should save some CPU)
|
|
|
|
if minetest.registered_items[abovenode.name].groups.container then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local meta = minetest.get_meta(pos)
|
2017-01-17 16:50:56 +00:00
|
|
|
local inv = meta:get_inventory()
|
|
|
|
|
|
|
|
for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
|
|
|
if not object:is_player() and object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then
|
|
|
|
if inv and inv:room_for_item("main", ItemStack(object:get_luaentity().itemstring)) then
|
|
|
|
local posob = object:getpos()
|
|
|
|
if math.abs(posob.x-pos.x) <= 0.5 and (posob.y-pos.y <= 0.85 and posob.y-pos.y >= 0.3) then
|
|
|
|
inv:add_item("main", ItemStack(object:get_luaentity().itemstring))
|
|
|
|
object:get_luaentity().itemstring = ""
|
|
|
|
object:remove()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
2017-02-21 02:22:25 +00:00
|
|
|
-- Iterates through all items in the given inventory and
|
|
|
|
-- return the slot of the first item which matches a condition
|
|
|
|
local get_eligible_transfer_item = function(inventory, list, condition)
|
|
|
|
local size = inventory:get_size(list)
|
|
|
|
local stack
|
|
|
|
for i=1, size do
|
|
|
|
stack = inventory:get_stack(list, i)
|
|
|
|
if not stack:is_empty() and condition(stack) then
|
|
|
|
return i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
2017-02-21 02:38:24 +00:00
|
|
|
-- Returns true if given itemstack is a shulker box
|
|
|
|
local is_not_shulker_box = function(itemstack)
|
|
|
|
local g = minetest.get_item_group(itemstack:get_name(), "shulker_box")
|
|
|
|
return g == 0 or g == nil
|
|
|
|
end
|
|
|
|
|
2017-01-17 16:50:56 +00:00
|
|
|
minetest.register_abm({
|
2017-01-17 17:41:25 +00:00
|
|
|
nodenames = {"mcl_hoppers:hopper"},
|
2017-02-14 00:32:13 +00:00
|
|
|
neighbors = {"group:container"},
|
2017-01-17 16:50:56 +00:00
|
|
|
interval = 1.0,
|
|
|
|
chance = 1,
|
|
|
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
2017-02-14 00:25:02 +00:00
|
|
|
-- Get node pos' for item transfer
|
|
|
|
local uppos = {x=pos.x,y=pos.y+1,z=pos.z}
|
|
|
|
local downpos = {x=pos.x,y=pos.y-1,z=pos.z}
|
2017-01-17 16:50:56 +00:00
|
|
|
|
2017-02-14 00:25:02 +00:00
|
|
|
-- Suck an item from the container above into the hopper
|
|
|
|
local upnode = minetest.get_node(uppos)
|
|
|
|
local g = minetest.registered_nodes[upnode.name].groups.container
|
|
|
|
if g == 2 or g == 3 then
|
|
|
|
-- Typical container inventory
|
|
|
|
mcl_util.move_item_container(uppos, "main", -1, pos)
|
|
|
|
elseif g == 4 then
|
|
|
|
-- Furnace output
|
|
|
|
mcl_util.move_item_container(uppos, "dst", -1, pos)
|
2017-01-17 16:50:56 +00:00
|
|
|
end
|
2017-02-14 00:25:02 +00:00
|
|
|
|
2017-02-14 00:31:24 +00:00
|
|
|
-- Move an item from the hopper into container below
|
2017-02-21 02:38:24 +00:00
|
|
|
local downnode = minetest.get_node(downpos)
|
|
|
|
g = minetest.registered_nodes[downnode.name].groups.container
|
|
|
|
local slot_id = -1
|
|
|
|
if g == 3 then
|
|
|
|
-- For shulker boxes, only select non-shulker boxes
|
|
|
|
local sinv = minetest.get_inventory({type="node", pos = pos})
|
|
|
|
slot_id = get_eligible_transfer_item(sinv, "main", is_not_shulker_box)
|
|
|
|
end
|
|
|
|
if slot_id then
|
|
|
|
mcl_util.move_item_container(pos, "main", slot_id, downpos)
|
|
|
|
end
|
2017-01-17 16:50:56 +00:00
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
minetest.register_abm({
|
2017-01-17 17:41:25 +00:00
|
|
|
nodenames = {"mcl_hoppers:hopper_side"},
|
2017-02-14 00:32:13 +00:00
|
|
|
neighbors = {"group:container"},
|
2017-01-17 16:50:56 +00:00
|
|
|
interval = 1.0,
|
|
|
|
chance = 1,
|
|
|
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
2017-02-14 00:25:02 +00:00
|
|
|
-- Determine to which side the hopper is facing, get nodes
|
|
|
|
local face = minetest.get_node(pos).param2
|
2017-01-17 16:50:56 +00:00
|
|
|
local front = {}
|
|
|
|
if face == 0 then
|
|
|
|
front = {x=pos.x-1,y=pos.y,z=pos.z}
|
|
|
|
elseif face == 1 then
|
|
|
|
front = {x=pos.x,y=pos.y,z=pos.z+1}
|
|
|
|
elseif face == 2 then
|
|
|
|
front = {x=pos.x+1,y=pos.y,z=pos.z}
|
|
|
|
elseif face == 3 then
|
|
|
|
front = {x=pos.x,y=pos.y,z=pos.z-1}
|
|
|
|
end
|
2017-02-14 00:25:02 +00:00
|
|
|
local above = {x=pos.x,y=pos.y+1,z=pos.z}
|
2017-01-17 16:50:56 +00:00
|
|
|
|
2017-02-14 00:25:02 +00:00
|
|
|
local frontnode = minetest.get_node(front)
|
2017-02-22 13:00:58 +00:00
|
|
|
|
2017-02-14 00:25:02 +00:00
|
|
|
-- Suck an item from the container above into the hopper
|
|
|
|
local abovenode = minetest.get_node(above)
|
|
|
|
local g = minetest.registered_nodes[abovenode.name].groups.container
|
|
|
|
if g == 2 or g == 3 then
|
|
|
|
-- Typical container inventory
|
|
|
|
mcl_util.move_item_container(above, "main", -1, pos)
|
|
|
|
elseif g == 4 then
|
|
|
|
-- Furnace output
|
|
|
|
mcl_util.move_item_container(above, "dst", -1, pos)
|
2017-01-17 16:50:56 +00:00
|
|
|
end
|
2017-02-14 00:31:24 +00:00
|
|
|
|
|
|
|
-- Move an item from the hopper into the container to which the hopper points to
|
2017-02-21 01:09:34 +00:00
|
|
|
local g = minetest.registered_nodes[frontnode.name].groups.container
|
2017-02-21 02:38:24 +00:00
|
|
|
if g == 2 then
|
2017-02-21 01:09:34 +00:00
|
|
|
mcl_util.move_item_container(pos, "main", -1, front)
|
2017-02-21 02:38:24 +00:00
|
|
|
elseif g == 3 then
|
|
|
|
-- Put non-shulker boxes into shulker box
|
|
|
|
local sinv = minetest.get_inventory({type="node", pos = pos})
|
|
|
|
local slot_id = get_eligible_transfer_item(sinv, "main", is_not_shulker_box)
|
|
|
|
if slot_id then
|
|
|
|
mcl_util.move_item_container(pos, "main", slot_id, front)
|
|
|
|
end
|
2017-02-21 01:09:34 +00:00
|
|
|
elseif g == 4 then
|
2017-02-21 02:22:25 +00:00
|
|
|
-- Put fuel into fuel slot
|
2017-02-21 02:38:24 +00:00
|
|
|
local sinv = minetest.get_inventory({type="node", pos = pos})
|
|
|
|
local slot_id = get_eligible_transfer_item(sinv, "main", mcl_util.is_fuel)
|
2017-02-21 02:22:25 +00:00
|
|
|
if slot_id then
|
|
|
|
mcl_util.move_item_container(pos, "main", slot_id, front, "fuel")
|
|
|
|
end
|
2017-02-21 01:09:34 +00:00
|
|
|
end
|
2017-02-14 00:25:02 +00:00
|
|
|
end
|
2017-01-17 16:50:56 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_craft({
|
2017-02-22 13:00:58 +00:00
|
|
|
output = "mcl_hoppers:hopper",
|
2017-01-17 16:50:56 +00:00
|
|
|
recipe = {
|
2017-02-11 20:14:40 +00:00
|
|
|
{"mcl_core:iron_ingot","","mcl_core:iron_ingot"},
|
|
|
|
{"mcl_core:iron_ingot","mcl_chests:chest","mcl_core:iron_ingot"},
|
|
|
|
{"","mcl_core:iron_ingot",""},
|
2017-01-17 16:50:56 +00:00
|
|
|
}
|
|
|
|
})
|
2017-02-22 13:00:58 +00:00
|
|
|
|
|
|
|
-- Legacy
|
|
|
|
minetest.register_alias("mcl_hoppers:hopper_item", "mcl_hoppers:hopper")
|