456 lines
13 KiB
Lua
456 lines
13 KiB
Lua
--[[
|
|
|
|
Autobahn
|
|
|
|
Copyright (C) 2017-2021 Joachim Stolberg
|
|
GPL v3
|
|
See LICENSE.txt for more information
|
|
|
|
History:
|
|
2017-11-11 v0.01 first version
|
|
2019-09-13 v0.02 adapted to 5.0.0
|
|
2020-03-19 v0.03 recipe added for techage bitumen
|
|
2020-07-02 v0.04 further slope nodes added
|
|
|
|
]]--
|
|
local S = minetest.get_translator("autobahn")
|
|
local mod_player_monoids = minetest.get_modpath("player_monoids")
|
|
|
|
autobahn = {}
|
|
|
|
-- Test for MT 5.4 new string mode
|
|
autobahn.CLIP = minetest.features.use_texture_alpha_string_modes and "clip" or true
|
|
|
|
local Facedir2Dir = {[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},
|
|
}
|
|
|
|
-- To prevent race condition crashes
|
|
local Currently_left_the_game = {}
|
|
|
|
local function is_active(player)
|
|
local pl_meta = player:get_meta()
|
|
if not pl_meta or pl_meta:get_int("autobahn_isactive") ~= 1 then
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
local function set_player_privs(player)
|
|
local meta = player:get_meta()
|
|
-- Check access conflicts with other mods
|
|
if meta:get_int("player_physics_locked") == 0 then
|
|
meta:set_int("player_physics_locked", 1)
|
|
if mod_player_monoids then
|
|
player_monoids.speed:add_change(player, 3.5, "autobahn:speed")
|
|
else
|
|
local physics = player:get_physics_override()
|
|
-- store the player privs default values
|
|
meta:set_float("autobahn_speed", physics.speed)
|
|
physics.speed = 3.5
|
|
-- write back
|
|
player:set_physics_override(physics)
|
|
end
|
|
-- set operator privs
|
|
meta:set_int("autobahn_isactive", 1)
|
|
minetest.sound_play("autobahn_motor", {
|
|
pos = player:get_pos(),
|
|
gain = 0.5,
|
|
max_hear_distance = 5,
|
|
})
|
|
end
|
|
end
|
|
|
|
local function reset_player_privs(player)
|
|
local meta = player:get_meta()
|
|
-- restore the player privs default values
|
|
meta:set_int("autobahn_isactive", 0)
|
|
if mod_player_monoids then
|
|
player_monoids.speed:del_change(player, "autobahn:speed")
|
|
else
|
|
local physics = player:get_physics_override()
|
|
physics.speed = meta:get_float("autobahn_speed")
|
|
if physics.speed == 0 then physics.speed = 1 end
|
|
-- delete stored default values
|
|
meta:set_string("autobahn_speed", "")
|
|
-- write back
|
|
player:set_physics_override(physics)
|
|
end
|
|
meta:set_int("player_physics_locked", 0)
|
|
end
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
if is_active(player) then
|
|
reset_player_privs(player)
|
|
end
|
|
end)
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
if is_active(player) then
|
|
Currently_left_the_game[player:get_player_name()] = true
|
|
end
|
|
end)
|
|
|
|
minetest.register_on_respawnplayer(function(player)
|
|
if is_active(player) then
|
|
reset_player_privs(player)
|
|
end
|
|
end)
|
|
|
|
local function control_player(player_name)
|
|
if Currently_left_the_game[player_name] then
|
|
Currently_left_the_game[player_name] = nil
|
|
return
|
|
end
|
|
local player = minetest.get_player_by_name(player_name)
|
|
if player then
|
|
local pos = player:get_pos()
|
|
if pos then
|
|
pos.y = math.floor(pos.y)
|
|
local node = minetest.get_node(pos)
|
|
if string.sub(node.name,1,13) == "autobahn:node" then
|
|
minetest.after(0.5, control_player, player_name)
|
|
else
|
|
pos.y = pos.y - 1
|
|
node = minetest.get_node(pos)
|
|
if string.sub(node.name,1,13) == "autobahn:node" then
|
|
minetest.after(0.5, control_player, player_name)
|
|
else
|
|
pos.y = pos.y + 2
|
|
node = minetest.get_node(pos)
|
|
if string.sub(node.name,1,13) == "autobahn:node" then
|
|
minetest.after(0.5, control_player, player_name)
|
|
else
|
|
reset_player_privs(player)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local NodeTbl1 = {
|
|
["autobahn:node1"] = true,
|
|
["autobahn:node2"] = true,
|
|
["autobahn:node3"] = true,
|
|
["autobahn:node4"] = true,
|
|
["autobahn:node5"] = true,
|
|
["autobahn:node6"] = true,
|
|
["autobahn:node12"] = true,
|
|
["autobahn:node22"] = true,
|
|
["autobahn:node32"] = true,
|
|
["autobahn:node42"] = true,
|
|
["autobahn:node52"] = true,
|
|
["autobahn:node62"] = true,
|
|
}
|
|
local NodeTbl2 = {
|
|
["autobahn:node11"] = true,
|
|
["autobahn:node21"] = true,
|
|
["autobahn:node31"] = true,
|
|
["autobahn:node41"] = true,
|
|
["autobahn:node51"] = true,
|
|
["autobahn:node61"] = true,
|
|
}
|
|
local NodeTbl3 = {
|
|
["autobahn:node1"] = true,
|
|
["autobahn:node2"] = true,
|
|
["autobahn:node3"] = true,
|
|
["autobahn:node4"] = true,
|
|
["autobahn:node5"] = true,
|
|
["autobahn:node6"] = true,
|
|
}
|
|
|
|
-- 1) _o_
|
|
-- /\ [?] ==> 1
|
|
-- [T][T][S][S][S] T..tar
|
|
-- [S][S][S][S][S] S..sand
|
|
--
|
|
--
|
|
-- 2) _o_
|
|
-- /\ [1][?] ==> 2
|
|
-- [T][T][S][S][S]
|
|
-- [S][S][S][S][S]
|
|
--
|
|
--
|
|
-- 3) _o_
|
|
-- /\ [?] ==> 1
|
|
-- [S][S][S][T][T]
|
|
-- [S][S][S][S][S]
|
|
--
|
|
--
|
|
-- 4) _o_
|
|
-- /\ [?][1] ==> 2
|
|
-- [S][S][S][T][T]
|
|
-- [S][S][S][S][S]
|
|
|
|
local function update_node(pos)
|
|
local node = minetest.get_node(pos)
|
|
local nnode
|
|
local npos
|
|
-- check case 1
|
|
local facedir = (2 + node.param2) % 4
|
|
npos = vector.add(pos, Facedir2Dir[facedir])
|
|
npos.y = npos.y - 1
|
|
nnode = minetest.get_node(npos)
|
|
if NodeTbl1[nnode.name] and NodeTbl3[node.name] then
|
|
node.name = node.name .. "1"
|
|
if minetest.registered_nodes[node.name] then
|
|
minetest.swap_node(pos, node)
|
|
end
|
|
return
|
|
end
|
|
-- check case 2
|
|
npos.y = npos.y + 1
|
|
nnode = minetest.get_node(npos)
|
|
if NodeTbl2[nnode.name] then
|
|
node.name = string.sub(node.name,1,-1) .. "2"
|
|
if minetest.registered_nodes[node.name] then
|
|
minetest.swap_node(pos, node)
|
|
end
|
|
return
|
|
end
|
|
-- check case 3
|
|
facedir = (0 + node.param2) % 4
|
|
npos = vector.add(pos, Facedir2Dir[facedir])
|
|
npos.y = npos.y - 1
|
|
nnode = minetest.get_node(npos)
|
|
if NodeTbl1[nnode.name] and NodeTbl3[node.name] then
|
|
node.name = node.name .. "1"
|
|
node.param2 = 3
|
|
if minetest.registered_nodes[node.name] then
|
|
minetest.swap_node(pos, node)
|
|
end
|
|
return
|
|
end
|
|
-- check case 4
|
|
npos.y = npos.y + 1
|
|
nnode = minetest.get_node(npos)
|
|
if NodeTbl2[nnode.name] then
|
|
node.name = string.sub(node.name,1,-1) .. "2"
|
|
node.param2 = 3
|
|
if minetest.registered_nodes[node.name] then
|
|
minetest.swap_node(pos, node)
|
|
end
|
|
return
|
|
end
|
|
end
|
|
|
|
|
|
local function register_node(name, tiles, drawtype, mesh, box, drop)
|
|
minetest.register_node("autobahn:"..name, {
|
|
description = S("Autobahn"),
|
|
tiles = tiles,
|
|
drawtype = drawtype,
|
|
mesh = mesh,
|
|
selection_box = box,
|
|
collision_box = box,
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
sunlight_propagates = true,
|
|
use_texture_alpha = autobahn.CLIP,
|
|
sounds = default.node_sound_stone_defaults(),
|
|
is_ground_content = false,
|
|
groups = {cracky=2, crumbly=2,
|
|
fall_damage_add_percent = -80,
|
|
not_in_creative_inventory=(mesh==nil) and 0 or 1},
|
|
drop = "autobahn:"..drop,
|
|
|
|
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
|
update_node(pos)
|
|
end,
|
|
|
|
on_rightclick = function(pos, node, clicker)
|
|
if is_active(clicker) then
|
|
reset_player_privs(clicker)
|
|
else
|
|
set_player_privs(clicker)
|
|
local player_name = clicker:get_player_name()
|
|
minetest.after(0.5, control_player, player_name)
|
|
end
|
|
end,
|
|
})
|
|
end
|
|
|
|
local sb1 = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, -0.375, 0.5},
|
|
{-0.5, -0.375, -0.25, 0.5, -0.25, 0.5},
|
|
{-0.5, -0.25, 0, 0.5, -0.125, 0.5},
|
|
{-0.5, -0.125, 0.25, 0.5, 0, 0.5},
|
|
}
|
|
}
|
|
local sb2 = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 0.125, 0.5},
|
|
{-0.5, 0.125, -0.25, 0.5, 0.25, 0.5},
|
|
{-0.5, 0.25, 0, 0.5, 0.375, 0.5},
|
|
{-0.5, 0.375, 0.25, 0.5, 0.5, 0.5},
|
|
}
|
|
}
|
|
|
|
local Nodes = {
|
|
{name="node1", tiles={"autobahn1.png"}, drawtype="normal", mesh=nil, box=nil, drop="node1"},
|
|
{name="node2", tiles={"autobahn2.png","autobahn1.png"}, drawtype="normal", mesh=nil, box=nil, drop="node2"},
|
|
{name="node3", tiles={"autobahn3.png","autobahn1.png"}, drawtype="normal", mesh=nil, box=nil, drop="node3"},
|
|
{name="node4", tiles={"autobahn2.png^[transformR180]","autobahn1.png"}, drawtype="normal", mesh=nil, box=nil, drop="node4"},
|
|
{name="node5", tiles={"autobahn4.png^[transformR90]","autobahn1.png"}, drawtype="normal", mesh=nil, box=nil, drop="node5"},
|
|
{name="node6", tiles={"autobahn5.png^[transformR90]","autobahn1.png"}, drawtype="normal", mesh=nil, box=nil, drop="node6"},
|
|
|
|
{name="node11", tiles={"autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node1"},
|
|
{name="node21", tiles={"autobahn2.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node2"},
|
|
{name="node31", tiles={"autobahn3.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node3"},
|
|
{name="node41", tiles={"autobahn2.png^[transformR180]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node4"},
|
|
{name="node51", tiles={"autobahn4.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node5"},
|
|
{name="node61", tiles={"autobahn5.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp1.obj", box=sb1, drop="node6"},
|
|
|
|
{name="node12", tiles={"autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node1"},
|
|
{name="node22", tiles={"autobahn2.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node2"},
|
|
{name="node32", tiles={"autobahn3.png","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node3"},
|
|
{name="node42", tiles={"autobahn2.png^[transformR180]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node4"},
|
|
{name="node52", tiles={"autobahn4.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node5"},
|
|
{name="node62", tiles={"autobahn5.png^[transformR90]","autobahn1.png"}, drawtype="mesh", mesh="autobahn_ramp2.obj", box=sb2, drop="node6"},
|
|
}
|
|
|
|
for _,item in ipairs(Nodes) do
|
|
register_node(item.name, item.tiles, item.drawtype, item.mesh, item.box, item.drop)
|
|
end
|
|
|
|
|
|
minetest.register_craftitem("autobahn:stripes", {
|
|
description = S("Autobahn Stripe"),
|
|
inventory_image = 'autobahn_stripes.png',
|
|
})
|
|
|
|
|
|
if minetest.global_exists("techage") then
|
|
minetest.register_craft({
|
|
output = "autobahn:node1 12",
|
|
recipe = {
|
|
{"techage:sieved_basalt_gravel", "techage:sieved_basalt_gravel", "techage:sieved_basalt_gravel"},
|
|
{"techage:sieved_basalt_gravel", "techage:ta3_barrel_bitumen", "techage:sieved_basalt_gravel"},
|
|
{"techage:sieved_basalt_gravel", "techage:sieved_basalt_gravel", "techage:sieved_basalt_gravel"},
|
|
},
|
|
replacements = {{"techage:ta3_barrel_bitumen", "techage:ta3_barrel_empty"}},
|
|
})
|
|
minetest.register_craft({
|
|
output = "autobahn:node1 12",
|
|
recipe = {
|
|
{"techage:sieved_gravel", "techage:sieved_gravel", "techage:sieved_gravel"},
|
|
{"techage:sieved_gravel", "techage:ta3_barrel_bitumen", "techage:sieved_gravel"},
|
|
{"techage:sieved_gravel", "techage:sieved_gravel", "techage:sieved_gravel"},
|
|
},
|
|
replacements = {{"techage:ta3_barrel_bitumen", "techage:ta3_barrel_empty"}},
|
|
})
|
|
elseif minetest.global_exists("moreblocks") then
|
|
minetest.register_craft({
|
|
output = "autobahn:node1 4",
|
|
recipe = {
|
|
{"moreblocks:tar", "moreblocks:tar"},
|
|
{"default:cobble", "default:cobble"},
|
|
},
|
|
})
|
|
else
|
|
minetest.register_craft({
|
|
output = "autobahn:node1 4",
|
|
recipe = {
|
|
{"autobahn:tar", "autobahn:tar"},
|
|
{"default:cobble", "default:cobble"},
|
|
},
|
|
})
|
|
minetest.register_craft({
|
|
type = "cooking",
|
|
output = "autobahn:tar",
|
|
recipe = "default:pine_tree",
|
|
})
|
|
minetest.register_node("autobahn:tar", {
|
|
description = S("Tar"),
|
|
tiles = {"autobahn1.png^[colorize:#000000:80"},
|
|
is_ground_content = false,
|
|
groups = {cracky = 2},
|
|
sounds = default.node_sound_stone_defaults(),
|
|
})
|
|
end
|
|
|
|
minetest.register_craft({
|
|
output = "autobahn:stripes 8",
|
|
recipe = {
|
|
{"dye:white"},
|
|
}
|
|
})
|
|
|
|
|
|
minetest.register_craft({
|
|
output = "autobahn:node2",
|
|
recipe = {
|
|
{"", "", "autobahn:stripes"},
|
|
{"", "autobahn:node1", ""},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "autobahn:node3",
|
|
recipe = {
|
|
{"", "autobahn:stripes", ""},
|
|
{"", "autobahn:node1", ""},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "autobahn:node4",
|
|
recipe = {
|
|
{"autobahn:stripes", "", ""},
|
|
{"", "autobahn:node1", ""},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "autobahn:node5",
|
|
recipe = {
|
|
{"", "", ""},
|
|
{"autobahn:stripes", "autobahn:node1", ""},
|
|
}
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "autobahn:node6",
|
|
recipe = {
|
|
{"", "autobahn:stripes", ""},
|
|
{"autobahn:stripes", "autobahn:node1", ""},
|
|
}
|
|
})
|
|
|
|
if minetest.global_exists("minecart") then
|
|
minecart.register_protected_node("autobahn:node1")
|
|
minecart.register_protected_node("autobahn:node2")
|
|
minecart.register_protected_node("autobahn:node3")
|
|
minecart.register_protected_node("autobahn:node4")
|
|
minecart.register_protected_node("autobahn:node5")
|
|
minecart.register_protected_node("autobahn:node6")
|
|
minecart.register_protected_node("autobahn:node11")
|
|
minecart.register_protected_node("autobahn:node21")
|
|
minecart.register_protected_node("autobahn:node31")
|
|
minecart.register_protected_node("autobahn:node41")
|
|
minecart.register_protected_node("autobahn:node51")
|
|
minecart.register_protected_node("autobahn:node61")
|
|
minecart.register_protected_node("autobahn:node12")
|
|
minecart.register_protected_node("autobahn:node22")
|
|
minecart.register_protected_node("autobahn:node32")
|
|
minecart.register_protected_node("autobahn:node42")
|
|
minecart.register_protected_node("autobahn:node52")
|
|
minecart.register_protected_node("autobahn:node62")
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- External API functions
|
|
-------------------------------------------------------------------------------
|
|
|
|
-- Returns true if player is "driving" on the autobahn
|
|
-- func autobahn.is_driving(player)
|
|
autobahn.is_driving = is_active |