new
parent
7aff68370e
commit
34028ced08
|
@ -0,0 +1,13 @@
|
|||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
@ -0,0 +1,2 @@
|
|||
default
|
||||
|
|
@ -0,0 +1 @@
|
|||
Hyperloop Mod for faster traveling.
|
|
@ -0,0 +1,371 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
v0.01 by JoSt
|
||||
|
||||
Copyright (C) 2017 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
History:
|
||||
2017-06-18 v0.01 First version
|
||||
|
||||
]]--
|
||||
|
||||
|
||||
hyperloop = {
|
||||
ringList = {},
|
||||
}
|
||||
|
||||
-- max teleport distance
|
||||
-- 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
|
||||
|
||||
|
||||
local dist = tonumber(minetest.setting_get("map_generation_limit") or 31000)
|
||||
|
||||
|
||||
dofile(minetest.get_modpath("hyperloop") .. "/utils.lua")
|
||||
dofile(minetest.get_modpath("hyperloop") .. "/door.lua")
|
||||
dofile(minetest.get_modpath("hyperloop") .. "/tubes.lua")
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
local function enter_display(pos, text)
|
||||
-- Use LCD from digilines. TODO: Own display
|
||||
local node = minetest.get_node(pos)
|
||||
local spec = digilines.getspec(node)
|
||||
if spec then
|
||||
-- Effector actions --> Receive
|
||||
if spec.effector then
|
||||
spec.effector.action(pos, node, "lcd", text)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
local function check_coordinates(str)
|
||||
-- obsolete?
|
||||
if not str or str == "" then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- get coords from string
|
||||
local x, y, z, desc = string.match(str, "^(-?%d+),(-?%d+),(-?%d+),?(.*)$")
|
||||
|
||||
-- check coords
|
||||
if x == nil or string.len(x) > 6
|
||||
or y == nil or string.len(y) > 6
|
||||
or z == nil or string.len(z) > 6 then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- convert string coords to numbers
|
||||
x = tonumber(x)
|
||||
y = tonumber(y)
|
||||
z = tonumber(z)
|
||||
|
||||
-- are coords in map range ?
|
||||
if x > dist or x < -dist
|
||||
or y > dist or y < -dist
|
||||
or z > dist or z < -dist then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- return ok coords
|
||||
return {x = x, y = y, z = z, desc = desc}
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- seat_pos: position of the seat
|
||||
-- facedir: direction to the display
|
||||
-- cmnd: "close", "open", or "animate"
|
||||
local function door_command(seat_pos, facedir, cmnd)
|
||||
-- one step forward
|
||||
local lcd_pos = vector.add(seat_pos, facedir2dir(facedir))
|
||||
-- one step left
|
||||
local door_pos1 = vector.add(lcd_pos, facedir2dir(facedir + 1))
|
||||
-- one step up
|
||||
local door_pos2 = vector.add(door_pos1, {x=0, y=1, z=0})
|
||||
|
||||
local node1 = minetest.get_node(door_pos1)
|
||||
local node2 = minetest.get_node(door_pos2)
|
||||
|
||||
-- switch from the radian following facedir to the silly original one
|
||||
local tbl = {[0]=0, [1]=3, [2]=2, [3]=1}
|
||||
facedir = (facedir + 3) % 4 -- first turn left
|
||||
facedir = tbl[facedir]
|
||||
|
||||
if cmnd == "open" then
|
||||
node1.name = "air"
|
||||
minetest.swap_node(door_pos1, node1)
|
||||
node2.name = "air"
|
||||
minetest.swap_node(door_pos2, node2)
|
||||
elseif cmnd == "close" then
|
||||
node1.name = "hyperloop:doorBottom"
|
||||
node1.param2 = facedir
|
||||
minetest.swap_node(door_pos1, node1)
|
||||
node2.name = "hyperloop:doorTopPassive"
|
||||
node2.param2 = facedir
|
||||
minetest.swap_node(door_pos2, node2)
|
||||
elseif cmnd == "animate" then
|
||||
node2.name = "hyperloop:doorTopActive"
|
||||
node2.param2 = facedir
|
||||
minetest.swap_node(door_pos2, node2)
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
local function on_open_door(pos, facedir)
|
||||
-- open the door and play sound
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("arrival_time", 0) -- finished
|
||||
|
||||
-- open the door
|
||||
minetest.sound_play("door", {
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 10,
|
||||
})
|
||||
door_command(pos, facedir, "open")
|
||||
|
||||
-- prepare dislay for the next trip
|
||||
local text = "We will start | in a few | seconds"
|
||||
enter_display(lcd_pos, text)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
local function on_arrival(player, src_pos, dst_pos, snd, radiant)
|
||||
-- open the door an the departure station
|
||||
local meta = minetest.get_meta(src_pos)
|
||||
local facedir = meta:get_int("facedir")
|
||||
door_command(src_pos, facedir, "open")
|
||||
|
||||
-- get coords from arrival station
|
||||
meta = minetest.get_meta(dst_pos)
|
||||
facedir = meta:get_int("facedir")
|
||||
--print("on_arrival "..dump(dst_pos))----------------------------------------------
|
||||
|
||||
-- close the door at arrival station
|
||||
door_command(dst_pos, facedir, "close")
|
||||
|
||||
-- move player to the arrival station
|
||||
player:setpos(dst_pos)
|
||||
-- rotate player to look in correct arrival direction
|
||||
-- calculate the look correction
|
||||
local offs = radiant - player:get_look_horizontal()
|
||||
local yaw = facedir2rad(facedir) + offs
|
||||
player:set_look_yaw(yaw)
|
||||
|
||||
-- play arrival sound
|
||||
minetest.sound_stop(snd)
|
||||
minetest.sound_play("down", {
|
||||
pos = dst_pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = 10
|
||||
})
|
||||
-- activate display
|
||||
local lcd_pos = vector.add(dst_pos, facedir2dir(facedir))
|
||||
lcd_pos.y = lcd_pos.y + 1
|
||||
--print("LCD "..dump(pos)..dump(lcd_pos))
|
||||
local text = "Wellcome in | | Hauptstadt"
|
||||
enter_display(lcd_pos, text)
|
||||
|
||||
minetest.after(6.0, on_open_door, dst_pos, facedir)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
local function on_travel(src_pos, facedir, player, dst_pos, radiant)
|
||||
-- play sound and switch door state
|
||||
-- radiant is the player look direction at departure
|
||||
local snd = minetest.sound_play("normal", {
|
||||
pos = src_pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = 1,
|
||||
loop = true,
|
||||
})
|
||||
door_command(src_pos, facedir, "animate")
|
||||
minetest.after(6.0, on_arrival, player, src_pos, dst_pos, snd, radiant)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
local function display_timer(pos, elapsed)
|
||||
-- update display with trip data
|
||||
local meta = minetest.get_meta(pos)
|
||||
local atime = meta:get_int("arrival_time") - 1
|
||||
meta:set_int("arrival_time", atime)
|
||||
local lcd_pos = minetest.string_to_pos(meta:get_string("lcd_pos"))
|
||||
local text = meta:get_string("lcd_text")
|
||||
if atime > 0 then
|
||||
enter_display(lcd_pos, text..atime.." sec")
|
||||
return true
|
||||
else
|
||||
enter_display(lcd_pos, "We will start | in a view | minutes..")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
local function on_start_travel(pos, node, clicker)
|
||||
-- place the player, close the door, activate display
|
||||
local meta = minetest.get_meta(pos)
|
||||
local facedir = meta:get_int("facedir")
|
||||
if meta:get_int("arrival_time") ~= 0 then
|
||||
return
|
||||
end
|
||||
local target_coords = {
|
||||
x = meta:get_int("x"),
|
||||
y = meta:get_int("y"),
|
||||
z = meta:get_int("z")
|
||||
}
|
||||
|
||||
minetest.sound_play("up", {
|
||||
pos = pos,
|
||||
gain = 1.0,
|
||||
max_hear_distance = 10
|
||||
})
|
||||
-- place player on the seat
|
||||
clicker:setpos(pos)
|
||||
-- rotate player to look in move direction
|
||||
clicker:set_look_horizontal(facedir2rad(facedir))
|
||||
|
||||
-- activate display
|
||||
local lcd_pos = vector.add(pos, facedir2dir(facedir))
|
||||
lcd_pos.y = lcd_pos.y + 1
|
||||
--print("LCD "..dump(pos)..dump(lcd_pos))
|
||||
local text = "Next stop: | Hauptstadt | Dist: 2.2km | Arrival in: | "
|
||||
local atime = 15
|
||||
enter_display(lcd_pos, text..atime.." sec")
|
||||
|
||||
-- store some data
|
||||
meta:set_int("arrival_time", atime)
|
||||
meta:set_string("lcd_pos", minetest.pos_to_string(lcd_pos))
|
||||
meta:set_string("lcd_text", text)
|
||||
meta:set_string("lcd_text", text)
|
||||
minetest.get_node_timer(pos):start(1.0)
|
||||
|
||||
--print("on_rightclick "..dump(pos))----------------------------------------------
|
||||
|
||||
-- close the door
|
||||
minetest.sound_play("door", {
|
||||
pos = pos,
|
||||
gain = 0.5,
|
||||
max_hear_distance = 10,
|
||||
})
|
||||
door_command(pos, facedir, "close")
|
||||
|
||||
minetest.after(4.9, on_travel, pos, facedir, clicker, target_coords, facedir2rad(facedir))
|
||||
end
|
||||
|
||||
-- Hyperloop Seat
|
||||
minetest.register_node("hyperloop:seat", {
|
||||
tiles = {
|
||||
"seat-top.png",
|
||||
"seat-side.png",
|
||||
"seat-side.png",
|
||||
"seat-side.png",
|
||||
"seat-side.png",
|
||||
"seat-side.png",
|
||||
},
|
||||
drawtype = "nodebox",
|
||||
paramtype2 = "facedir",
|
||||
is_ground_content = false,
|
||||
walkable = false,
|
||||
--description = S("Hyperloop Pad (place and right-click to enchant location)"),
|
||||
groups = {snappy = 3},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{ -6/16, -8/16, -8/16, 6/16, -2/16, 5/16},
|
||||
{ -8/16, -8/16, -8/16, -6/16, 4/16, 8/16},
|
||||
{ 6/16, -8/16, -8/16, 8/16, 4/16, 8/16},
|
||||
{ -6/16, -8/16, 4/16, 6/16, 6/16, 8/16},
|
||||
},
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -8/16, -8/16, -8/16, 8/16, -2/16, 8/16 },
|
||||
},
|
||||
|
||||
on_timer = display_timer,
|
||||
|
||||
on_construct = function(pos)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
-- text entry formspec
|
||||
meta:set_string("formspec", "field[text;" .. S("Enter teleport coords (e.g. 200,20,-200,Home)") .. ";${text}]")
|
||||
meta:set_string("infotext", S("Right-click to enchant teleport location"))
|
||||
meta:set_string("text", pos.x .. "," .. pos.y .. "," .. pos.z)
|
||||
meta:set_int("arrival_time", 0)
|
||||
|
||||
-- set default coords
|
||||
meta:set_int("x", pos.x)
|
||||
meta:set_int("y", pos.y)
|
||||
meta:set_int("z", pos.z)
|
||||
end,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local yaw = placer:get_look_horizontal()
|
||||
-- facedir according to radiant
|
||||
local facedir = rad2facedir(yaw)
|
||||
-- do a 180 degree correction
|
||||
meta:set_int("facedir", (facedir + 2) % 4)
|
||||
print("on_construct "..dump(pos))----------------------------------------------
|
||||
end,
|
||||
|
||||
-- once entered, check coords, if ok then return potion
|
||||
on_receive_fields = function(pos, formname, fields, sender)
|
||||
|
||||
local name = sender:get_player_name()
|
||||
|
||||
if minetest.is_protected(pos, name) then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
return
|
||||
end
|
||||
|
||||
local coords = check_coordinates(fields.text)
|
||||
|
||||
if coords then
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
print("on_receive_fields "..dump(pos))----------------------------------------------
|
||||
|
||||
meta:set_int("x", coords.x)
|
||||
meta:set_int("y", coords.y)
|
||||
meta:set_int("z", coords.z)
|
||||
meta:set_string("text", fields.text)
|
||||
|
||||
if coords.desc and coords.desc ~= "" then
|
||||
|
||||
meta:set_string("infotext", S("Teleport to @1", coords.desc))
|
||||
else
|
||||
meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
|
||||
coords.x, coords.y, coords.z))
|
||||
end
|
||||
-- delete formspec so that right-click will work
|
||||
meta:set_string("formspec", nil)
|
||||
else
|
||||
minetest.chat_send_player(name, S("Teleport Pad coordinates failed!"))
|
||||
end
|
||||
end,
|
||||
|
||||
on_rightclick = on_start_travel,
|
||||
})
|
||||
|
||||
print ("[MOD] Hyperloop loaded")
|
|
@ -0,0 +1,2 @@
|
|||
# Max distance in blocks between two stations
|
||||
hyperloop_max_distance (Hyperloop max station distance) int 1000
|
|
@ -0,0 +1,84 @@
|
|||
-- We need:
|
||||
-- * tube_power0, can be placed and docked by a tube
|
||||
-- * tube_power1, can be docked by a second tube
|
||||
-- * tube_power2, can't be docked by a third tube
|
||||
for idx = 0,2 do
|
||||
local img
|
||||
if idx < 2 then
|
||||
img = "hyperloop_power_tube_green.png"
|
||||
else
|
||||
img = "hyperloop_power_tube_red.png"
|
||||
end
|
||||
minetest.register_node("hyperloop:tube_power"..idx, {
|
||||
description = "Hyperloop Power Tube",
|
||||
tiles = {
|
||||
{
|
||||
name = img,
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local nodes = scan_tube_neighbours(pos, true, {"hyperloop:tube_head", "hyperloop:tube_power1"})
|
||||
-- power node can't be placed nearby another power node
|
||||
for _,node in ipairs(nodes) do
|
||||
if node.name == "hyperloop:tube_power0" or node.name == "hyperloop:tube_power1" then
|
||||
-- remove node again
|
||||
minetest.chat_send_player(placer:get_player_name(), "Power Tube block can't be placed here.")
|
||||
minetest.remove_node(pos)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local station_name = meta:get_string("station") or "<unknown>"
|
||||
local ring_addr
|
||||
if #nodes == 0 then -- are we the one and only?
|
||||
--print("start ring")----------------------
|
||||
-- a new ring starts here
|
||||
ring_addr = determine_ring_addr(pos)
|
||||
else
|
||||
--print("degrade to tubes")----------------------
|
||||
-- degrade neighbor nodes
|
||||
swap_to_tube(pos, placer, nodes)
|
||||
ring_addr = meta:get_string("ring_addr")
|
||||
|
||||
-- already connected with two tube nodes?
|
||||
if #nodes == 2 then
|
||||
--print("switch to tube_power1")----------------------
|
||||
-- tube_power1 cant be docked by a third tube
|
||||
local node = minetest.get_node(pos)
|
||||
node.name = "hyperloop:tube_power1"
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
meta:set_string("infotext", "Power Tube block "..idx..". ring at: "..ring_addr.." Station Name: "..station_name)
|
||||
-- store ring_addr in ring list
|
||||
if hyperloop.ringList[ring_addr] ~= nil then
|
||||
table.insert(hyperloop.ringList[ring_addr], pos)
|
||||
else
|
||||
hyperloop.ringList[ring_addr] = {pos}
|
||||
end
|
||||
--print("store ring_addr in ring list")-------------------------------------
|
||||
--hyperloop.dbg_ringlist()------------------------------------------
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
local nodes = scan_tube_neighbours(pos, true, {"hyperloop:tube"})
|
||||
-- upgrade neighbor nodes
|
||||
swap_to_tube_head(pos, nodes)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, not_in_creative_inventory=idx},
|
||||
is_ground_content = false,
|
||||
drop = "hyperloop:tube_power0",
|
||||
})
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
History:
|
||||
see init.lua
|
||||
|
||||
]]--
|
||||
|
||||
local function scan_neighbours(pos)
|
||||
-- Scan all 8 neighbor positions for tube nodes.
|
||||
-- Return:
|
||||
-- 0, nodes - no node available
|
||||
-- 1, nodes - one tube1 available
|
||||
-- 3, nodes - two tube1 available
|
||||
-- 4, nodes - invalid position
|
||||
local nodes = {}
|
||||
local node, npos, idx
|
||||
local res = 0
|
||||
for _,dir in ipairs(hyperloop.NeighborPos) do
|
||||
npos = vector.add(pos, dir)
|
||||
node = minetest.get_node(npos)
|
||||
if string.find(node.name, "hyperloop:tube") then
|
||||
idx = string.byte(node.name, -1) - 48
|
||||
if idx == 0 then -- starter tube node?
|
||||
idx = 1
|
||||
elseif
|
||||
idx == 2 then -- normal tube node
|
||||
return 4, nodes
|
||||
end
|
||||
res = res * 2 + idx
|
||||
if res > 3 then
|
||||
return 4, nodes
|
||||
end
|
||||
node.pos = npos
|
||||
table.insert(nodes, node)
|
||||
end
|
||||
end
|
||||
return res, nodes
|
||||
end
|
||||
|
||||
local function degrade_tupe_node(node)
|
||||
if node.name == "hyperloop:tube0" then
|
||||
node.name = "hyperloop:tube1"
|
||||
elseif node.name == "hyperloop:tube1" then
|
||||
node.name = "hyperloop:tube2"
|
||||
node.diggable = false
|
||||
else
|
||||
return
|
||||
end
|
||||
minetest.swap_node(node.pos, node)
|
||||
end
|
||||
|
||||
local function upgrade_node(pos, node)
|
||||
-- Upgrade one node.
|
||||
-- Is needed when a tube node is digged.
|
||||
local meta_local = minetest.get_meta(pos)
|
||||
local meta_head = minetest.get_meta(node.pos)
|
||||
meta_head:set_string("other", meta_local:get_string("other"))
|
||||
meta_head:set_string("me", minetest.pos_to_string(node.pos))
|
||||
node.diggable = true
|
||||
if node.name == "hyperloop:tube2" then -- 2 connections?
|
||||
node.name = "hyperloop:tube1"
|
||||
elseif node.name == "hyperloop:tube1" then -- 1 connection?
|
||||
node.name = "hyperloop:tube0"
|
||||
end
|
||||
minetest.swap_node(node.pos, node)
|
||||
end
|
||||
|
||||
local function starter_node(node)
|
||||
local meta = minetest.get_meta(node.pos)
|
||||
meta:set_string("local", minetest.pos_to_string(node.pos))
|
||||
meta:set_string("remote", minetest.pos_to_string(node.pos))
|
||||
-- upgrade self to starter node
|
||||
node.name = "hyperloop:tube0"
|
||||
minetest.swap_node(node.pos, node)
|
||||
end
|
||||
|
||||
local function head_node(node, node1)
|
||||
local meta_local = minetest.get_meta(node.pos)
|
||||
local meta_head = minetest.get_meta(node1.pos)
|
||||
-- set local data
|
||||
meta_local:set_string("local", minetest.pos_to_string(node.pos))
|
||||
meta_local:set_string("remote", meta_head:get_string("remote"))
|
||||
-- set remote data
|
||||
local rpos = minetest.string_to_pos(meta_head:get_string("remote"))
|
||||
local rmeta = minetest.get_meta(rpos)
|
||||
rmeta:set_string("remote", minetest.pos_to_string(node.pos))
|
||||
-- upgrade self
|
||||
node.name = "hyperloop:tube1"
|
||||
minetest.swap_node(node.pos, node)
|
||||
-- degrade old head
|
||||
degrade_tupe_node(node1)
|
||||
end
|
||||
|
||||
local function link_node(node, node1, node2)
|
||||
-- determine the meta data from both remote heads
|
||||
local meta_head1 = minetest.get_meta(node1.pos)
|
||||
local meta_head2 = minetest.get_meta(node2.pos)
|
||||
local pos1 = minetest.string_to_pos(meta_head1:get_string("remote"))
|
||||
local pos2 = minetest.string_to_pos(meta_head2:get_string("remote"))
|
||||
local meta_rmt1 = minetest.get_meta(pos1)
|
||||
local meta_rmt2 = minetest.get_meta(pos2)
|
||||
-- exchange position data
|
||||
meta_rmt2:set_string("remote", meta_rmt1:get_string("local"))
|
||||
meta_rmt1:set_string("remote", meta_rmt2:get_string("local"))
|
||||
-- degrade all three nodes
|
||||
degrade_tupe_node(node)
|
||||
degrade_tupe_node(node1)
|
||||
degrade_tupe_node(node2)
|
||||
end
|
||||
|
||||
local function remove_node(pos, node)
|
||||
---minetest.remove_node(pos) can't call because "on_destruct" will then be called, too
|
||||
node.name = "air"
|
||||
node.diggable = true
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
|
||||
-- simple tube without logic or "memory"
|
||||
minetest.register_node("hyperloop:tube2", {
|
||||
description = "Hyperloop Tube",
|
||||
tiles = {
|
||||
{
|
||||
name = "hyperloop_tube_red.png",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
diggable = false,
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=1, not_in_creative_inventory=1},
|
||||
is_ground_content = false,
|
||||
})
|
||||
|
||||
-- single-node and head-node with meta info about the counter part node
|
||||
for idx = 0,1 do
|
||||
minetest.register_node("hyperloop:tube"..idx, {
|
||||
description = "Hyperloop Tube",
|
||||
tiles = {
|
||||
{
|
||||
name = "hyperloop_tube_green.png",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 32,
|
||||
aspect_h = 32,
|
||||
length = 2.0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||
local res, nodes = scan_neighbours(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
node.pos = pos
|
||||
hyperloop.dbg_nodes(nodes)-------------------------------------
|
||||
if res == 0 then -- no neighbor available?
|
||||
starter_node(node)
|
||||
elseif res == 1 then -- one neighbor available?
|
||||
head_node(node, nodes[1])
|
||||
elseif res == 3 then -- two neighbours available?
|
||||
link_node(node, nodes[1], nodes[2])
|
||||
else -- invalid position
|
||||
minetest.chat_send_player(placer:get_player_name(), "Invalid tube block position")
|
||||
remove_node(pos, node)
|
||||
end
|
||||
end,
|
||||
|
||||
on_destruct = function(pos)
|
||||
print("on_destruct")------------------------------
|
||||
local res, nodes = scan_neighbours(pos)
|
||||
if res == 1 then
|
||||
upgrade_node(pos, nodes[1])
|
||||
end
|
||||
end,
|
||||
|
||||
on_punch = function(pos, node, puncher, pointed_thing)
|
||||
local meta = minetest.get_meta(pos)
|
||||
loc = meta:get_string("local")
|
||||
rmt = meta:get_string("remote")
|
||||
minetest.chat_send_player(puncher:get_player_name(), "local="..loc.." remote="..rmt)
|
||||
end,
|
||||
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, not_in_creative_inventory=idx},
|
||||
is_ground_content = false,
|
||||
drop = "hyperloop:tube0",
|
||||
})
|
||||
end
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
--[[
|
||||
|
||||
Hyperloop Mod
|
||||
=============
|
||||
|
||||
Copyright (C) 2017 Joachim Stolberg
|
||||
|
||||
LGPLv2.1+
|
||||
See LICENSE.txt for more information
|
||||
|
||||
History:
|
||||
see init.lua
|
||||
|
||||
]]--
|
||||
|
||||
local PI = 3.1415926
|
||||
|
||||
hyperloop.NeighborPos = {
|
||||
{ x=1, y=0, z=0},
|
||||
{ x=-1, y=0, z=0},
|
||||
{ x=0, y=1, z=0},
|
||||
{ x=0, y=-1, z=0},
|
||||
{ x=0, y=0, z=1},
|
||||
{ x=0, y=0, z=-1},
|
||||
}
|
||||
|
||||
function hyperloop.rad2facedir(yaw)
|
||||
-- radiant (0..2*PI) to my facedir (0..3) from N, W, S to E
|
||||
return math.floor((yaw + PI/4) / PI * 2) % 4
|
||||
end
|
||||
|
||||
function hyperloop.facedir2rad(facedir)
|
||||
-- my facedir (0..3) from N, W, S to E to radiant (0..2*PI)
|
||||
return facedir / 2 * PI
|
||||
end
|
||||
|
||||
function hyperloop.facedir2dir(facedir)
|
||||
-- my facedir (0..3) from N, W, S to E to dir vector
|
||||
local tbl = {
|
||||
[0] = { x=0, y=0, z=1},
|
||||
[1] = { x=-1, y=0, z=0},
|
||||
[2] = { x=0, y=0, z=-1},
|
||||
[3] = { x=1, y=0, z=0},
|
||||
}
|
||||
return tbl[facedir % 4]
|
||||
end
|
||||
|
||||
function hyperloop.turnright(dir)
|
||||
local facedir = minetest.dir_to_facedir(dir)
|
||||
return minetest.facedir_to_dir((facedir + 1) % 4)
|
||||
end
|
||||
|
||||
function hyperloop.turnleft(dir)
|
||||
local facedir = minetest.dir_to_facedir(dir)
|
||||
return minetest.facedir_to_dir((facedir + 3) % 4)
|
||||
end
|
||||
|
||||
-- File writing / reading utilities
|
||||
local wpath = minetest.get_worldpath()
|
||||
|
||||
function hyperloop.file2table(filename)
|
||||
local f = io.open(wpath..DIR_DELIM..filename, "r")
|
||||
if f == nil then return {} end
|
||||
local t = f:read("*all")
|
||||
f:close()
|
||||
if t == "" or t == nil then return {} end
|
||||
return minetest.deserialize(t)
|
||||
end
|
||||
|
||||
function hyperloop.table2file(filename, table)
|
||||
local f = io.open(wpath..DIR_DELIM..filename, "w")
|
||||
f:write(minetest.serialize(table))
|
||||
f:close()
|
||||
end
|
||||
|
||||
function hyperloop.store_ring_list()
|
||||
hyperloop.table2file("hyperloop_ringlist", hyperloop.ringList)
|
||||
end
|
||||
|
||||
|
||||
function hyperloop.dbg_ringlist()
|
||||
print("RingList:")
|
||||
print(dump(hyperloop.ringList))-------------------------------------------
|
||||
for addr,list in ipairs(hyperloop.ringList) do
|
||||
for idx, pos in ipairs(list) do
|
||||
print("addr:"..addr.." idx:"..idx.." pos:"..minetest.pos_to_string(pos))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function hyperloop.dbg_nodes(nodes)
|
||||
print("Nodes:")
|
||||
for _,node in ipairs(nodes) do
|
||||
print("name:"..node.name)
|
||||
end
|
||||
end
|
||||
|
||||
-- Store and read the RingList to / from a file
|
||||
-- so that upcoming actions are remembered when the game
|
||||
-- is restarted
|
||||
hyperloop.ringList = hyperloop.file2table("hyperloop_ringlist")
|
||||
|
||||
minetest.register_on_shutdown(hyperloop.store_ring_list)
|
||||
|
||||
-- store ring list once a day
|
||||
minetest.after(60*60*24, hyperloop.store_ring_list)
|
||||
|
Loading…
Reference in New Issue