v1.0, Hopper added, buffer improved, docu improved, readme reworked
parent
766bf758d6
commit
ca1bde4dbf
87
README.md
87
README.md
|
@ -1,7 +1,7 @@
|
|||
Minecart
|
||||
========
|
||||
|
||||
**A minecart running through unloaded areas for Minetest v5.0+**
|
||||
**Minecart, the lean railway transportation automation system**
|
||||
|
||||
|
||||
Browse on: ![GitHub](https://github.com/joe7575/minecart)
|
||||
|
@ -26,45 +26,71 @@ license).
|
|||
3. https://github.com/stujones11/railcart/
|
||||
|
||||
|
||||
Original Features
|
||||
-----------------
|
||||
Original Cart Features
|
||||
----------------------
|
||||
|
||||
- A fast cart for your railway or roller coaster (up to 7 m/s!)
|
||||
- Boost and brake rails
|
||||
- Rail junction switching with the 'right-left' walking keys
|
||||
- Handbrake with the 'back' key
|
||||
|
||||
New Features
|
||||
------------
|
||||
- Minecart has its own cart in addition to the standard cart.
|
||||
- The Minecart can "run" through unloaded areas. This is done by
|
||||
means of recorded and stored routes. If the area is unloaded
|
||||
the cart will simply follow the predefined route until an
|
||||
area is loaded again. In this case the cart will be spawned and
|
||||
run as usual.
|
||||
- The Minecart is protected and can't be removed by foreign players.
|
||||
- The mod adds Protection Landmarks to protect the rails
|
||||
- To store a route, a player has to place Railway Buffers on both ends,
|
||||
and use the Minecart to drive the route in both directions.
|
||||
- The digging of protected Minecarts and rails is only possible as an owner
|
||||
or with 'minecart' privs.
|
||||
|
||||
Use Case
|
||||
--------
|
||||
The main use of the Minecart is for item transport from mines to warehouses,
|
||||
ideally by means of an automation mod like Signs Bot.
|
||||
https://github.com/joe7575/signs_bot
|
||||
Minecart Features
|
||||
-----------------
|
||||
|
||||
The mod Minecart has its own cart (called Minecart) in addition to the standard cart.
|
||||
Minecarts are used for automated item transport on private and public rail networks.
|
||||
The mod features are:
|
||||
- configurable timetables and routes for Minecarts
|
||||
- automated loading/unloading of Minecarts by means of a Minecart Hopper
|
||||
- rail network protection based on protection blocks called Land Marks
|
||||
- protection of minecarts and cargo
|
||||
- Minecarts run through unloaded areas (only the stations/hopper have to be loaded)
|
||||
- Extra Minecard privs for rail workers
|
||||
- Ingame documentation (German and English), based on the mod "doc"
|
||||
|
||||
|
||||
Technical Background
|
||||
--------------------
|
||||
|
||||
The Minecart can "run" through unloaded areas. This is done by means of recorded
|
||||
and stored routes. If the area is unloaded the cart will simply follow the
|
||||
predefined route until an area is loaded again. In this case the cart will be
|
||||
spawned and run as usual.
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
1. Place your rails and build a route with two ends. Junctions are allowed as
|
||||
long as each route has its own start and end point.
|
||||
2. Place a Railway Buffer at both ends.
|
||||
3. Protect your rails with the Protection Landmarks (one Landmark at least every 16 blocks)
|
||||
4. Drive the route in both directions (route recording), starting at the Railway Buffers.
|
||||
5. Now you can drop items into the Minecart and punch the cart to get started.
|
||||
6. Sneak+click the cart to get the items back
|
||||
7. Dig the empty cart with a second sneak+Click (as usual).
|
||||
1. Place your rails and build a route with two endpoints. Junctions are allowed
|
||||
as long as each route has its own start and endpoint.
|
||||
2. Place a Railway Buffer at both endpoints. (buffers are always needed,
|
||||
they store the route and timing information)
|
||||
3. Give both Railway Buffers unique station names, like Oxford and Cambridge
|
||||
4. Drive from buffer to buffer in both directions using a Minecart(!) to record the
|
||||
routes (use 'right-left' keys to control the Minecart)
|
||||
5. Punch the buffers to check the connection data (e.g. "Oxford: connected to Cambridge")
|
||||
6. Optional: Configure the Minecart stop time in one or both buffers. The Minecart
|
||||
will then start automatically after the configured time
|
||||
7. Optional: Protect your rail network with the Protection Landmarks (one Landmark
|
||||
at least every 16 nodes/meters)
|
||||
8. Place a Minecart in front of the buffer and check whether it starts after the
|
||||
configured time
|
||||
9. Drop items into the Minecart and punch the cart to start it, or "sneak+click" the
|
||||
Minecart to get the items back
|
||||
10. Dig the empty cart with a second "sneak+click" (as usual)
|
||||
|
||||
|
||||
Hopper
|
||||
------
|
||||
|
||||
![hopper](https://github.com/joe7575/minecart/blob/master/hopper.png)
|
||||
|
||||
The Hopper is used to load/unload Minecarts.
|
||||
The Hopper can pull and push items into/out off chests and can drop/pick up items
|
||||
to/from Minecarts. To unload a Minecart place the hopper below the rail.
|
||||
To load the Minecart, place the hopper right next to the Minecart.
|
||||
|
||||
|
||||
History
|
||||
-------
|
||||
|
@ -76,3 +102,4 @@ History
|
|||
2019-05-04 v0.05 Route recording protection added
|
||||
2019-05-22 v0.06 Pick up items from a cart improved
|
||||
2019-06-23 v0.07 'doc' mod support and German translation added
|
||||
2020-01-04 v1.00 Hopper added, buffer improved
|
||||
|
|
106
buffer.lua
106
buffer.lua
|
@ -1,26 +1,53 @@
|
|||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local S = minecart.S
|
||||
|
||||
local CYCLE_TIME = 2
|
||||
|
||||
local StopTime = {}
|
||||
|
||||
local function formspec(pos)
|
||||
local name = M(pos):get_string("name")
|
||||
local time = M(pos):get_int("time")
|
||||
local s = "size[4,4.2]" ..
|
||||
"label[0,0;Configuration]" ..
|
||||
"field[0.5,1.2;3.6,1;name;"..S("Station name")..":;"..name.."]"..
|
||||
"button_exit[1,3.4;2,1;exit;Save]"
|
||||
if minecart.hopper_enabled then
|
||||
return s.."field[0.5,2.5;3.6,1;time;"..S("Stop time/sec")..":;"..time.."]"
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
local function remote_station_name(pos)
|
||||
local route = minecart.get_route(P2S(pos))
|
||||
if route and route.dest_pos then
|
||||
local pos2 = S2P(route.dest_pos)
|
||||
return M(pos2):get_string("name")
|
||||
end
|
||||
return "none"
|
||||
end
|
||||
|
||||
local function on_punch(pos, node, puncher)
|
||||
local start_key = P2S(pos)
|
||||
local route = minecart.get_route(start_key)
|
||||
if next(route.waypoints) then
|
||||
minetest.chat_send_player(puncher:get_player_name(),
|
||||
S("[minecart] Route available"))
|
||||
local no_cart = true
|
||||
for key,item in pairs(minecart.CartsOnRail) do
|
||||
if item.start_key == start_key or item.start_key == route.dest_pos then
|
||||
local pos, vel = minecart.calc_pos_and_vel(item)
|
||||
minetest.chat_send_player(puncher:get_player_name(), S("[minecart] One cart at").." "..
|
||||
P2S(pos)..", "..S("velocity").." "..vector.length(vel))
|
||||
no_cart = false
|
||||
end
|
||||
end
|
||||
if no_cart then
|
||||
minetest.chat_send_player(puncher:get_player_name(), S("[minecart] No cart available"))
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(puncher:get_player_name(), S("[minecart] No route stored!"))
|
||||
local name = M(pos):get_string("name")
|
||||
M(pos):set_string("infotext", name..": "..S("connected to").." "..remote_station_name(pos))
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
if minecart.hopper_enabled then
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -49,12 +76,49 @@ minetest.register_node("minecart:buffer", {
|
|||
fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16},
|
||||
},
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
M(pos):set_string("owner", placer:get_player_name())
|
||||
minecart.del_route(minetest.pos_to_string(pos))
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
if minecart.hopper_enabled then
|
||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||
end
|
||||
end,
|
||||
on_timer = function(pos, elapsed)
|
||||
local time = M(pos):get_int("time")
|
||||
if time > 0 then
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
local param2 = (minetest.get_node(pos).param2 + 2) % 4
|
||||
if minecart.check_cart(pos, param2) then
|
||||
if StopTime[hash] then
|
||||
if StopTime[hash] < minetest.get_gametime() then
|
||||
StopTime[hash] = nil
|
||||
minecart.punch_cart(pos, param2)
|
||||
minecart.hopper_resync(pos, param2)
|
||||
end
|
||||
else
|
||||
StopTime[hash] = minetest.get_gametime() + time
|
||||
end
|
||||
else
|
||||
StopTime[hash] = nil
|
||||
end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
after_dig_node = function(pos)
|
||||
minecart.del_route(minetest.pos_to_string(pos))
|
||||
local hash = minetest.hash_node_position(pos)
|
||||
StopTime[hash] = nil
|
||||
end,
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
if M(pos):get_string("owner") ~= player:get_player_name() then
|
||||
return
|
||||
end
|
||||
if (fields.key_enter == "true" or fields.exit == "Save") and fields.name ~= "" then
|
||||
M(pos):set_string("name", fields.name)
|
||||
M(pos):set_int("time", tonumber(fields.time) or 0)
|
||||
M(pos):set_string("formspec", formspec(pos))
|
||||
M(pos):set_string("infotext", fields.name.." "..S("connected to").." "..remote_station_name(pos))
|
||||
end
|
||||
end,
|
||||
on_punch = on_punch,
|
||||
sunlight_propagates = true,
|
||||
|
|
41
doc.lua
41
doc.lua
|
@ -1,3 +1,16 @@
|
|||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
|
||||
minecart.doc = {}
|
||||
|
||||
if not minetest.get_modpath("doc") then
|
||||
|
@ -10,13 +23,16 @@ local summary_doc = table.concat({
|
|||
S("Summary"),
|
||||
"------------",
|
||||
"",
|
||||
S("1. Place your rails and build a route with two ends. Junctions are allowed as long as each route has its own start and end point."),
|
||||
S("2. Place a Railway Buffer at both ends."),
|
||||
S("3. Protect your rails with the Protection Landmarks (one Landmark at least every 16 blocks)"),
|
||||
S("4. Drive the route in both directions (route recording), starting at the Railway Buffers."),
|
||||
S("5. Now you can drop items into the Minecart and punch the cart to get started."),
|
||||
S("6. Sneak+click the cart to get the items back"),
|
||||
S("7. Dig the empty cart with a second sneak+Click (as usual).")
|
||||
S("1. Place your rails and build a route with two endpoints. Junctions are allowed as long as each route has its own start and endpoint."),
|
||||
S("2. Place a Railway Buffer at both endpoints (buffers are always needed, they store the route and timing information)."),
|
||||
S("3. Give both Railway Buffers unique station names, like Oxford and Cambridge."),
|
||||
S("4. Drive from buffer to buffer in both directions using a Minecart(!) to record the routes (use 'right-left' keys to control the Minecart)."),
|
||||
S("5. Punch the buffers to check the connection data (e.g. 'Oxford: connected to Cambridge')."),
|
||||
S("6. Optional: Configure the Minecart stop time in one or both buffers. The Minecart will then start automatically after the configured time."),
|
||||
S("7. Optional: Protect your rail network with the Protection Landmarks (one Landmark at least every 16 nodes/meters)."),
|
||||
S("8. Place a Minecart in front of the buffer and check whether it starts after the configured time."),
|
||||
S("9. Drop items into the Minecart and punch the cart to start it, or 'sneak+click' the Minecart to get the items back."),
|
||||
S("10. Dig the empty cart with a second 'sneak+click' (as usual)."),
|
||||
}, "\n")
|
||||
|
||||
local cart_doc = S("Primary used to transport items. You can drop items into the Minecart and punch the cart to get started. Sneak+click the cart to get the items back")
|
||||
|
@ -25,6 +41,9 @@ local buffer_doc = S("Used as buffer on both rail ends. Needed to be able to rec
|
|||
|
||||
local landmark_doc = S("Protect your rails with the Landmarks (one Landmark at least every 16 blocks near the rail)")
|
||||
|
||||
local hopper_doc = S("Used to load/unload Minecart. The Hopper can push/pull items to/from chests and drop/pickup items to/from Minecarts. To unload a Minecart place the hopper below the rail. To load the Minecart, place the hopper right next to the Minecart.")
|
||||
|
||||
|
||||
local function formspec(data)
|
||||
if data.image then
|
||||
local image = "image["..(doc.FORMSPEC.ENTRY_WIDTH - 3)..",0;3,2;"..data.image.."]"
|
||||
|
@ -43,7 +62,7 @@ end
|
|||
doc.add_category("minecart",
|
||||
{
|
||||
name = S("Minecart"),
|
||||
description = S("A minecart running through unloaded areas, mainly used for item transportation"),
|
||||
description = S("Minecart, the lean railway transportation automation system"),
|
||||
sorting = "custom",
|
||||
sorting_data = {"summary", "cart"},
|
||||
build_formspec = formspec,
|
||||
|
@ -69,3 +88,9 @@ doc.add_entry("minecart", "landmark", {
|
|||
data = {text = landmark_doc, item="minecart:landmark"},
|
||||
})
|
||||
|
||||
if minecart.hopper_enabled then
|
||||
doc.add_entry("minecart", "hopper", {
|
||||
name = S("Minecart Hopper"),
|
||||
data = {text=hopper_doc, item="minecart:hopper"},
|
||||
})
|
||||
end
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
local NUM_ITEMS = 4
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local S = minecart.S
|
||||
|
||||
local function scan_for_objects(pos, inv)
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
local lua_entity = object:get_luaentity()
|
||||
if not object:is_player() and lua_entity and lua_entity.name == "__builtin:item" then
|
||||
if lua_entity.itemstring ~= "" then
|
||||
local stack = ItemStack(lua_entity.itemstring)
|
||||
if inv:room_for_item("main", stack) then
|
||||
inv:add_item("main", stack)
|
||||
object:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function pull_push_item(pos, param2)
|
||||
local items = minecart.take_items(pos, param2, NUM_ITEMS)
|
||||
if items then
|
||||
local leftover = minecart.put_items(pos, param2, items)
|
||||
if leftover then
|
||||
-- place item back
|
||||
minecart.untake_items(pos, param2, leftover)
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function push_item(pos, inv, param2)
|
||||
local taken = minecart.inv_take_items(inv, "main", NUM_ITEMS)
|
||||
if taken then
|
||||
local leftover = minecart.put_items(pos, param2, taken)
|
||||
if leftover then
|
||||
inv:add_item("main", leftover)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local formspec = "size[8,6.5]"..
|
||||
"list[context;main;2,0;2,2;]"..
|
||||
"list[current_player;main;0,2.7;8,4;]"..
|
||||
"listring[context;main]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
minetest.register_node("minecart:hopper", {
|
||||
description = S("Minecart Hopper"),
|
||||
tiles = {
|
||||
-- up, down, right, left, back, front
|
||||
"default_cobble.png^minecart_appl_hopper_top.png",
|
||||
"default_cobble.png^minecart_appl_hopper.png",
|
||||
"default_cobble.png^minecart_appl_hopper_right.png",
|
||||
"default_cobble.png^minecart_appl_hopper.png",
|
||||
"default_cobble.png^minecart_appl_hopper.png",
|
||||
"default_cobble.png^minecart_appl_hopper.png",
|
||||
},
|
||||
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, 2/16, -8/16, 8/16, 8/16, -6/16},
|
||||
{-8/16, 2/16, 6/16, 8/16, 8/16, 8/16},
|
||||
{-8/16, 2/16, -8/16, -6/16, 8/16, 8/16},
|
||||
{ 6/16, 2/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-6/16, 0/16, -6/16, 6/16, 3/16, 6/16},
|
||||
{-5/16, -4/16, -5/16, 5/16, 0/16, 5/16},
|
||||
{ 0/16, -4/16, -3/16, 11/16, 2/16, 3/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-8/16, 2/16, -8/16, 8/16, 8/16, 8/16},
|
||||
{-5/16, -4/16, -5/16, 5/16, 0/16, 5/16},
|
||||
{ 0/16, -4/16, -3/16, 11/16, 2/16, 3/16},
|
||||
},
|
||||
},
|
||||
|
||||
on_construct = function(pos)
|
||||
local inv = M(pos):get_inventory()
|
||||
inv:set_size('main', 4)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = M(pos)
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
meta:set_string("formspec", formspec)
|
||||
minetest.get_node_timer(pos):start(2)
|
||||
end,
|
||||
|
||||
on_timer = function(pos, elapsed)
|
||||
local inv = M(pos):get_inventory()
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
param2 = (param2 + 1) % 4 -- output is on the right
|
||||
if not pull_push_item(pos, param2) then
|
||||
scan_for_objects({x=pos.x, y=pos.y+1, z=pos.z}, inv)
|
||||
push_item(pos, inv, param2)
|
||||
end
|
||||
return true
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
minetest.get_node_timer(pos):start(2)
|
||||
return stack:get_count()
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||
for _,stack in ipairs(oldmetadata.inventory.main) do
|
||||
minetest.add_item(pos, stack)
|
||||
end
|
||||
end,
|
||||
|
||||
-- to prevent items from being dropped when the cart is just launched
|
||||
minecart_resync = function(pos)
|
||||
minetest.get_node_timer(pos):stop()
|
||||
minetest.get_node_timer(pos):start(2)
|
||||
end,
|
||||
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
paramtype2 = "facedir",
|
||||
groups = {choppy=2, cracky=2, crumbly=2},
|
||||
is_ground_content = false,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "minecart:hopper",
|
||||
recipe = {
|
||||
{"default:stone", "", "default:stone"},
|
||||
{"default:stone", "default:gold_ingot", "default:stone"},
|
||||
{"", "default:stone", ""},
|
||||
},
|
||||
})
|
Binary file not shown.
After Width: | Height: | Size: 121 KiB |
19
init.lua
19
init.lua
|
@ -1,12 +1,31 @@
|
|||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
minecart = {}
|
||||
|
||||
minecart.hopper_enabled = minetest.settings:get_bool("minecart_hopper_enabled") ~= false
|
||||
|
||||
print("minecart_hopper_enabled", dump(minetest.settings:get_bool("minecart_hopper_enabled")))
|
||||
|
||||
minecart.S = minetest.get_translator("minecart")
|
||||
local MP = minetest.get_modpath("minecart")
|
||||
dofile(MP.."/storage.lua")
|
||||
dofile(MP.."/lib.lua")
|
||||
dofile(MP.."/routes.lua")
|
||||
dofile(MP.."/cart_entity.lua")
|
||||
dofile(MP.."/buffer.lua")
|
||||
dofile(MP.."/protection.lua")
|
||||
if minecart.hopper_enabled then
|
||||
dofile(MP.."/hopper.lua")
|
||||
end
|
||||
dofile(MP.."/doc.lua")
|
||||
minetest.log("info", "[MOD] Minecart loaded")
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local S = minecart.S
|
||||
|
||||
local RegisteredInventories = {}
|
||||
|
||||
local param2_to_dir = {[0]=
|
||||
{x=0, y=0, z=1},
|
||||
{x=1, y=0, z=0},
|
||||
{x=0, y=0, z=-1},
|
||||
{x=-1, y=0, z=0},
|
||||
{x=0, y=-1, z=0},
|
||||
{x=0, y=1, z=0}
|
||||
}
|
||||
|
||||
local function is_air_like(name)
|
||||
local ndef = minetest.registered_nodes[name]
|
||||
if ndef and ndef.buildable_to then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function minecart.get_next_node(pos, param2)
|
||||
local pos2 = vector.add(pos, param2_to_dir[param2])
|
||||
local node = minetest.get_node(pos2)
|
||||
return pos2, node
|
||||
end
|
||||
|
||||
function minecart.check_cart(pos, param2)
|
||||
if param2 then
|
||||
pos = minecart.get_next_node(pos, param2)
|
||||
end
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
|
||||
if object:get_entity_name() == "minecart:cart" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local get_next_node = minecart.get_next_node
|
||||
local check_cart = minecart.check_cart
|
||||
|
||||
-- Take the given number of items from the inv.
|
||||
-- Returns nil if ItemList is empty.
|
||||
function minecart.inv_take_items(inv, listname, num)
|
||||
if inv:is_empty(listname) then
|
||||
return nil
|
||||
end
|
||||
local size = inv:get_size(listname)
|
||||
for idx = 1, size do
|
||||
local items = inv:get_stack(listname, idx)
|
||||
if items:get_count() > 0 then
|
||||
local taken = items:take_item(num)
|
||||
inv:set_stack(listname, idx, items)
|
||||
return taken
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function minecart.take_items(pos, param2, num)
|
||||
local npos, node = get_next_node(pos, (param2 + 2) % 4)
|
||||
local def = RegisteredInventories[node.name]
|
||||
local owner = M(pos):get_string("owner")
|
||||
local inv = minetest.get_inventory({type="node", pos=npos})
|
||||
|
||||
if def and inv and (not def.allow_take or def.allow_take(npos, nil, owner)) then
|
||||
return minecart.inv_take_items(inv, def.take_listname, num)
|
||||
end
|
||||
end
|
||||
|
||||
function minecart.put_items(pos, param2, stack)
|
||||
local npos, node = get_next_node(pos, param2)
|
||||
local def = RegisteredInventories[node.name]
|
||||
local owner = M(pos):get_string("owner")
|
||||
local inv = minetest.get_inventory({type="node", pos=npos})
|
||||
|
||||
if def and inv and (not def.allow_put or def.allow_put(npos, stack, owner)) then
|
||||
local leftover = inv:add_item(def.put_listname, stack)
|
||||
if leftover:get_count() > 0 then
|
||||
return leftover
|
||||
end
|
||||
elseif is_air_like(node.name) or check_cart(npos) then
|
||||
minetest.add_item(npos, stack)
|
||||
else
|
||||
return stack
|
||||
end
|
||||
end
|
||||
|
||||
function minecart.untake_items(pos, param2, stack)
|
||||
local npos, node = get_next_node(pos, (param2 + 2) % 4)
|
||||
local def = RegisteredInventories[node.name]
|
||||
local inv = minetest.get_inventory({type="node", pos=npos})
|
||||
|
||||
if def then
|
||||
return inv and inv:add_item(def.put_listname, stack)
|
||||
end
|
||||
end
|
||||
|
||||
function minecart.punch_cart(pos, param2)
|
||||
local pos2 = minecart.get_next_node(pos, param2)
|
||||
for _, object in pairs(minetest.get_objects_inside_radius(pos2, 0.5)) do
|
||||
if object:get_entity_name() == "minecart:cart" then
|
||||
object:punch(object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
damage_groups = {fleshy = 1},
|
||||
}, minetest.facedir_to_dir(0))
|
||||
break -- start only one cart
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function minecart.hopper_resync(pos, param2)
|
||||
local pos2 = minecart.get_next_node(pos, param2)
|
||||
local pos3 = {x = pos2.x-1, y = pos2.y, z = pos2.z-1}
|
||||
local pos4 = {x = pos2.x+1, y = pos2.y, z = pos2.z-1}
|
||||
for _, pos5 in ipairs(minetest.find_nodes_in_area(pos3, pos4, {"minecart:hopper"})) do
|
||||
local node = minetest.get_node(pos5)
|
||||
local def = minetest.registered_nodes[node.name]
|
||||
def.minecart_resync(pos5)
|
||||
end
|
||||
end
|
||||
|
||||
-- Register inventory node for hopper access
|
||||
-- (for examples, see below)
|
||||
function minecart.register_inventory(node_names, def)
|
||||
for _, name in ipairs(node_names) do
|
||||
RegisteredInventories[name] = {
|
||||
allow_put = def.put and def.put.allow_inventory_put,
|
||||
put_listname = def.put and def.put.listname,
|
||||
allow_take = def.take and def.take.allow_inventory_take,
|
||||
take_listname = def.take and def.take.listname,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
minecart.register_inventory({"default:chest", "default:chest_open"}, {
|
||||
put = {
|
||||
listname = "main",
|
||||
},
|
||||
take = {
|
||||
listname = "main",
|
||||
},
|
||||
})
|
||||
|
||||
minecart.register_inventory({"default:chest_locked", "default:chest_locked_open"}, {
|
||||
put = {
|
||||
allow_inventory_put = function(pos, stack, player_name)
|
||||
local owner = M(pos):get_string("owner")
|
||||
return owner == player_name
|
||||
end,
|
||||
listname = "main",
|
||||
},
|
||||
take = {
|
||||
allow_inventory_take = function(pos, stack, player_name)
|
||||
local owner = M(pos):get_string("owner")
|
||||
return owner == player_name
|
||||
end,
|
||||
listname = "main",
|
||||
},
|
||||
})
|
||||
|
||||
minecart.register_inventory({"minecart:hopper"}, {
|
||||
put = {
|
||||
allow_inventory_put = function(pos, stack, player_name)
|
||||
local owner = M(pos):get_string("owner")
|
||||
return owner == player_name
|
||||
end,
|
||||
listname = "main",
|
||||
},
|
||||
take = {
|
||||
allow_inventory_take = function(pos, stack, player_name)
|
||||
local owner = M(pos):get_string("owner")
|
||||
return owner == player_name
|
||||
end,
|
||||
listname = "main",
|
||||
},
|
||||
})
|
|
@ -1,29 +1,35 @@
|
|||
# textdomain: minecart
|
||||
|
||||
1. Place your rails and build a route with two ends. Junctions are allowed as long as each route has its own start and end point.=1. Baue eine Schienenstrecke mit 2 Enden. Kreuzungen sind zulässig, solange jede Route ihre eigenen Start- und Endepunkt hat.
|
||||
2. Place a Railway Buffer at both ends.=2. Platziere einen Prellbock an beide Schienenenden.
|
||||
3. Protect your rails with the Protection Landmarks (one Landmark at least every 16 blocks)=3. Schütze deine Schienen mit Hilfe der Meilensteine (ein Meilenstein mindestens alle 16 Blöcke).
|
||||
4. Drive the route in both directions (route recording), starting at the Railway Buffers.=4. Fahre die Route in beide Richtungen (um die Route aufzuzeichnen), starte jeweils an den Prellböcken.
|
||||
5. Now you can drop items into the Minecart and punch the cart to get started.=5. Nun kannst du Gegenstände in ein Cart legen (Taste Q) und dann den Wagen durch Anklicken starten.
|
||||
6. Sneak+click the cart to get the items back=6. Klicke mit gedrückter Shift-Taste auf den Wagen, um Gegenstände auszuladen.
|
||||
7. Dig the empty cart with a second sneak+Click (as usual).=7. Klicke erneut mit gedrückter Shift-Taste auf den Wagen, um diesen zu entfernen.
|
||||
1. Place your rails and build a route with two endpoints. Junctions are allowed as long as each route has its own start and endpoint.=1. Baue eine Schienenstrecke mit zwei Enden. Kreuzungen sind zulässig, solange jede Route ihre eigenen Start- und Endpunkte hat.
|
||||
10. Dig the empty cart with a second 'sneak+click' (as usual).=10. Klicke erneut mit gedrückter Shift-Taste auf den Wagen, um diesen zu entfernen.
|
||||
2. Place a Railway Buffer at both endpoints (buffers are always needed, they store the route and timing information).=2. Platziere einen Prellbock an beide Schienenenden (Prellböcke sind zwingend notwendig, sie speichern die Routen- und Zeit-Informationen).
|
||||
3. Give both Railway Buffers unique station names, like Oxford and Cambridge.=3. Gib beiden Prellböcken eindeutige Stationsnamen wie: Stuttgart und München.
|
||||
4. Drive from buffer to buffer in both directions using a Minecart(!) to record the routes (use 'right-left' keys to control the Minecart).=4. Um eine Route aufzuzeichnen, fahre die Route in beide Richtungen von Prellbock zu Prellbock mit einem Minecart Wagen(!). Nutze 'links-rechts' Tasten zur Steuerung.
|
||||
5. Punch the buffers to check the connection data (e.g. 'Oxford: connected to Cambridge').=5. Schlage auf die Prellböcke um die Verbindungsdaten zu prüfen (bspw.: 'München: verbunden mit Stuttgart')
|
||||
6. Optional: Configure the Minecart stop time in one or both buffers. The Minecart will then start automatically after the configured time.=6. Optional: Konfiguriere die Wagenwartezeit in einem oder in beiden Prellböcken. Der Wagen startet dann nach dieser Zeit automatisch.
|
||||
7. Optional: Protect your rail network with the Protection Landmarks (one Landmark at least every 16 nodes/meters).=7. Optional: Schütze deine Schienen mit Hilfe der Meilensteine (ein Meilenstein mindestens alle 16 Blöcke).
|
||||
8. Place a Minecart in front of the buffer and check whether it starts after the configured time.=8. Platziere einen Wagen direkt vor einem Prellbock und prüfe, ob er nach der konfigurierten Zeit startet.
|
||||
9. Drop items into the Minecart and punch the cart to start it, or 'sneak+click' the Minecart to get the items back.=9: Lege Gegenstände in ein Wagen (Taste Q) und starte dann den Wagen durch Anklicken. Klicke mit gedrückter Shift-Taste auf den Wagen, um Gegenstände wieder auszuladen.
|
||||
A minecart running through unloaded areas, mainly used for item transportation=Ein Wagen, welcher auch durch nicht geladene Kartenbereiche fährt, primär für den Transport von Gegenständen genutzt (Lore)
|
||||
Allow to dig/place rails in Minecart Landmark areas=Erlaubt dir, Schienen in Meilensteinbereichen zu setzen/zu entfernen
|
||||
Minecart=Minecart
|
||||
Minecart (Sneak+Click to pick up)=Minecart (Shift+Klick zum Entfernen des Carts)
|
||||
Minecart Cart=Wagen
|
||||
Minecart Hopper=Minecart Hopper
|
||||
Minecart Landmark=Minecart Meilenstein
|
||||
Minecart Railway Buffer=Minecart Prellbock
|
||||
Minecart, the lean railway transportation automation system=Minecart, das schlanke Schienentransport Automatisierungssystem
|
||||
Primary used to transport items. You can drop items into the Minecart and punch the cart to get started. Sneak+click the cart to get the items back=Primär für den Transport von Gegenständen genutzt. Du kannst Gegenstände in ein Cart legen (Taste Q) und dann den Wagen durch Anklicken starten. Klicke mit gedrückter Shift-Taste auf den Wagen, um die Gegenstände wieder auszuladen
|
||||
Protect your rails with the Landmarks (one Landmark at least every 16 blocks near the rail)=Schütze deine Schienen mit Hilfe der Meilensteine (ein Meilenstein mindestens alle 16 Blöcke der Strecke entlang)
|
||||
Station name=Stationsname
|
||||
Stop time/sec=Haltezeit/s
|
||||
Summary=Zusammenfassung
|
||||
Used as buffer on both rail ends. Needed to be able to record the cart routes=Preckblöcke müssen an beiden Schienenenden platziert sein, so dass Aufzeichnungen der Strecke gemacht werden können.
|
||||
[minecart] No cart available=[minecart] Kein Wagen verfügbar
|
||||
[minecart] No route stored!=[minecart] Keine Strecke aufgezeichnet!
|
||||
[minecart] One cart at=[minecart] Ein Cart bei
|
||||
Used to load/unload Minecart. The Hopper can push/pull items to/from chests and drop/pickup items to/from Minecarts. To unload a Minecart place the hopper below the rail. To load the Minecart, place the hopper right next to the Minecart.=Um Wagen zu be- und entladen. Der Hopper kann Gegenstände aus Kisten Holen und legen, sowie diese in Wagen fallen lassen bzw. aus Wagen entnehmen. Um einen Wagen zu entladen, muss der Hopper unter die Schiene platziert werden. Um einen Wagen zu beladen, muss der Hopper direkt neben die Schiene platziert werden.
|
||||
[minecart] Area is protected!=[minecart] Bereich ist geschützt!
|
||||
[minecart] Please start at a Railway Buffer!=[minecart] Bitte starte beim Prellbock!
|
||||
[minecart] Recording canceled!=[minecart] Aufzeichnung abgebrochen!
|
||||
[minecart] Route available=[minecart] Strecke verfügbar
|
||||
[minecart] Route stored!=[minecart] Strecke gespeichert
|
||||
[minecart] Start route recording!=[minecart] Starte die Streckenaufzeichnung!
|
||||
velocity=Geschwindigkeit
|
||||
connected to=verbunden mit
|
||||
|
||||
|
|
|
@ -1,27 +1,31 @@
|
|||
1. Place your rails and build a route with two ends. Junctions are allowed as long as each route has its own start and end point.=
|
||||
2. Place a Railway Buffer at both ends.=
|
||||
3. Protect your rails with the Protection Landmarks (one Landmark at least every 16 blocks)=
|
||||
4. Drive the route in both directions (route recording), starting at the Railway Buffers.=
|
||||
5. Now you can drop items into the Minecart and punch the cart to get started.=
|
||||
6. Sneak+click the cart to get the items back=
|
||||
7. Dig the empty cart with a second sneak+Click (as usual).=
|
||||
A minecart running through unloaded areas, mainly used for item transportation=
|
||||
1. Place your rails and build a route with two endpoints. Junctions are allowed as long as each route has its own start and endpoint.=
|
||||
10. Dig the empty cart with a second 'sneak+click' (as usual).=
|
||||
2. Place a Railway Buffer at both endpoints (buffers are always needed, they store the route and timing information).=
|
||||
3. Give both Railway Buffers unique station names, like Oxford and Cambridge.=
|
||||
4. Drive from buffer to buffer in both directions using a Minecart(!) to record the routes (use 'right-left' keys to control the Minecart).=
|
||||
5. Punch the buffers to check the connection data (e.g. 'Oxford: connected to Cambridge').=
|
||||
6. Optional: Configure the Minecart stop time in one or both buffers. The Minecart will then start automatically after the configured time.=
|
||||
7. Optional: Protect your rail network with the Protection Landmarks (one Landmark at least every 16 nodes/meters).=
|
||||
8. Place a Minecart in front of the buffer and check whether it starts after the configured time.=
|
||||
9. Drop items into the Minecart and punch the cart to start it, or 'sneak+click' the Minecart to get the items back.=
|
||||
Allow to dig/place rails in Minecart Landmark areas=
|
||||
Minecart=
|
||||
Minecart (Sneak+Click to pick up)=
|
||||
Minecart Cart=
|
||||
Minecart Hopper=
|
||||
Minecart Landmark=
|
||||
Minecart Railway Buffer=
|
||||
Minecart, the lean railway transportation automation system=
|
||||
Primary used to transport items. You can drop items into the Minecart and punch the cart to get started. Sneak+click the cart to get the items back=
|
||||
Protect your rails with the Landmarks (one Landmark at least every 16 blocks near the rail)=
|
||||
Station name=
|
||||
Stop time/sec=
|
||||
Summary=
|
||||
Used as buffer on both rail ends. Needed to be able to record the cart routes=
|
||||
[minecart] No cart available=
|
||||
[minecart] No route stored!=
|
||||
[minecart] One cart at=
|
||||
Used to load/unload Minecart. The Hopper can push/pull items to/from chests and drop/pickup items to/from Minecarts. To unload a Minecart place the hopper below the rail. To load the Minecart, place the hopper right next to the Minecart.=
|
||||
[minecart] Area is protected!=
|
||||
[minecart] Please start at a Railway Buffer!=
|
||||
[minecart] Recording canceled!=
|
||||
[minecart] Route available=
|
||||
[minecart] Route stored!=
|
||||
[minecart] Start route recording!=
|
||||
velocity=
|
||||
connected to=
|
3
mod.conf
3
mod.conf
|
@ -1,3 +1,4 @@
|
|||
name=minecart
|
||||
depends = default,carts
|
||||
description = A minecart running through unloaded areas
|
||||
optional_depends = doc
|
||||
description = Minecart, the lean railway transportation automation system
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
local S = minecart.S
|
||||
local RANGE = 8
|
||||
|
||||
|
@ -73,7 +85,7 @@ minetest.register_node("minecart:landmark", {
|
|||
return true
|
||||
end
|
||||
minetest.chat_send_player(digger:get_player_name(),
|
||||
S("[minecart] Area is protected! (owner: "..meta:get_string("owner")..")"))
|
||||
S("[minecart] Area is protected!").." (owner: "..meta:get_string("owner")..")")
|
||||
return false
|
||||
end,
|
||||
|
||||
|
|
19
routes.lua
19
routes.lua
|
@ -1,4 +1,19 @@
|
|||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local S = minecart.S
|
||||
|
||||
local CartsOnRail = minecart.CartsOnRail
|
||||
|
@ -74,7 +89,9 @@ end
|
|||
function minecart.set_junction(self, pos, dir, switch_keys)
|
||||
local junctions = CartsOnRail[self.myID] and CartsOnRail[self.myID].junctions
|
||||
if junctions then
|
||||
self.junctions[minetest.pos_to_string(vector.round(pos))] = {dir, switch_keys}
|
||||
if self.junctions then
|
||||
self.junctions[minetest.pos_to_string(vector.round(pos))] = {dir, switch_keys}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# If enabled, allows the complete automation of Minecarts by means of Hopper and station stop times.
|
||||
minecart_hopper_enabled (Hopper enabled) bool true
|
19
storage.lua
19
storage.lua
|
@ -1,4 +1,21 @@
|
|||
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
--[[
|
||||
|
||||
Minecart
|
||||
========
|
||||
|
||||
Copyright (C) 2019-2020 Joachim Stolberg
|
||||
|
||||
MIT
|
||||
See license.txt for more information
|
||||
|
||||
]]--
|
||||
|
||||
-- for lazy programmers
|
||||
local M = minetest.get_meta
|
||||
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||
local S2P = minetest.string_to_pos
|
||||
local S = minecart.S
|
||||
|
||||
local DAYS_VALID = (30 * 72) -- 30 real days
|
||||
|
||||
local storage = minetest.get_mod_storage()
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 159 B |
Binary file not shown.
After Width: | Height: | Size: 169 B |
Binary file not shown.
After Width: | Height: | Size: 203 B |
|
@ -0,0 +1,16 @@
|
|||
import os, fnmatch
|
||||
|
||||
|
||||
print ">>> Convert"
|
||||
for filename in os.listdir("./"):
|
||||
if fnmatch.fnmatch(filename, "*.png"):
|
||||
print(filename)
|
||||
os.system("pngquant --skip-if-larger --quality=8-32 --output ./%s.new ./%s" % (filename, filename))
|
||||
|
||||
print "\n>>> Copy"
|
||||
for filename in os.listdir("./"):
|
||||
if fnmatch.fnmatch(filename, "*.new"):
|
||||
print(filename)
|
||||
os.remove("./" + filename[:-4])
|
||||
os.rename("./" + filename, "./" + filename[:-4])
|
||||
|
Loading…
Reference in New Issue