git subrepo clone https://github.com/tenplus1/hopper.git mods/hopper
subrepo: subdir: "mods/hopper" merged: "00779b5" upstream: origin: "https://github.com/tenplus1/hopper.git" branch: "master" commit: "00779b5" git-subrepo: version: "0.3.1" origin: "https://github.com/ingydotnet/git-subrepo" commit: "a7ee886"master
|
@ -0,0 +1,11 @@
|
|||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = https://github.com/tenplus1/hopper.git
|
||||
branch = master
|
||||
commit = 00779b5f11f5111bc08d52d25b55ddac7c7b8d14
|
||||
parent = 60957d74691c4afc189f2dfa72bf4df7d6bcda73
|
||||
cmdver = 0.3.1
|
|
@ -0,0 +1,23 @@
|
|||
Hopper mod
|
||||
|
||||
Based on jordan4ibanez original mod and optimized by TenPlus1
|
||||
|
||||
Hoppers allow for items dropped on top to be sucked in and transfered to chests/hoppers below and beside the original hopper. Chests above hopper will have items inside transfered into hopper. Furnaces above hopper will have output transfered into hopper, furnaces below will have hopper items dropped into source material to be cooked and furnaces to the side will have hopper items copied into fuel slot.
|
||||
|
||||
Change log:
|
||||
|
||||
- 0.1 - Initial release from jordan4ibanez
|
||||
- 0.2 - Fixed tool glitch (wear restored by accident)
|
||||
- 0.3 - transfer function added
|
||||
- 0.4 - Supports locked chest and protected chest
|
||||
- 0.5 - Works with 0.4.13's new shift+click for newly placed Hoppers
|
||||
- 0.6 - Remove formspec from hopper nodes to improve speed for servers
|
||||
- 0.7 - Halved hopper capacity, can be dug by wooden pick
|
||||
- 0.8 - Added Napiophelios' new textures and tweaked code
|
||||
- 0.9 - Added support for Wine mod's wine barrels
|
||||
- 1.0 - New furances do not work properly with hoppers so old reverted to abm furnaces
|
||||
- 1.1 - Hoppers now work with new node timer Furnaces. Reduced Abm's and tidied code
|
||||
- 1.2 - Added simple API so that hoppers can work with other containers
|
||||
- 1.3 - Tweaked code to use a single abm and added intllib support
|
||||
|
||||
Lucky Blocks: 2
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
Hopper API
|
||||
----------
|
||||
|
||||
This API is kept simple by adding a single command which allows mods to add
|
||||
containers like chests and furnaces to the hopper check list.
|
||||
|
||||
|
||||
Command Usage
|
||||
-------------
|
||||
|
||||
Make sure any mods using this function has 'hopper' in the depends.txt file.
|
||||
|
||||
hopper:add_container({ {"where_from", "node_name", "inventory_name"} })
|
||||
|
||||
'where_from' is a string telling the api that items are coming from either
|
||||
the 'top' node into a hopper below, going into the 'bottom' node
|
||||
from the hopper above or coming from a 'side' hopper into the
|
||||
node next door.
|
||||
|
||||
'node_name" is the name of the container itself (e.g. "default:chest")
|
||||
|
||||
'inventory_name' is the name of the container inventory that is affected.
|
||||
|
||||
e.g.
|
||||
|
||||
hopper:add_container({
|
||||
{"top", "default:furnace", "dst"}, -- take cooked items from above into hopper below
|
||||
{"bottom", "default:furnace", "src"}, -- insert items below to be cooked from hopper above
|
||||
{"side", "default:furnace", "fuel"}, -- replenish furnace fuel from hopper at side
|
||||
})
|
||||
|
||||
|
||||
We already have support for the wine barrel inside of the Wine mod and protected
|
||||
chests inside of Protector Redo, as well as default chests, furnaces and hoppers
|
||||
themselves.
|
||||
|
||||
Note: Hoppers can transfer into locked chests but not take from them (yet).
|
|
@ -0,0 +1,3 @@
|
|||
default
|
||||
intllib?
|
||||
lucky_block?
|
|
@ -0,0 +1 @@
|
|||
Adds hoppers to transport items between chests/furnace etc.
|
|
@ -0,0 +1,449 @@
|
|||
|
||||
-- define global
|
||||
hopper = {}
|
||||
|
||||
|
||||
-- Intllib
|
||||
local S
|
||||
|
||||
if minetest.get_modpath("intllib") then
|
||||
S = intllib.Getter()
|
||||
else
|
||||
S = function(s, a, ...) a = {a, ...}
|
||||
return s:gsub("@(%d+)", function(n)
|
||||
return a[tonumber(n)]
|
||||
end)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- default containers
|
||||
local containers = {
|
||||
|
||||
{"top", "hopper:hopper", "main"},
|
||||
{"bottom", "hopper:hopper", "main"},
|
||||
{"side", "hopper:hopper", "main"},
|
||||
{"side", "hopper:hopper_side", "main"},
|
||||
|
||||
{"top", "default:chest", "main"},
|
||||
{"bottom", "default:chest", "main"},
|
||||
{"side", "default:chest", "main"},
|
||||
|
||||
{"top", "default:furnace", "dst"},
|
||||
{"bottom", "default:furnace", "src"},
|
||||
{"side", "default:furnace", "fuel"},
|
||||
|
||||
{"top", "default:furnace_active", "dst"},
|
||||
{"bottom", "default:furnace_active", "src"},
|
||||
{"side", "default:furnace_active", "fuel"},
|
||||
|
||||
{"bottom", "default:chest_locked", "main"},
|
||||
{"side", "default:chest_locked", "main"},
|
||||
}
|
||||
|
||||
-- global function to add new containers
|
||||
function hopper:add_container(list)
|
||||
|
||||
for n = 1, #list do
|
||||
table.insert(containers, list[n])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- protector redo mod support
|
||||
if minetest.get_modpath("protector") then
|
||||
|
||||
hopper:add_container({
|
||||
{"top", "protector:chest", "main"},
|
||||
{"bottom", "protector:chest", "main"},
|
||||
{"side", "protector:chest", "main"},
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
-- wine mod support
|
||||
if minetest.get_modpath("wine") then
|
||||
|
||||
hopper:add_container({
|
||||
{"top", "wine:wine_barrel", "dst"},
|
||||
{"bottom", "wine:wine_barrel", "src"},
|
||||
{"side", "wine:wine_barrel", "src"},
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
-- formspec
|
||||
local function get_hopper_formspec(pos)
|
||||
|
||||
local spos = pos.x .. "," .. pos.y .. "," ..pos.z
|
||||
local formspec =
|
||||
"size[8,9]"
|
||||
.. default.gui_bg
|
||||
.. default.gui_bg_img
|
||||
.. default.gui_slots
|
||||
.. "list[nodemeta:" .. spos .. ";main;0,0.3;8,4;]"
|
||||
.. "list[current_player;main;0,4.85;8,1;]"
|
||||
.. "list[current_player;main;0,6.08;8,3;8]"
|
||||
.. "listring[nodemeta:" .. spos .. ";main]"
|
||||
.. "listring[current_player;main]"
|
||||
|
||||
return formspec
|
||||
end
|
||||
|
||||
|
||||
-- hopper
|
||||
minetest.register_node("hopper:hopper", {
|
||||
description = S("Hopper (Place onto sides for side-hopper)"),
|
||||
groups = {cracky = 3},
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
tiles = {"hopper_top.png", "hopper_top.png", "hopper_front.png"},
|
||||
inventory_image = "hopper_inv.png",
|
||||
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)
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
inv:set_size("main", 4*4)
|
||||
end,
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
|
||||
local pos = pointed_thing.above
|
||||
local x = pointed_thing.under.x - pos.x
|
||||
local z = pointed_thing.under.z - pos.z
|
||||
|
||||
if x == -1 then
|
||||
minetest.set_node(pos, {name = "hopper:hopper_side", param2 = 0})
|
||||
|
||||
elseif x == 1 then
|
||||
minetest.set_node(pos, {name = "hopper:hopper_side", param2 = 2})
|
||||
|
||||
elseif z == -1 then
|
||||
minetest.set_node(pos, {name = "hopper:hopper_side", param2 = 3})
|
||||
|
||||
elseif z == 1 then
|
||||
minetest.set_node(pos, {name = "hopper:hopper_side", param2 = 1})
|
||||
|
||||
else
|
||||
minetest.set_node(pos, {name = "hopper:hopper"})
|
||||
end
|
||||
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
itemstack:take_item()
|
||||
end
|
||||
|
||||
return itemstack
|
||||
end,
|
||||
|
||||
can_dig = function(pos, player)
|
||||
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
|
||||
return inv:is_empty("main")
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker, itemstack)
|
||||
|
||||
if minetest.is_protected(pos, clicker:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(),
|
||||
"hopper:hopper", get_hopper_formspec(pos))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
|
||||
minetest.log("action", S("@1 moves stuff in hopper at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
|
||||
minetest.log("action", S("@1 moves stuff to hopper at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
|
||||
minetest.log("action", S("@1 moves stuff from hopper at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.disallow,
|
||||
})
|
||||
|
||||
|
||||
-- side hopper
|
||||
minetest.register_node("hopper:hopper_side", {
|
||||
description = S("Side Hopper (Place into crafting to return normal Hopper)"),
|
||||
groups = {cracky = 3, not_in_creative_inventory = 1},
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
tiles = {
|
||||
"hopper_top.png", "hopper_top.png", "hopper_back.png",
|
||||
"hopper_side.png", "hopper_back.png", "hopper_back.png"
|
||||
},
|
||||
inventory_image = "hopper_side_inv.png",
|
||||
drop = "hopper:hopper",
|
||||
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)
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
inv:set_size("main", 4*4)
|
||||
end,
|
||||
|
||||
can_dig = function(pos, player)
|
||||
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
|
||||
return inv:is_empty("main")
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker, itemstack)
|
||||
|
||||
if minetest.is_protected(pos, clicker:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(),
|
||||
"hopper:hopper_side", get_hopper_formspec(pos))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
|
||||
minetest.log("action", S("@1 moves stuff in hopper at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
|
||||
minetest.log("action", S("@1 moves stuff to hopper at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
|
||||
minetest.log("action", S("@1 moves stuff from hopper at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_rotate = screwdriver.rotate_simple,
|
||||
})
|
||||
|
||||
|
||||
-- transfer function
|
||||
local transfer = function(src, srcpos, dst, dstpos)
|
||||
|
||||
-- source inventory
|
||||
local inv = minetest.get_meta(srcpos):get_inventory()
|
||||
|
||||
-- destination inventory
|
||||
local inv2 = minetest.get_meta(dstpos):get_inventory()
|
||||
|
||||
-- check for empty source or no inventory
|
||||
if not inv or not inv2 or inv:is_empty(src) == true then
|
||||
return
|
||||
end
|
||||
|
||||
local stack, item
|
||||
|
||||
-- transfer item
|
||||
for i = 1, inv:get_size(src) do
|
||||
|
||||
stack = inv:get_stack(src, i)
|
||||
item = stack:get_name()
|
||||
|
||||
-- if slot not empty and room for item in destination
|
||||
if item ~= ""
|
||||
and inv2:room_for_item(dst, item) then
|
||||
|
||||
-- is item a tool
|
||||
if stack:get_wear() > 0 then
|
||||
inv2:add_item(dst, stack:take_item(stack:get_count()))
|
||||
inv:set_stack(src, i, nil)
|
||||
else -- not a tool
|
||||
stack:take_item(1)
|
||||
inv2:add_item(dst, item)
|
||||
inv:set_stack(src, i, stack)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- hopper workings
|
||||
minetest.register_abm({
|
||||
|
||||
label = "Hopper suction and transfer",
|
||||
nodenames = {"hopper:hopper", "hopper:hopper_side"},
|
||||
interval = 1.0,
|
||||
chance = 1,
|
||||
catch_up = false,
|
||||
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
|
||||
-- do we have any entities nearby to suck into hopper?
|
||||
if active_object_count > 0 then
|
||||
|
||||
local inv = minetest.get_meta(pos):get_inventory()
|
||||
|
||||
for _,object in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
|
||||
if not object:is_player()
|
||||
and object:get_luaentity()
|
||||
and object:get_luaentity().name == "__builtin:item"
|
||||
and inv
|
||||
and inv:room_for_item("main",
|
||||
ItemStack(object:get_luaentity().itemstring)) then
|
||||
|
||||
if object:getpos().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
|
||||
|
||||
|
||||
local front
|
||||
|
||||
-- if side hopper check which way spout is facing
|
||||
if node.name == "hopper:hopper_side" then
|
||||
|
||||
local face = minetest.get_node(pos).param2
|
||||
|
||||
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}
|
||||
else
|
||||
return
|
||||
end
|
||||
else
|
||||
-- otherwise normal hopper, output downwards
|
||||
front = {x = pos.x, y = pos.y - 1, z = pos.z}
|
||||
end
|
||||
|
||||
-- get node above hopper
|
||||
local top = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name
|
||||
|
||||
-- get node at other end of spout
|
||||
local out = minetest.get_node(front).name
|
||||
|
||||
local where, nod, inv, def
|
||||
|
||||
-- do for loop here for api check
|
||||
for n = 1, #containers do
|
||||
|
||||
where = containers[n][1]
|
||||
nod = containers[n][2]
|
||||
inv = containers[n][3]
|
||||
|
||||
-- from top node into hopper below
|
||||
if where == "top" and top == nod
|
||||
and (node.name == "hopper:hopper" or node.name == "hopper:hopper_side") then
|
||||
--print ("-- top")
|
||||
transfer(inv, {x = pos.x, y = pos.y + 1, z = pos.z}, "main", pos)
|
||||
minetest.get_node_timer(
|
||||
{x = pos.x, y = pos.y + 1, z = pos.z}):start(0.5)
|
||||
-- return
|
||||
|
||||
-- from top hopper into node below
|
||||
elseif where == "bottom" and out == nod
|
||||
and node.name == "hopper:hopper" then
|
||||
--print ("-- bot")
|
||||
transfer("main", pos, inv, front)
|
||||
minetest.get_node_timer(front):start(0.5)
|
||||
-- return
|
||||
|
||||
-- side hopper into container beside
|
||||
elseif where == "side" and out == nod
|
||||
and node.name == "hopper:hopper_side" then
|
||||
--print ("-- sid")
|
||||
transfer("main", pos, inv, front)
|
||||
minetest.get_node_timer(front):start(0.5)
|
||||
-- return
|
||||
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- hopper recipe
|
||||
minetest.register_craft({
|
||||
output = "hopper:hopper",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "default:chest", "default:steel_ingot"},
|
||||
{"", "default:steel_ingot", ""},
|
||||
},
|
||||
})
|
||||
|
||||
-- side hopper to hopper recipe
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "hopper:hopper",
|
||||
recipe = {"hopper:hopper_side"},
|
||||
})
|
||||
|
||||
-- add lucky blocks
|
||||
if minetest.get_modpath("lucky_block") then
|
||||
|
||||
lucky_block:add_blocks({
|
||||
{"dro", {"hopper:hopper"}, 3},
|
||||
{"nod", "default:lava_source", 1},
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
print (S("[MOD] Hopper loaded"))
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 TenPlus1
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -0,0 +1,11 @@
|
|||
# Template for translations of hopper mod
|
||||
# German translation by Xanthin
|
||||
# last update: 1st February 2017
|
||||
|
||||
#init.lua
|
||||
[MOD] Hopper loaded = [MOD] Trichter geladen
|
||||
Hopper (Place onto sides for side-hopper) = Trichter (für Seitentrichter an den Seiten platzieren)
|
||||
Side Hopper (Place into crafting to return normal Hopper) = Seitentrichter (in Fertigungsraster legen, um normalen Trichter zu erhalten)
|
||||
@1 moves stuff in hopper at @2 = @1 bewegt Dinge in einem Trichter bei @2
|
||||
@1 moves stuff to hopper at @2 = @1 verlagert Dinge in einen Trichter bei @2
|
||||
@1 moves stuff from hopper at @2 = @1 nimmt Dinge aus einem Trichter bei @2
|
|
@ -0,0 +1,10 @@
|
|||
# Template for translations of hopper mod
|
||||
# last update: 1st February 2017
|
||||
|
||||
#init.lua
|
||||
[MOD] Hopper loaded =
|
||||
Hopper (Place onto sides for side-hopper) =
|
||||
Side Hopper (Place into crafting to return normal Hopper) =
|
||||
@1 moves stuff in hopper at @2
|
||||
@1 moves stuff to hopper at @2
|
||||
@1 moves stuff from hopper at @2
|
|
@ -0,0 +1 @@
|
|||
name = hopper
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 500 B |
After Width: | Height: | Size: 494 B |
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 451 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 624 B |