Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 294 B |
|
@ -1,24 +0,0 @@
|
||||||
Minetest mod: boost_cart
|
|
||||||
=======================
|
|
||||||
Based on (and fully compatible with) the mod "carts" by PilzAdam
|
|
||||||
Target: Run smoothly and do not use too much CPU.
|
|
||||||
Edited by TenPlus1 to drop cart when no-one inside
|
|
||||||
|
|
||||||
License of source code:
|
|
||||||
-----------------------
|
|
||||||
WTFPL
|
|
||||||
|
|
||||||
License of media (textures, sounds and models):
|
|
||||||
-----------------------------------------------
|
|
||||||
CC-0
|
|
||||||
|
|
||||||
Authors of media files:
|
|
||||||
-----------------------
|
|
||||||
kddekadenz:
|
|
||||||
cart_bottom.png
|
|
||||||
cart_side.png
|
|
||||||
cart_top.png
|
|
||||||
|
|
||||||
Zeg9:
|
|
||||||
cart.x
|
|
||||||
cart.png
|
|
|
@ -1,4 +0,0 @@
|
||||||
default
|
|
||||||
mesecons?
|
|
||||||
moreores?
|
|
||||||
mobs?
|
|
|
@ -1,150 +0,0 @@
|
||||||
function boost_cart:get_sign(z)
|
|
||||||
if z == 0 then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return z / math.abs(z)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart:velocity_to_dir(v)
|
|
||||||
if math.abs(v.x) > math.abs(v.z) then
|
|
||||||
return {x=boost_cart:get_sign(v.x), y=boost_cart:get_sign(v.y), z=0}
|
|
||||||
else
|
|
||||||
return {x=0, y=boost_cart:get_sign(v.y), z=boost_cart:get_sign(v.z)}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart:is_rail(pos, railtype)
|
|
||||||
local node = minetest.get_node(pos).name
|
|
||||||
if node == "ignore" then
|
|
||||||
local vm = minetest.get_voxel_manip()
|
|
||||||
local emin, emax = vm:read_from_map(pos, pos)
|
|
||||||
local area = VoxelArea:new{
|
|
||||||
MinEdge = emin,
|
|
||||||
MaxEdge = emax,
|
|
||||||
}
|
|
||||||
local data = vm:get_data()
|
|
||||||
local vi = area:indexp(pos)
|
|
||||||
node = minetest.get_name_from_content_id(data[vi])
|
|
||||||
end
|
|
||||||
if minetest.get_item_group(node, "rail") == 0 then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if not railtype then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return minetest.get_item_group(node, "connect_to_raillike") == railtype
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart:check_front_up_down(pos, dir_, check_down, railtype)
|
|
||||||
local dir = vector.new(dir_)
|
|
||||||
local cur = nil
|
|
||||||
|
|
||||||
-- Front
|
|
||||||
dir.y = 0
|
|
||||||
cur = vector.add(pos, dir)
|
|
||||||
if boost_cart:is_rail(cur, railtype) then
|
|
||||||
return dir
|
|
||||||
end
|
|
||||||
-- Up
|
|
||||||
if check_down then
|
|
||||||
dir.y = 1
|
|
||||||
cur = vector.add(pos, dir)
|
|
||||||
if boost_cart:is_rail(cur, railtype) then
|
|
||||||
return dir
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Down
|
|
||||||
dir.y = -1
|
|
||||||
cur = vector.add(pos, dir)
|
|
||||||
if boost_cart:is_rail(cur, railtype) then
|
|
||||||
return dir
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
|
|
||||||
local pos = vector.round(pos_)
|
|
||||||
local cur = nil
|
|
||||||
local left_check, right_check = true, true
|
|
||||||
|
|
||||||
-- Check left and right
|
|
||||||
local left = {x=0, y=0, z=0}
|
|
||||||
local right = {x=0, y=0, z=0}
|
|
||||||
if dir.z ~= 0 and dir.x == 0 then
|
|
||||||
left.x = -dir.z
|
|
||||||
right.x = dir.z
|
|
||||||
elseif dir.x ~= 0 and dir.z == 0 then
|
|
||||||
left.z = dir.x
|
|
||||||
right.z = -dir.x
|
|
||||||
end
|
|
||||||
|
|
||||||
if ctrl then
|
|
||||||
if old_switch == 1 then
|
|
||||||
left_check = false
|
|
||||||
elseif old_switch == 2 then
|
|
||||||
right_check = false
|
|
||||||
end
|
|
||||||
if ctrl.left and left_check then
|
|
||||||
cur = boost_cart:check_front_up_down(pos, left, false, railtype)
|
|
||||||
if cur then
|
|
||||||
return cur, 1
|
|
||||||
end
|
|
||||||
left_check = false
|
|
||||||
end
|
|
||||||
if ctrl.right and right_check then
|
|
||||||
cur = boost_cart:check_front_up_down(pos, right, false, railtype)
|
|
||||||
if cur then
|
|
||||||
return cur, 2
|
|
||||||
end
|
|
||||||
right_check = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Normal
|
|
||||||
cur = boost_cart:check_front_up_down(pos, dir, true, railtype)
|
|
||||||
if cur then
|
|
||||||
return cur
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Left, if not already checked
|
|
||||||
if left_check then
|
|
||||||
cur = boost_cart:check_front_up_down(pos, left, false, railtype)
|
|
||||||
if cur then
|
|
||||||
return cur
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Right, if not already checked
|
|
||||||
if right_check then
|
|
||||||
cur = boost_cart:check_front_up_down(pos, right, false, railtype)
|
|
||||||
if cur then
|
|
||||||
return cur
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Backwards
|
|
||||||
if not old_switch then
|
|
||||||
cur = boost_cart:check_front_up_down(pos, {
|
|
||||||
x = -dir.x,
|
|
||||||
y = dir.y,
|
|
||||||
z = -dir.z
|
|
||||||
}, true, railtype)
|
|
||||||
if cur then
|
|
||||||
return cur
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {x=0, y=0, z=0}
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart:boost_rail(pos, amount)
|
|
||||||
minetest.get_meta(pos):set_string("cart_acceleration", tostring(amount))
|
|
||||||
for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 0.5)) do
|
|
||||||
if not obj_:is_player()
|
|
||||||
and obj_:get_luaentity()
|
|
||||||
and obj_:get_luaentity().name == "carts:cart" then
|
|
||||||
obj_:get_luaentity():on_punch()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,380 +0,0 @@
|
||||||
boost_cart = {}
|
|
||||||
boost_cart.modpath = minetest.get_modpath("boost_cart")
|
|
||||||
boost_cart.speed_max = 10
|
|
||||||
|
|
||||||
function vector.floor(v)
|
|
||||||
return {
|
|
||||||
x = math.floor(v.x),
|
|
||||||
y = math.floor(v.y),
|
|
||||||
z = math.floor(v.z)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
dofile(boost_cart.modpath.."/functions.lua")
|
|
||||||
dofile(boost_cart.modpath.."/rails.lua")
|
|
||||||
|
|
||||||
-- Support for non-default games
|
|
||||||
if not default.player_attached then
|
|
||||||
default.player_attached = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
boost_cart.cart = {
|
|
||||||
physical = false,
|
|
||||||
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
|
||||||
visual = "mesh",
|
|
||||||
mesh = "cart.x",
|
|
||||||
visual_size = {x=1, y=1},
|
|
||||||
textures = {"cart.png"},
|
|
||||||
driver = nil,
|
|
||||||
punched = false, -- used to re-send velocity and position
|
|
||||||
velocity = {x=0, y=0, z=0}, -- only used on punch
|
|
||||||
old_dir = {x=0, y=0, z=0},
|
|
||||||
old_pos = nil,
|
|
||||||
old_switch = 0,
|
|
||||||
railtype = nil,
|
|
||||||
attached_items = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
local function get_v(v)
|
|
||||||
return math.sqrt(v.x ^ 2 + v.z ^ 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart.cart:on_rightclick(clicker)
|
|
||||||
if not clicker or not clicker:is_player() then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local player_name = clicker:get_player_name()
|
|
||||||
if self.driver and player_name == self.driver then
|
|
||||||
self.driver = nil
|
|
||||||
clicker:set_detach()
|
|
||||||
elseif not self.driver then
|
|
||||||
self.driver = player_name
|
|
||||||
default.player_attached[player_name] = true
|
|
||||||
clicker:set_attach(self.object, "", {x=0, y=3, z=0}, {x=0, y=0, z=0})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart.cart:on_activate(staticdata, dtime_s)
|
|
||||||
|
|
||||||
if mobs and mobs.entity and mobs.entity == false then
|
|
||||||
self.object:remove()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:set_armor_groups({immortal=1})
|
|
||||||
self.driver = nil
|
|
||||||
self.count = 0
|
|
||||||
self.snd = 0
|
|
||||||
self.handle = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart.cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
|
|
||||||
local pos = self.object:getpos()
|
|
||||||
if not self.railtype then
|
|
||||||
local node = minetest.get_node(vector.floor(pos)).name
|
|
||||||
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
|
|
||||||
end
|
|
||||||
|
|
||||||
if not puncher or not puncher:is_player() then
|
|
||||||
local cart_dir = boost_cart:get_rail_direction(pos, {x=1, y=0, z=0}, nil, nil, self.railtype)
|
|
||||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
self.velocity = vector.multiply(cart_dir, 3)
|
|
||||||
self.old_pos = nil
|
|
||||||
self.punched = true
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if puncher:get_player_control().sneak then
|
|
||||||
if self.driver then
|
|
||||||
if self.old_pos then
|
|
||||||
self.object:setpos(self.old_pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.handle then
|
|
||||||
minetest.sound_stop(self.handle)
|
|
||||||
self.handle = nil
|
|
||||||
self.snd = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
default.player_attached[self.driver] = nil
|
|
||||||
local player = minetest.get_player_by_name(self.driver)
|
|
||||||
if player then
|
|
||||||
player:set_detach()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _,obj_ in ipairs(self.attached_items) do
|
|
||||||
if obj_ then
|
|
||||||
obj_:set_detach()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local inv = puncher:get_inventory()
|
|
||||||
if inv:room_for_item("main", "carts:cart") then
|
|
||||||
inv:add_item("main", "carts:cart")
|
|
||||||
else
|
|
||||||
minetest.add_item(self.object:getpos(), "carts:cart")
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:remove()
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local vel = self.object:getvelocity()
|
|
||||||
if puncher:get_player_name() == self.driver then
|
|
||||||
if math.abs(vel.x + vel.z) > 7 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local punch_dir = boost_cart:velocity_to_dir(puncher:get_look_dir())
|
|
||||||
punch_dir.y = 0
|
|
||||||
local cart_dir = boost_cart:get_rail_direction(pos, punch_dir, nil, nil, self.railtype)
|
|
||||||
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
time_from_last_punch = math.min(time_from_last_punch, tool_capabilities.full_punch_interval)
|
|
||||||
local f = 3 * (time_from_last_punch / tool_capabilities.full_punch_interval)
|
|
||||||
|
|
||||||
self.velocity = vector.multiply(cart_dir, f)
|
|
||||||
self.old_pos = nil
|
|
||||||
self.punched = true
|
|
||||||
end
|
|
||||||
|
|
||||||
function boost_cart.cart:on_step(dtime)
|
|
||||||
|
|
||||||
self.count = self.count + dtime
|
|
||||||
|
|
||||||
-- no driver inside
|
|
||||||
if self.count > 10 and not self.driver then
|
|
||||||
minetest.add_item(self.object:getpos(), "carts:cart")
|
|
||||||
self.object:remove()
|
|
||||||
return
|
|
||||||
|
|
||||||
-- driver inside
|
|
||||||
elseif self.driver then
|
|
||||||
self.count = 0
|
|
||||||
|
|
||||||
-- items inside
|
|
||||||
elseif #self.attached_items > 0 then
|
|
||||||
self.count = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local vel = self.object:getvelocity()
|
|
||||||
|
|
||||||
local vv = get_v(vel) ; --print ("vel", vv, self.driver)
|
|
||||||
if vv > 1 and self.driver and self.snd == 0 then
|
|
||||||
|
|
||||||
self.handle = minetest.sound_play("cart_ride", {
|
|
||||||
-- to_player = self.player,
|
|
||||||
object = self.object,
|
|
||||||
gain = 1.0,
|
|
||||||
loop = true,
|
|
||||||
})
|
|
||||||
if self.handle then
|
|
||||||
self.snd = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if (vv < 1 or not self.driver) and self.snd == 1 then
|
|
||||||
|
|
||||||
if self.handle then
|
|
||||||
minetest.sound_stop(self.handle)
|
|
||||||
self.handle = nil
|
|
||||||
self.snd = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.punched then
|
|
||||||
vel = vector.add(vel, self.velocity)
|
|
||||||
self.object:setvelocity(vel)
|
|
||||||
elseif vector.equals(vel, {x=0, y=0, z=0}) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local dir, last_switch = nil, nil
|
|
||||||
local pos = self.object:getpos()
|
|
||||||
if self.old_pos and not self.punched then
|
|
||||||
local flo_pos = vector.floor(pos)
|
|
||||||
local flo_old = vector.floor(self.old_pos)
|
|
||||||
if vector.equals(flo_pos, flo_old) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local update = {}
|
|
||||||
local ctrl, player = nil, nil
|
|
||||||
if self.driver then
|
|
||||||
player = minetest.get_player_by_name(self.driver)
|
|
||||||
if player then
|
|
||||||
ctrl = player:get_player_control()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if self.old_pos then
|
|
||||||
local diff = vector.subtract(self.old_pos, pos)
|
|
||||||
for _,v in ipairs({"x","y","z"}) do
|
|
||||||
if math.abs(diff[v]) > 1.1 then
|
|
||||||
local expected_pos = vector.add(self.old_pos, self.old_dir)
|
|
||||||
dir, last_switch = boost_cart:get_rail_direction(pos, self.old_dir, ctrl, self.old_switch, self.railtype)
|
|
||||||
if vector.equals(dir, {x=0, y=0, z=0}) then
|
|
||||||
dir = false
|
|
||||||
pos = vector.new(expected_pos)
|
|
||||||
update.pos = true
|
|
||||||
end
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if vel.y == 0 then
|
|
||||||
for _,v in ipairs({"x", "z"}) do
|
|
||||||
if vel[v] ~= 0 and math.abs(vel[v]) < 0.9 then
|
|
||||||
vel[v] = 0
|
|
||||||
update.vel = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local cart_dir = boost_cart:velocity_to_dir(vel)
|
|
||||||
local max_vel = boost_cart.speed_max
|
|
||||||
if not dir then
|
|
||||||
dir, last_switch = boost_cart:get_rail_direction(pos, cart_dir, ctrl, self.old_switch, self.railtype)
|
|
||||||
end
|
|
||||||
|
|
||||||
local new_acc = {x=0, y=0, z=0}
|
|
||||||
if vector.equals(dir, {x=0, y=0, z=0}) then
|
|
||||||
vel = {x=0, y=0, z=0}
|
|
||||||
update.vel = true
|
|
||||||
else
|
|
||||||
-- If the direction changed
|
|
||||||
if dir.x ~= 0 and self.old_dir.z ~= 0 then
|
|
||||||
vel.x = dir.x * math.abs(vel.z)
|
|
||||||
vel.z = 0
|
|
||||||
pos.z = math.floor(pos.z + 0.5)
|
|
||||||
update.pos = true
|
|
||||||
end
|
|
||||||
if dir.z ~= 0 and self.old_dir.x ~= 0 then
|
|
||||||
vel.z = dir.z * math.abs(vel.x)
|
|
||||||
vel.x = 0
|
|
||||||
pos.x = math.floor(pos.x + 0.5)
|
|
||||||
update.pos = true
|
|
||||||
end
|
|
||||||
-- Up, down?
|
|
||||||
if dir.y ~= self.old_dir.y then
|
|
||||||
vel.y = dir.y * math.abs(vel.x + vel.z)
|
|
||||||
pos = vector.round(pos)
|
|
||||||
update.pos = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Slow down or speed up..
|
|
||||||
local acc = dir.y * -1.8
|
|
||||||
|
|
||||||
local speed_mod = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
|
|
||||||
if speed_mod and speed_mod ~= 0 then
|
|
||||||
if speed_mod > 0 then
|
|
||||||
for _,v in ipairs({"x","y","z"}) do
|
|
||||||
if math.abs(vel[v]) >= max_vel then
|
|
||||||
speed_mod = 0
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
acc = acc + (speed_mod * 8)
|
|
||||||
else
|
|
||||||
acc = acc - 0.4
|
|
||||||
-- Handbrake
|
|
||||||
if ctrl and ctrl.down and math.abs(vel.x + vel.z) > 1.2 then
|
|
||||||
acc = acc - 1.2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
new_acc = vector.multiply(dir, acc)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.object:setacceleration(new_acc)
|
|
||||||
self.old_pos = vector.new(pos)
|
|
||||||
self.old_dir = vector.new(dir)
|
|
||||||
self.old_switch = last_switch
|
|
||||||
|
|
||||||
-- Limits
|
|
||||||
for _,v in ipairs({"x","y","z"}) do
|
|
||||||
if math.abs(vel[v]) > max_vel then
|
|
||||||
vel[v] = boost_cart:get_sign(vel[v]) * max_vel
|
|
||||||
update.vel = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.punched then
|
|
||||||
-- Collect dropped items
|
|
||||||
for _,obj_ in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
|
|
||||||
if not obj_:is_player() and
|
|
||||||
obj_:get_luaentity() and
|
|
||||||
not obj_:get_luaentity().physical_state and
|
|
||||||
obj_:get_luaentity().name == "__builtin:item" then
|
|
||||||
obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
|
|
||||||
self.attached_items[#self.attached_items + 1] = obj_
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.punched = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if not (update.vel or update.pos) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local yaw = 0
|
|
||||||
if dir.x < 0 then
|
|
||||||
yaw = 0.5
|
|
||||||
elseif dir.x > 0 then
|
|
||||||
yaw = 1.5
|
|
||||||
elseif dir.z < 0 then
|
|
||||||
yaw = 1
|
|
||||||
end
|
|
||||||
self.object:setyaw(yaw * math.pi)
|
|
||||||
|
|
||||||
local anim = {x=0, y=0}
|
|
||||||
if dir.y == -1 then
|
|
||||||
anim = {x=1, y=1}
|
|
||||||
elseif dir.y == 1 then
|
|
||||||
anim = {x=2, y=2}
|
|
||||||
end
|
|
||||||
self.object:set_animation(anim, 1, 0)
|
|
||||||
|
|
||||||
self.object:setvelocity(vel)
|
|
||||||
if update.pos then
|
|
||||||
self.object:setpos(pos)
|
|
||||||
end
|
|
||||||
update = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_entity(":carts:cart", boost_cart.cart)
|
|
||||||
minetest.register_craftitem(":carts:cart", {
|
|
||||||
description = "Cart",
|
|
||||||
inventory_image = minetest.inventorycube("cart_top.png", "cart_side.png", "cart_side.png"),
|
|
||||||
wield_image = "cart_side.png",
|
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
|
||||||
if not pointed_thing.type == "node" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if boost_cart:is_rail(pointed_thing.under) then
|
|
||||||
minetest.add_entity(pointed_thing.under, "carts:cart")
|
|
||||||
elseif boost_cart:is_rail(pointed_thing.above) then
|
|
||||||
minetest.add_entity(pointed_thing.above, "carts:cart")
|
|
||||||
else return end
|
|
||||||
|
|
||||||
itemstack:take_item()
|
|
||||||
return itemstack
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = "carts:cart",
|
|
||||||
recipe = {
|
|
||||||
{"default:steel_ingot", "", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
|
||||||
},
|
|
||||||
})
|
|
Before Width: | Height: | Size: 216 B |
|
@ -1,339 +0,0 @@
|
||||||
xof 0303txt 0032
|
|
||||||
|
|
||||||
Frame Root {
|
|
||||||
FrameTransformMatrix {
|
|
||||||
1.000000, 0.000000, 0.000000, 0.000000,
|
|
||||||
0.000000, 0.000000, 1.000000, 0.000000,
|
|
||||||
0.000000, 1.000000,-0.000000, 0.000000,
|
|
||||||
0.000000, 0.000000, 0.000000, 1.000000;;
|
|
||||||
}
|
|
||||||
Frame Cube {
|
|
||||||
FrameTransformMatrix {
|
|
||||||
5.000000, 0.000000,-0.000000, 0.000000,
|
|
||||||
-0.000000, 3.535534, 3.535534, 0.000000,
|
|
||||||
0.000000,-3.535534, 3.535534, 0.000000,
|
|
||||||
0.000000,-3.000000, 3.000000, 1.000000;;
|
|
||||||
}
|
|
||||||
Mesh { //Cube_001 Mesh
|
|
||||||
72;
|
|
||||||
-1.000000; 1.000000;-1.000000;,
|
|
||||||
-1.000000;-1.000000;-1.000000;,
|
|
||||||
1.000000;-1.000000;-1.000000;,
|
|
||||||
1.000000; 1.000000;-1.000000;,
|
|
||||||
-0.833334;-1.000000; 1.000000;,
|
|
||||||
-1.000000;-1.000000; 1.000000;,
|
|
||||||
-1.000000;-0.833333; 1.000000;,
|
|
||||||
-0.833334;-0.833333; 1.000000;,
|
|
||||||
-1.000000;-1.000000;-1.000000;,
|
|
||||||
-1.000000;-1.000000; 1.000000;,
|
|
||||||
0.999999;-1.000001; 1.000000;,
|
|
||||||
1.000000;-1.000000;-1.000000;,
|
|
||||||
0.999999;-1.000001; 1.000000;,
|
|
||||||
0.833332;-1.000000; 1.000000;,
|
|
||||||
0.833333;-0.833334; 1.000000;,
|
|
||||||
1.000000;-0.833334; 1.000000;,
|
|
||||||
0.833332;-1.000000; 1.000000;,
|
|
||||||
-0.833334;-1.000000; 1.000000;,
|
|
||||||
-0.833334;-0.833333; 1.000000;,
|
|
||||||
0.833333;-0.833334; 1.000000;,
|
|
||||||
1.000000; 0.833333; 1.000000;,
|
|
||||||
0.833334; 0.833333; 1.000000;,
|
|
||||||
0.833334; 1.000000; 1.000000;,
|
|
||||||
1.000000; 0.999999; 1.000000;,
|
|
||||||
1.000000;-0.833334; 1.000000;,
|
|
||||||
0.833333;-0.833334; 1.000000;,
|
|
||||||
0.833334; 0.833333; 1.000000;,
|
|
||||||
1.000000; 0.833333; 1.000000;,
|
|
||||||
0.833334; 0.833333; 1.000000;,
|
|
||||||
-0.833333; 0.833333; 1.000000;,
|
|
||||||
-0.833333; 1.000000; 1.000000;,
|
|
||||||
0.833334; 1.000000; 1.000000;,
|
|
||||||
0.833334; 0.833333;-0.800000;,
|
|
||||||
-0.833333; 0.833333;-0.800000;,
|
|
||||||
-0.833333; 0.833333; 1.000000;,
|
|
||||||
0.833334; 0.833333; 1.000000;,
|
|
||||||
-0.833333; 0.833333; 1.000000;,
|
|
||||||
-1.000000; 0.833333; 1.000000;,
|
|
||||||
-1.000000; 1.000000; 1.000000;,
|
|
||||||
-0.833333; 1.000000; 1.000000;,
|
|
||||||
-0.833334;-0.833333; 1.000000;,
|
|
||||||
-1.000000;-0.833333; 1.000000;,
|
|
||||||
-1.000000; 0.833333; 1.000000;,
|
|
||||||
-0.833333; 0.833333; 1.000000;,
|
|
||||||
0.833333;-0.833334;-0.800000;,
|
|
||||||
-0.833334;-0.833333;-0.800000;,
|
|
||||||
-0.833333; 0.833333;-0.800000;,
|
|
||||||
0.833334; 0.833333;-0.800000;,
|
|
||||||
-0.833333; 0.833333;-0.800000;,
|
|
||||||
-0.833334;-0.833333;-0.800000;,
|
|
||||||
-0.833334;-0.833333; 1.000000;,
|
|
||||||
-0.833333; 0.833333; 1.000000;,
|
|
||||||
-0.833334;-0.833333;-0.800000;,
|
|
||||||
0.833333;-0.833334;-0.800000;,
|
|
||||||
0.833333;-0.833334; 1.000000;,
|
|
||||||
-0.833334;-0.833333; 1.000000;,
|
|
||||||
0.833333;-0.833334;-0.800000;,
|
|
||||||
0.833334; 0.833333;-0.800000;,
|
|
||||||
0.833334; 0.833333; 1.000000;,
|
|
||||||
0.833333;-0.833334; 1.000000;,
|
|
||||||
-1.000000; 1.000000;-1.000000;,
|
|
||||||
-1.000000; 1.000000; 1.000000;,
|
|
||||||
-1.000000;-1.000000; 1.000000;,
|
|
||||||
-1.000000;-1.000000;-1.000000;,
|
|
||||||
-1.000000; 1.000000; 1.000000;,
|
|
||||||
-1.000000; 1.000000;-1.000000;,
|
|
||||||
1.000000; 1.000000;-1.000000;,
|
|
||||||
1.000000; 0.999999; 1.000000;,
|
|
||||||
1.000000;-1.000000;-1.000000;,
|
|
||||||
0.999999;-1.000001; 1.000000;,
|
|
||||||
1.000000; 0.999999; 1.000000;,
|
|
||||||
1.000000; 1.000000;-1.000000;;
|
|
||||||
18;
|
|
||||||
4;0;1;2;3;,
|
|
||||||
4;4;5;6;7;,
|
|
||||||
4;8;9;10;11;,
|
|
||||||
4;12;13;14;15;,
|
|
||||||
4;16;17;18;19;,
|
|
||||||
4;20;21;22;23;,
|
|
||||||
4;24;25;26;27;,
|
|
||||||
4;28;29;30;31;,
|
|
||||||
4;32;33;34;35;,
|
|
||||||
4;36;37;38;39;,
|
|
||||||
4;40;41;42;43;,
|
|
||||||
4;44;45;46;47;,
|
|
||||||
4;48;49;50;51;,
|
|
||||||
4;52;53;54;55;,
|
|
||||||
4;56;57;58;59;,
|
|
||||||
4;60;61;62;63;,
|
|
||||||
4;64;65;66;67;,
|
|
||||||
4;68;69;70;71;;
|
|
||||||
MeshNormals { //Cube_001 Normals
|
|
||||||
72;
|
|
||||||
0.000000; 0.000000;-1.000000;,
|
|
||||||
0.000000; 0.000000;-1.000000;,
|
|
||||||
0.000000; 0.000000;-1.000000;,
|
|
||||||
0.000000; 0.000000;-1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
-0.000000;-1.000000;-0.000000;,
|
|
||||||
-0.000000;-1.000000;-0.000000;,
|
|
||||||
-0.000000;-1.000000;-0.000000;,
|
|
||||||
-0.000000;-1.000000;-0.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
-0.000000;-1.000000; 0.000000;,
|
|
||||||
-0.000000;-1.000000; 0.000000;,
|
|
||||||
-0.000000;-1.000000; 0.000000;,
|
|
||||||
-0.000000;-1.000000; 0.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
0.000000;-0.000000; 1.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
-1.000000; 0.000000; 0.000000;,
|
|
||||||
-1.000000; 0.000000; 0.000000;,
|
|
||||||
-1.000000; 0.000000; 0.000000;,
|
|
||||||
-1.000000; 0.000000; 0.000000;,
|
|
||||||
-1.000000; 0.000000;-0.000000;,
|
|
||||||
-1.000000; 0.000000;-0.000000;,
|
|
||||||
-1.000000; 0.000000;-0.000000;,
|
|
||||||
-1.000000; 0.000000;-0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
0.000000; 1.000000; 0.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;,
|
|
||||||
1.000000;-0.000000; 0.000000;;
|
|
||||||
18;
|
|
||||||
4;0;1;2;3;,
|
|
||||||
4;4;5;6;7;,
|
|
||||||
4;8;9;10;11;,
|
|
||||||
4;12;13;14;15;,
|
|
||||||
4;16;17;18;19;,
|
|
||||||
4;20;21;22;23;,
|
|
||||||
4;24;25;26;27;,
|
|
||||||
4;28;29;30;31;,
|
|
||||||
4;32;33;34;35;,
|
|
||||||
4;36;37;38;39;,
|
|
||||||
4;40;41;42;43;,
|
|
||||||
4;44;45;46;47;,
|
|
||||||
4;48;49;50;51;,
|
|
||||||
4;52;53;54;55;,
|
|
||||||
4;56;57;58;59;,
|
|
||||||
4;60;61;62;63;,
|
|
||||||
4;64;65;66;67;,
|
|
||||||
4;68;69;70;71;;
|
|
||||||
} //End of Cube_001 Normals
|
|
||||||
MeshMaterialList { //Cube_001 Material List
|
|
||||||
1;
|
|
||||||
18;
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0;;
|
|
||||||
Material Material {
|
|
||||||
0.640000; 0.640000; 0.640000; 1.000000;;
|
|
||||||
96.078431;
|
|
||||||
0.500000; 0.500000; 0.500000;;
|
|
||||||
0.000000; 0.000000; 0.000000;;
|
|
||||||
TextureFilename {"cart.png";}
|
|
||||||
}
|
|
||||||
} //End of Cube_001 Material List
|
|
||||||
MeshTextureCoords { //Cube_001 UV Coordinates
|
|
||||||
72;
|
|
||||||
0.000000; 0.500000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 1.000000;,
|
|
||||||
0.000000; 1.000000;,
|
|
||||||
0.031250; 0.500000;,
|
|
||||||
-0.000000; 0.500000;,
|
|
||||||
-0.000000; 0.468750;,
|
|
||||||
0.031250; 0.468750;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
1.000000; 0.500000;,
|
|
||||||
0.468750; 0.468750;,
|
|
||||||
0.500000; 0.468750;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.468750; 0.500000;,
|
|
||||||
0.031250; 0.468750;,
|
|
||||||
0.468750; 0.468750;,
|
|
||||||
0.468750; 0.500000;,
|
|
||||||
0.031250; 0.500000;,
|
|
||||||
0.468750; 0.000000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
0.500000; 0.031250;,
|
|
||||||
0.468750; 0.031250;,
|
|
||||||
0.468750; 0.031250;,
|
|
||||||
0.500000; 0.031250;,
|
|
||||||
0.500000; 0.468750;,
|
|
||||||
0.468750; 0.468750;,
|
|
||||||
0.468750; 0.031250;,
|
|
||||||
0.031250; 0.031250;,
|
|
||||||
0.031250; 0.000000;,
|
|
||||||
0.468750; 0.000000;,
|
|
||||||
1.000000; 0.500000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
0.031250; 0.031250;,
|
|
||||||
0.000000; 0.031250;,
|
|
||||||
0.000000; 0.000000;,
|
|
||||||
0.031250; 0.000000;,
|
|
||||||
0.031250; 0.468750;,
|
|
||||||
-0.000000; 0.468750;,
|
|
||||||
0.000000; 0.031250;,
|
|
||||||
0.031250; 0.031250;,
|
|
||||||
0.000000; 0.500000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 1.000000;,
|
|
||||||
0.000000; 1.000000;,
|
|
||||||
1.000000; 0.500000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
1.000000; 0.500000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
1.000000; 0.500000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
1.000000; 0.500000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
1.000000; 0.500000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
0.500000; 0.500000;,
|
|
||||||
0.500000; 0.000000;,
|
|
||||||
1.000000; 0.000000;,
|
|
||||||
1.000000; 0.500000;;
|
|
||||||
} //End of Cube_001 UV Coordinates
|
|
||||||
} //End of Cube_001 Mesh
|
|
||||||
} //End of Cube
|
|
||||||
} //End of Root Frame
|
|
||||||
AnimationSet {
|
|
||||||
Animation {
|
|
||||||
{Cube}
|
|
||||||
AnimationKey { //Position
|
|
||||||
2;
|
|
||||||
4;
|
|
||||||
0;3; 0.000000, 0.000000, 0.000000;;,
|
|
||||||
1;3; 0.000000, 3.000000, 3.000000;;,
|
|
||||||
2;3; 0.000000,-3.000000, 3.000000;;,
|
|
||||||
3;3; 0.000000,-3.000000, 3.000000;;;
|
|
||||||
}
|
|
||||||
AnimationKey { //Rotation
|
|
||||||
0;
|
|
||||||
4;
|
|
||||||
0;4; -1.000000, 0.000000, 0.000000, 0.000000;;,
|
|
||||||
1;4; -0.923880,-0.382683,-0.000000, 0.000000;;,
|
|
||||||
2;4; -0.923880, 0.382683, 0.000000, 0.000000;;,
|
|
||||||
3;4; -0.923880, 0.382683, 0.000000, 0.000000;;;
|
|
||||||
}
|
|
||||||
AnimationKey { //Scale
|
|
||||||
1;
|
|
||||||
4;
|
|
||||||
0;3; 5.000000, 5.000000, 5.000000;;,
|
|
||||||
1;3; 5.000000, 5.000000, 5.000000;;,
|
|
||||||
2;3; 5.000000, 5.000000, 5.000000;;,
|
|
||||||
3;3; 5.000000, 5.000000, 5.000000;;;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} //End of AnimationSet
|
|
|
@ -1,115 +0,0 @@
|
||||||
minetest.register_node("boost_cart:rail", {
|
|
||||||
description = "Rail",
|
|
||||||
drawtype = "raillike",
|
|
||||||
tiles = {"default_rail.png", "default_rail_curved.png", "default_rail_t_junction.png", "default_rail_crossing.png"},
|
|
||||||
inventory_image = "default_rail.png",
|
|
||||||
wield_image = "default_rail.png",
|
|
||||||
paramtype = "light",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
|
||||||
},
|
|
||||||
groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1},
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = 'boost_cart:rail 15',
|
|
||||||
recipe = {
|
|
||||||
{'default:steel_ingot', '', 'default:steel_ingot'},
|
|
||||||
{'default:steel_ingot', 'default:stick', 'default:steel_ingot'},
|
|
||||||
{'default:steel_ingot', '', 'default:steel_ingot'},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Speed up
|
|
||||||
|
|
||||||
minetest.register_node(":carts:powerrail", {
|
|
||||||
description = "Powered rail",
|
|
||||||
drawtype = "raillike",
|
|
||||||
tiles = {"carts_rail_pwr.png", "carts_rail_curved_pwr.png", "carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"},
|
|
||||||
inventory_image = "carts_rail_pwr.png",
|
|
||||||
wield_image = "carts_rail_pwr.png",
|
|
||||||
paramtype = "light",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
|
||||||
},
|
|
||||||
groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1},
|
|
||||||
|
|
||||||
after_place_node = function(pos, placer, itemstack)
|
|
||||||
if not mesecon then
|
|
||||||
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
mesecons = {
|
|
||||||
effector = {
|
|
||||||
action_on = function(pos, node)
|
|
||||||
boost_cart:boost_rail(pos, 0.5)
|
|
||||||
end,
|
|
||||||
|
|
||||||
action_off = function(pos, node)
|
|
||||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = "carts:powerrail 6",
|
|
||||||
recipe = {
|
|
||||||
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node(":carts:brakerail", {
|
|
||||||
description = "Brake rail",
|
|
||||||
drawtype = "raillike",
|
|
||||||
tiles = {"carts_rail_brk.png", "carts_rail_curved_brk.png", "carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"},
|
|
||||||
inventory_image = "carts_rail_brk.png",
|
|
||||||
wield_image = "carts_rail_brk.png",
|
|
||||||
paramtype = "light",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
is_ground_content = false,
|
|
||||||
walkable = false,
|
|
||||||
selection_box = {
|
|
||||||
type = "fixed",
|
|
||||||
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
|
||||||
},
|
|
||||||
groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1},
|
|
||||||
|
|
||||||
after_place_node = function(pos, placer, itemstack)
|
|
||||||
if not mesecon then
|
|
||||||
minetest.get_meta(pos):set_string("cart_acceleration", "-0.2")
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
mesecons = {
|
|
||||||
effector = {
|
|
||||||
action_on = function(pos, node)
|
|
||||||
boost_cart:boost_rail(pos, -0.2)
|
|
||||||
end,
|
|
||||||
|
|
||||||
action_off = function(pos, node)
|
|
||||||
minetest.get_meta(pos):set_string("cart_acceleration", "0")
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = "carts:brakerail 6",
|
|
||||||
recipe = {
|
|
||||||
{"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
|
|
||||||
{"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
|
|
||||||
}
|
|
||||||
})
|
|
Before Width: | Height: | Size: 147 B |
Before Width: | Height: | Size: 131 B |
Before Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 392 B |
Before Width: | Height: | Size: 393 B |
Before Width: | Height: | Size: 381 B |
Before Width: | Height: | Size: 389 B |
Before Width: | Height: | Size: 383 B |
Before Width: | Height: | Size: 399 B |
Before Width: | Height: | Size: 383 B |
Before Width: | Height: | Size: 399 B |
|
@ -1,73 +0,0 @@
|
||||||
local default_spawn_settings = minetest.setting_get("static_spawnpoint")
|
|
||||||
|
|
||||||
minetest.register_globalstep(function(dtime)
|
|
||||||
local players = minetest.get_connected_players()
|
|
||||||
for i,player in ipairs(players) do
|
|
||||||
local function has_compass(player)
|
|
||||||
for _,stack in ipairs(player:get_inventory():get_list("main")) do
|
|
||||||
if minetest.get_item_group(stack:get_name(), "compass") ~= 0 then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if has_compass(player) then
|
|
||||||
local spawn = beds_player_spawns[player:get_player_name()] or
|
|
||||||
minetest.setting_get("static_spawnpoint") or
|
|
||||||
{x=0,y=0,z=0}
|
|
||||||
pos = player:getpos()
|
|
||||||
dir = player:get_look_yaw()
|
|
||||||
local angle_north = math.deg(math.atan2(spawn.x - pos.x, spawn.z - pos.z))
|
|
||||||
if angle_north < 0 then angle_north = angle_north + 360 end
|
|
||||||
angle_dir = 90 - math.deg(dir)
|
|
||||||
local angle_relative = (angle_north - angle_dir) % 360
|
|
||||||
local compass_image = math.floor((angle_relative/30) + 0.5)%12
|
|
||||||
|
|
||||||
for j,stack in ipairs(player:get_inventory():get_list("main")) do
|
|
||||||
if minetest.get_item_group(stack:get_name(), "compass") ~= 0 and
|
|
||||||
minetest.get_item_group(stack:get_name(), "compass")-1 ~= compass_image then
|
|
||||||
player:get_inventory():set_stack("main", j, "compass:"..compass_image)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local images = {
|
|
||||||
"compass_0.png",
|
|
||||||
"compass_1.png",
|
|
||||||
"compass_2.png",
|
|
||||||
"compass_3.png",
|
|
||||||
"compass_4.png",
|
|
||||||
"compass_5.png",
|
|
||||||
"compass_6.png",
|
|
||||||
"compass_7.png",
|
|
||||||
"compass_8.png",
|
|
||||||
"compass_9.png",
|
|
||||||
"compass_10.png",
|
|
||||||
"compass_11.png",
|
|
||||||
}
|
|
||||||
|
|
||||||
local i
|
|
||||||
for i,img in ipairs(images) do
|
|
||||||
local inv = 1
|
|
||||||
if i == 1 then
|
|
||||||
inv = 0
|
|
||||||
end
|
|
||||||
minetest.register_tool("compass:"..(i-1), {
|
|
||||||
description = "Compass",
|
|
||||||
inventory_image = img,
|
|
||||||
wield_image = img,
|
|
||||||
stack_max = 1,
|
|
||||||
groups = {not_in_creative_inventory=inv,compass=i, tools = inv}
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
minetest.register_craft({
|
|
||||||
output = 'compass:1',
|
|
||||||
recipe = {
|
|
||||||
{'', 'default:iron_ingot', ''},
|
|
||||||
{'default:iron_ingot', 'default_bluestone_dust', 'default:iron_ingot'},
|
|
||||||
{'', 'default:iron_ingot', ''}
|
|
||||||
}
|
|
||||||
})
|
|
Before Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 210 B |
Before Width: | Height: | Size: 209 B |
Before Width: | Height: | Size: 206 B |
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 360 B |
|
@ -1922,25 +1922,3 @@ minetest.register_node("default:snowblock", {
|
||||||
}),
|
}),
|
||||||
drop = "default:snow 4",
|
drop = "default:snow 4",
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_node("default:cobweb", {
|
|
||||||
description = "Cobweb",
|
|
||||||
drawtype = "plantlike",
|
|
||||||
visual_scale = 1.1,
|
|
||||||
stack_max = 64,
|
|
||||||
tiles = {"web.png"},
|
|
||||||
inventory_image = "web.png",
|
|
||||||
paramtype = "light",
|
|
||||||
sunlight_propagates = true,
|
|
||||||
liquid_viscosity = 14,
|
|
||||||
liquidtype = "source",
|
|
||||||
liquid_alternative_flowing = "default:cobweb",
|
|
||||||
liquid_alternative_source = "default:cobweb",
|
|
||||||
liquid_renewable = false,
|
|
||||||
liquid_range = 0,
|
|
||||||
walkable = false,
|
|
||||||
groups = {snappy=1,liquid=3,flammable=2, decorative = 1},
|
|
||||||
drop = "farming:string",
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_alias('mobs:cobweb','default:cobweb')
|
|
After Width: | Height: | Size: 241 B |
Before Width: | Height: | Size: 271 B |
|
@ -1,5 +1,9 @@
|
||||||
Minetest 0.4 mod: fire
|
Fire Redo 0.2
|
||||||
======================
|
|
||||||
|
by TenPlus1
|
||||||
|
|
||||||
|
Based on Minetest 0.4 mod: fire with changes by HybridDog
|
||||||
|
=========================================================
|
||||||
|
|
||||||
License of source code:
|
License of source code:
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -7,10 +11,10 @@ Copyright (C) 2012 Perttu Ahola (celeron55) <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
the Free Software Foundation; either version 3.0 of the License, or
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
http://www.gnu.org/licenses/lgpl-3.0.html
|
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
|
||||||
License of media (textures and sounds)
|
License of media (textures and sounds)
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -1,37 +1,17 @@
|
||||||
|
-- minetest/fire/init.lua (HybridDog pull request changes)
|
||||||
|
|
||||||
|
-- Tweaked by TenPlus1 to add chest drops, also removed sounds which are now
|
||||||
|
-- handled by Ambience mod.
|
||||||
|
|
||||||
|
|
||||||
|
-- Global namespace for functions
|
||||||
|
|
||||||
fire = {}
|
fire = {}
|
||||||
fire.mod = "redo"
|
fire.mod = "redo"
|
||||||
|
|
||||||
-- initial check to see if fire is disabled
|
-- Register flame nodes
|
||||||
local disable_fire = minetest.setting_getbool("disable_fire")
|
|
||||||
|
|
||||||
minetest.register_node("fire:basic_flame", {
|
local flamedef = {
|
||||||
description = "Basic Flame",
|
|
||||||
drawtype = "plantlike",
|
|
||||||
tiles = {
|
|
||||||
{
|
|
||||||
name = "fire_basic_flame_animated.png",
|
|
||||||
animation = {
|
|
||||||
type="vertical_frames",
|
|
||||||
aspect_w = 16,
|
|
||||||
aspect_h = 16,
|
|
||||||
length = 1
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
inventory_image = "fire_basic_flame.png",
|
|
||||||
paramtype = "light",
|
|
||||||
light_source = 14,
|
|
||||||
walkable = false,
|
|
||||||
buildable_to = true,
|
|
||||||
sunlight_propagates = true,
|
|
||||||
damage_per_second = 4,
|
|
||||||
groups = {igniter = 2, dig_immediate = 3},
|
|
||||||
drop = '',
|
|
||||||
on_blast = function()
|
|
||||||
end, -- unaffected by explosions
|
|
||||||
})
|
|
||||||
|
|
||||||
minetest.register_node("fire:permanent_flame", {
|
|
||||||
description = "Permanent Flame",
|
description = "Permanent Flame",
|
||||||
drawtype = "firelike",
|
drawtype = "firelike",
|
||||||
tiles = {
|
tiles = {
|
||||||
|
@ -56,83 +36,162 @@ minetest.register_node("fire:permanent_flame", {
|
||||||
drop = "",
|
drop = "",
|
||||||
|
|
||||||
on_blast = function()
|
on_blast = function()
|
||||||
end,
|
end, -- unaffected by explosions
|
||||||
})
|
}
|
||||||
|
minetest.register_node("fire:permanent_flame", table.copy(flamedef))
|
||||||
|
|
||||||
-- compatibility
|
flamedef.description = "Basic Flame"
|
||||||
minetest.register_alias("fire:eternal_flame", "fire:permanent_flame")
|
flamedef.drawtype = "plantlike" -- quick draw for basic flame, fancy for permanent
|
||||||
|
|
||||||
-- extinguish flames quickly with dedicated ABM
|
minetest.register_node("fire:basic_flame", flamedef)
|
||||||
minetest.register_abm({
|
|
||||||
nodenames = {"fire:basic_flame"},
|
|
||||||
interval = 7,
|
-- Return positions for flames around a burning node
|
||||||
chance = 2,
|
|
||||||
catch_up = false,
|
function fire.find_pos_for_flame_around(pos)
|
||||||
action = function(p0, node, _, _)
|
return minetest.find_node_near(pos, 1, {"air"})
|
||||||
if not disable_fire then return end
|
end
|
||||||
minetest.set_node(p0, {name = "air"})
|
|
||||||
end,
|
|
||||||
})
|
-- Detect nearby extinguishing nodes
|
||||||
|
|
||||||
|
function fire.flame_should_extinguish(pos)
|
||||||
|
return minetest.find_node_near(pos, 1, {"group:puts_out_fire"})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Extinguish all flames quickly with water, snow, ice
|
||||||
|
|
||||||
-- extinguish flames quickly with water, snow, ice
|
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
nodenames = {"fire:basic_flame", "fire:permanent_flame"},
|
nodenames = {"fire:basic_flame", "fire:permanent_flame"},
|
||||||
neighbors = {"group:puts_out_fire"},
|
neighbors = {"group:puts_out_fire"},
|
||||||
interval = 3,
|
interval = 3,
|
||||||
chance = 2,
|
chance = 1,
|
||||||
catch_up = false,
|
catch_up = false,
|
||||||
action = function(p0, node, _, _)
|
action = function(p0)
|
||||||
minetest.set_node(p0, {name = "air"})
|
-- fire node holds no metadata so quickly swap out for air
|
||||||
|
minetest.swap_node(p0, {name = "air"})
|
||||||
minetest.sound_play("fire_extinguish_flame",
|
minetest.sound_play("fire_extinguish_flame",
|
||||||
{pos = p0, max_hear_distance = 16, gain = 0.15})
|
{pos = p0, max_hear_distance = 16, gain = 0.25})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- ignite neighboring nodes
|
|
||||||
minetest.register_abm({
|
-- Enable the following ABMs according to 'disable fire' setting
|
||||||
|
|
||||||
|
if minetest.setting_getbool("disable_fire") then
|
||||||
|
|
||||||
|
-- Remove basic flames only
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
|
nodenames = {"fire:basic_flame"},
|
||||||
|
interval = 7,
|
||||||
|
chance = 1,
|
||||||
|
catch_up = false,
|
||||||
|
action = function(p0)
|
||||||
|
-- fire node holds no metadata so quickly swap out for air
|
||||||
|
minetest.swap_node(p0, {name = "air"})
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Ignite neighboring nodes, add basic flames
|
||||||
|
|
||||||
|
minetest.register_abm({
|
||||||
nodenames = {"group:flammable"},
|
nodenames = {"group:flammable"},
|
||||||
neighbors = {"group:igniter"},
|
neighbors = {"group:igniter"},
|
||||||
interval = 7,
|
interval = 7,
|
||||||
chance = 16,
|
chance = 16,
|
||||||
catch_up = false,
|
catch_up = false,
|
||||||
action = function(p0, node, _, _)
|
action = function(p0)
|
||||||
-- check to see if fire is still disabled
|
-- If there is water or stuff like that around node, don't ignite
|
||||||
disable_fire = minetest.setting_getbool("disable_fire")
|
if fire.flame_should_extinguish(p0) then
|
||||||
--print ("disable fire set to ", disable_fire)
|
|
||||||
|
|
||||||
-- if there is water or stuff like that around flame, don't ignite
|
|
||||||
if disable_fire
|
|
||||||
or minetest.find_node_near(p0, 1, {"group:puts_out_fire"}) then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local p = minetest.find_node_near(p0, 1, {"air"})
|
local p = fire.find_pos_for_flame_around(p0)
|
||||||
if p then
|
if p then
|
||||||
minetest.set_node(p, {name = "fire:basic_flame"})
|
-- air node holds no metadata so quickly swap out for fire
|
||||||
|
minetest.swap_node(p, {name = "fire:basic_flame"})
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- remove flammable nodes and flame
|
-- Remove basic flames and flammable nodes
|
||||||
minetest.register_abm({
|
|
||||||
|
minetest.register_abm({
|
||||||
nodenames = {"fire:basic_flame"},
|
nodenames = {"fire:basic_flame"},
|
||||||
interval = 5,
|
interval = 5,
|
||||||
chance = 16,
|
chance = 16,
|
||||||
catch_up = false,
|
catch_up = false,
|
||||||
action = function(p0, node, _, _)
|
action = function(p0)
|
||||||
|
|
||||||
-- If there are no flammable nodes around flame, remove flame
|
-- If there are no flammable nodes around flame, remove flame
|
||||||
if not minetest.find_node_near(p0, 1, {"group:flammable"}) then
|
if not minetest.find_node_near(p0, 1, {"group:flammable"}) then
|
||||||
minetest.set_node(p0, {name = "air"})
|
-- fire node holds no metadata so quickly swap out for air
|
||||||
|
minetest.swap_node(p0, {name = "air"})
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
if math.random(1, 4) ~= 1 then
|
||||||
if math.random(1, 4) == 1 then
|
return
|
||||||
-- remove a flammable node around flame
|
end
|
||||||
|
-- remove flammable nodes around flame
|
||||||
local p = minetest.find_node_near(p0, 1, {"group:flammable"})
|
local p = minetest.find_node_near(p0, 1, {"group:flammable"})
|
||||||
if p then
|
if not p then
|
||||||
minetest.set_node(p, {name = "air"})
|
return
|
||||||
-- nodeupdate(p)
|
end
|
||||||
|
local node = minetest.get_node(p)
|
||||||
|
local on_burn = minetest.registered_nodes[node.name].on_burn
|
||||||
|
if on_burn then
|
||||||
|
if type(on_burn) == "string" then
|
||||||
|
node.name = on_burn
|
||||||
|
minetest.set_node(p, node)
|
||||||
|
nodeupdate(p)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if on_burn(p, node) ~= false then
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
minetest.remove_node(p)
|
||||||
|
nodeupdate(p)
|
||||||
end,
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- used to drop items inside a chest or container
|
||||||
|
function fire.drop_items(pos, invstring)
|
||||||
|
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
|
||||||
|
for i = 1, inv:get_size(invstring) do
|
||||||
|
|
||||||
|
local m_stack = inv:get_stack(invstring, i)
|
||||||
|
local obj = minetest.add_item(pos, m_stack)
|
||||||
|
|
||||||
|
if obj then
|
||||||
|
|
||||||
|
obj:setvelocity({
|
||||||
|
x = math.random(-1, 1),
|
||||||
|
y = 3,
|
||||||
|
z = math.random(-1, 1)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- override chest node so that it's flammable
|
||||||
|
minetest.override_item("default:chest", {
|
||||||
|
|
||||||
|
groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 3},
|
||||||
|
|
||||||
|
on_burn = function(p)
|
||||||
|
fire.drop_items(p, "main")
|
||||||
|
minetest.remove_node(p)
|
||||||
|
end,
|
||||||
|
|
||||||
})
|
})
|
|
@ -15,16 +15,15 @@ if minetest.get_modpath("mobs") ~= nil then
|
||||||
if mobs.mod ~= nil and mobs.mod == "redo" then
|
if mobs.mod ~= nil and mobs.mod == "redo" then
|
||||||
register_food("mobs:cheese", 4)
|
register_food("mobs:cheese", 4)
|
||||||
register_food("mobs:meat", 8)
|
register_food("mobs:meat", 8)
|
||||||
register_food("mobs:meat_raw", 4, "", 2)
|
register_food("mobs:meat_raw", 4, "", 3)
|
||||||
register_food("mobs:rat_cooked", 4)
|
register_food("mobs:rat_cooked", 4)
|
||||||
register_food("mobs:rat_meat", 2)
|
register_food("mobs:rat_meat", 2)
|
||||||
register_food("mobs:honey", 2)
|
register_food("mobs:honey", 2)
|
||||||
register_food("mobs:pork_raw", 4, "", 2)
|
register_food("mobs:pork_raw", 3, "", 3)
|
||||||
register_food("mobs:pork_cooked", 8)
|
register_food("mobs:pork_cooked", 8)
|
||||||
register_food("mobs:chicken_cooked", 6)
|
register_food("mobs:chicken_cooked", 6)
|
||||||
register_food("mobs:chicken_raw", 2, "", 2)
|
register_food("mobs:chicken_raw", 2, "", 3)
|
||||||
register_food("mobs:chicken_egg_fried", 2)
|
register_food("mobs:chicken_egg_fried", 2)
|
||||||
register_food("mobs:rotten_flesh", 1, "", 5)
|
|
||||||
if minetest.get_modpath("bucket") then
|
if minetest.get_modpath("bucket") then
|
||||||
register_food("mobs:bucket_milk", 3, "bucket:bucket_empty")
|
register_food("mobs:bucket_milk", 3, "bucket:bucket_empty")
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,11 +22,11 @@ dofile(path.."/spider.lua") -- AspireMint
|
||||||
dofile(path.."/zombie.lua") -- Blockmen
|
dofile(path.."/zombie.lua") -- Blockmen
|
||||||
dofile(path.."/skeleton.lua") -- Blockmen
|
dofile(path.."/skeleton.lua") -- Blockmen
|
||||||
|
|
||||||
-- NPC
|
|
||||||
dofile(path.."/npc.lua") -- TenPlus1
|
|
||||||
|
|
||||||
-- Mob Items
|
-- Mob Items
|
||||||
dofile(path.."/crafts.lua")
|
dofile(path.."/crafts.lua")
|
||||||
|
|
||||||
-- Spawner
|
-- Spawner
|
||||||
dofile(path.."/spawner.lua")
|
dofile(path.."/spawner.lua")
|
||||||
|
|
||||||
|
-- Remove
|
||||||
|
dofile(path.."/npc.lua")
|
|
@ -75,7 +75,7 @@ minetest.register_node("mobs:cobweb", {
|
||||||
liquid_range = 0,
|
liquid_range = 0,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
groups = {snappy = 1, liquid = 3},
|
groups = {snappy = 1, liquid = 3},
|
||||||
drop = "farming:cotton",
|
--drop = "farming:cotton",
|
||||||
sounds = default.node_sound_leaves_defaults(),
|
sounds = default.node_sound_leaves_defaults(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 161 B |
Before Width: | Height: | Size: 127 B After Width: | Height: | Size: 127 B |
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 177 B |
Before Width: | Height: | Size: 167 B After Width: | Height: | Size: 167 B |
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 177 B |
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 573 B After Width: | Height: | Size: 573 B |
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 334 B |
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
Before Width: | Height: | Size: 129 B After Width: | Height: | Size: 129 B |
Before Width: | Height: | Size: 153 B After Width: | Height: | Size: 153 B |
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
|
@ -0,0 +1,21 @@
|
||||||
|
Minetest Mod - Railcart [railcart]
|
||||||
|
==================================
|
||||||
|
|
||||||
|
License Source Code: LGPL v2.1
|
||||||
|
|
||||||
|
License of media (textures, sounds and models not otherwise specified): CC-0
|
||||||
|
|
||||||
|
Authors of media files:
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
HybridDog: WTFPL
|
||||||
|
|
||||||
|
cart.png
|
||||||
|
cart_bottom.png
|
||||||
|
cart_side.png
|
||||||
|
cart_top.png
|
||||||
|
|
||||||
|
Zeg9:
|
||||||
|
|
||||||
|
cart.x
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
Minetest Mod - Railcart [railcart]
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Minetest version: 0.4.13
|
||||||
|
|
||||||
|
Depends: railtrack
|
||||||
|
|
||||||
|
Proof of concept ground up re-write of the carts mod. Currently uses media files
|
||||||
|
borrowed from the original carts mod by PilzAdam.
|
||||||
|
|
||||||
|
Please note, this mod makes heavy use of metadata so that carts are able to
|
||||||
|
travel through unloaded map chunks, therefor a 'carts' privilege is required
|
||||||
|
to place or pick up carts in multiplayer mode.
|
||||||
|
|
||||||
|
Crafting
|
||||||
|
--------
|
||||||
|
|
||||||
|
S = Steel Ingot [default:steel_ingot]
|
||||||
|
W = Wood [group:wood]
|
||||||
|
|
||||||
|
Railcart: [railcart:cart]
|
||||||
|
|
||||||
|
+---+---+---+
|
||||||
|
| S | | S |
|
||||||
|
+---+---+---+
|
||||||
|
| S | | S |
|
||||||
|
+---+---+---+
|
||||||
|
| W | S | W |
|
||||||
|
+---+---+---+
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
railtrack
|
|
@ -0,0 +1,191 @@
|
||||||
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
|
dofile(modpath.."/railcart.lua")
|
||||||
|
|
||||||
|
local worldpath = minetest.get_worldpath()
|
||||||
|
|
||||||
|
local function create_detached_inventory(id)
|
||||||
|
local inv = minetest.create_detached_inventory("railcart_"..tostring(id), {
|
||||||
|
on_put = function(inv, listname, index, stack, player)
|
||||||
|
railcart:save()
|
||||||
|
end,
|
||||||
|
on_take = function(inv, listname, index, stack, player)
|
||||||
|
railcart:save()
|
||||||
|
end,
|
||||||
|
allow_put = function(inv, listname, index, stack, player)
|
||||||
|
return 1
|
||||||
|
end,
|
||||||
|
allow_take = function(inv, listname, index, stack, player)
|
||||||
|
return stack:get_count()
|
||||||
|
end,
|
||||||
|
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||||
|
return count
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
inv:set_size("main", 32)
|
||||||
|
return inv
|
||||||
|
end
|
||||||
|
|
||||||
|
local input = io.open(worldpath.."/railcart.txt", "r")
|
||||||
|
if input then
|
||||||
|
local data = input:read('*all')
|
||||||
|
if data then
|
||||||
|
local carts = minetest.deserialize(data) or {}
|
||||||
|
for id, ref in pairs(carts) do
|
||||||
|
local cart = railcart.cart:new(ref)
|
||||||
|
if ref.inv then
|
||||||
|
local inv = create_detached_inventory(cart.id)
|
||||||
|
for i, stack in pairs(ref.inv) do
|
||||||
|
inv:set_stack("main", i, stack)
|
||||||
|
end
|
||||||
|
cart.inv = inv
|
||||||
|
end
|
||||||
|
railcart.allcarts[id] = cart
|
||||||
|
end
|
||||||
|
end
|
||||||
|
input = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local function is_valid_player(object)
|
||||||
|
if object then
|
||||||
|
return object:is_player()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
railcart:register_entity("railcart:cart_entity", {
|
||||||
|
on_punch = function(self, puncher, _, _, direction)
|
||||||
|
if not is_valid_player(puncher) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if puncher:get_player_control().sneak then
|
||||||
|
if self.cart then
|
||||||
|
if self.cart.id then
|
||||||
|
if self.cart.inv then
|
||||||
|
if not self.cart.inv:is_empty("main") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
railcart:remove_cart(self.cart.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.object:remove()
|
||||||
|
local inv = puncher:get_inventory()
|
||||||
|
if minetest.setting_getbool("creative_mode") then
|
||||||
|
if not inv:contains_item("main", "railcart:cart") then
|
||||||
|
inv:add_item("main", "railcart:cart")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
inv:add_item("main", "railcart:cart")
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.cart and direction then
|
||||||
|
if self.driver then
|
||||||
|
direction = {x=0, y=0, z=0}
|
||||||
|
local ld = self.driver:get_look_dir()
|
||||||
|
if ld.y > -0.99 then
|
||||||
|
direction = {
|
||||||
|
x = railtrack:get_sign(ld.x),
|
||||||
|
z = railtrack:get_sign(ld.z),
|
||||||
|
y = self.cart.dir.y
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local pos = vector.round(self.object:getpos())
|
||||||
|
local dir = vector.round(vector.normalize(direction))
|
||||||
|
local speed = railcart:velocity_to_speed(self.cart.vel)
|
||||||
|
self.timer = 0
|
||||||
|
self.cart.target = nil
|
||||||
|
self.cart.prev = pos
|
||||||
|
self.cart.vel = vector.multiply(dir, 5)
|
||||||
|
self.cart.accel = railtrack:get_acceleration(pos)
|
||||||
|
self.object:setvelocity(self.cart.vel)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_rightclick = function(self, clicker)
|
||||||
|
if not is_valid_player(clicker) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if clicker:get_player_control().sneak then
|
||||||
|
local name = clicker:get_player_name()
|
||||||
|
local cart = self.cart or {}
|
||||||
|
if cart.id and name then
|
||||||
|
local formspec = "size[8,9]"..
|
||||||
|
default.gui_bg..default.gui_bg_img..default.gui_slots..
|
||||||
|
"list[detached:railcart_"..cart.id..";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[detached:railcart_"..cart.id..";main]"..
|
||||||
|
"listring[current_player;main]"..
|
||||||
|
default.get_hotbar_bg(0,4.85)
|
||||||
|
minetest.show_formspec(name, "inventory", formspec)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self.driver and clicker == self.driver then
|
||||||
|
self.driver = nil
|
||||||
|
clicker:set_detach()
|
||||||
|
elseif not self.driver then
|
||||||
|
self.driver = clicker
|
||||||
|
clicker:set_attach(self.object, "", {x=0,y=5,z=0}, {x=0,y=0,z=0})
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craftitem("railcart:cart", {
|
||||||
|
description = "Railcart",
|
||||||
|
inventory_image = minetest.inventorycube("railcart_top.png", "railcart_side.png", "railcart_side.png"),
|
||||||
|
wield_image = "railcart_side.png",
|
||||||
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
|
local name = placer:get_player_name()
|
||||||
|
if not name or pointed_thing.type ~= "node" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not minetest.is_singleplayer() then
|
||||||
|
if not minetest.check_player_privs(name, {carts=true}) then
|
||||||
|
minetest.chat_send_player(name, "Requires carts privilege")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local pos = pointed_thing.under
|
||||||
|
if not railtrack:is_railnode(pos) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local carts = railcart:get_carts_in_radius(pos, 0.9)
|
||||||
|
if #carts > 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local id = railcart:get_new_id()
|
||||||
|
local ref = {
|
||||||
|
id = id,
|
||||||
|
inv = create_detached_inventory(id),
|
||||||
|
pos = vector.new(pos),
|
||||||
|
prev = vector.new(pos),
|
||||||
|
accel = railtrack:get_acceleration(pos),
|
||||||
|
dir = railcart:get_rail_direction(pos),
|
||||||
|
}
|
||||||
|
local cart = railcart.cart:new(ref)
|
||||||
|
table.insert(railcart.allcarts, cart)
|
||||||
|
railcart:save()
|
||||||
|
if not minetest.setting_getbool("creative_mode") then
|
||||||
|
itemstack:take_item()
|
||||||
|
end
|
||||||
|
return itemstack
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_privilege("carts", "Player can pick-up and place carts.")
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "railcart:cart",
|
||||||
|
recipe = {
|
||||||
|
{"default:steel_ingot", "", "default:steel_ingot"},
|
||||||
|
{"default:steel_ingot", "", "default:steel_ingot"},
|
||||||
|
{"group:wood", "default:steel_ingot", "group:wood"},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_on_shutdown(function()
|
||||||
|
railcart:save()
|
||||||
|
end)
|
||||||
|
|
|
@ -0,0 +1,444 @@
|
||||||
|
local ENTITY_UPDATE_TIME = 1
|
||||||
|
local OBJECT_UPDATE_TIME = 5
|
||||||
|
local OBJECT_SAVE_TIME = 10
|
||||||
|
local RELOAD_DISTANCE = 32
|
||||||
|
local SNAP_DISTANCE = 0.5
|
||||||
|
local SPEED_MIN = 0.1
|
||||||
|
local SPEED_MAX = 15
|
||||||
|
|
||||||
|
railcart = {
|
||||||
|
timer = 0,
|
||||||
|
allcarts = {},
|
||||||
|
default_entity = {
|
||||||
|
physical = false,
|
||||||
|
collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "railcart.b3d",
|
||||||
|
visual_size = {x=1, y=1},
|
||||||
|
textures = {"railcart.png"},
|
||||||
|
cart = nil,
|
||||||
|
driver = nil,
|
||||||
|
timer = 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
railcart.cart = {
|
||||||
|
id = nil,
|
||||||
|
pos = nil,
|
||||||
|
target = nil,
|
||||||
|
prev = nil,
|
||||||
|
accel = nil,
|
||||||
|
inv = nil,
|
||||||
|
dir = {x=0, y=0, z=0},
|
||||||
|
vel = {x=0, y=0, z=0},
|
||||||
|
acc = {x=0, y=0, z=0},
|
||||||
|
timer = 0,
|
||||||
|
name = "railcart:cart_entity",
|
||||||
|
}
|
||||||
|
|
||||||
|
function railcart.cart:new(obj)
|
||||||
|
obj = obj or {}
|
||||||
|
setmetatable(obj, self)
|
||||||
|
self.__index = self
|
||||||
|
return obj
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart.cart:is_loaded()
|
||||||
|
for _, player in pairs(minetest.get_connected_players()) do
|
||||||
|
local pos = player:getpos()
|
||||||
|
if pos then
|
||||||
|
local dist = railtrack:get_distance(pos, self.pos)
|
||||||
|
if dist <= RELOAD_DISTANCE then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart.cart:on_step(dtime)
|
||||||
|
self.timer = self.timer - dtime
|
||||||
|
if self.timer > 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.timer = OBJECT_UPDATE_TIME
|
||||||
|
local entity = railcart:get_cart_entity(self.id)
|
||||||
|
if entity.object then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if self:is_loaded() then
|
||||||
|
local object = minetest.add_entity(self.pos, self.name)
|
||||||
|
if object then
|
||||||
|
entity = object:get_luaentity() or {}
|
||||||
|
entity.cart = self
|
||||||
|
object:setvelocity(self.vel)
|
||||||
|
object:setacceleration(self.acc)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.timer = railcart:update(self, self.timer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:register_entity(name, def)
|
||||||
|
local ref = {}
|
||||||
|
for k, v in pairs(railcart.default_entity) do
|
||||||
|
ref[k] = def[k] or railtrack:copy(v)
|
||||||
|
end
|
||||||
|
ref.on_activate = function(self, staticdata, dtime_s)
|
||||||
|
if type(def.on_activate) == "function" then
|
||||||
|
def.on_activate(self, staticdata, dtime_s)
|
||||||
|
end
|
||||||
|
self.object:set_armor_groups({immortal=1})
|
||||||
|
if staticdata == "expired" then
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ref.on_step = function(self, dtime)
|
||||||
|
if type(def.on_step) == "function" then
|
||||||
|
def.on_step(self, dtime)
|
||||||
|
end
|
||||||
|
local cart = self.cart
|
||||||
|
local object = self.object
|
||||||
|
if not cart or not object then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.timer = self.timer - dtime
|
||||||
|
if self.timer > 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self.timer = railcart:update(cart, ENTITY_UPDATE_TIME, object)
|
||||||
|
if type(def.on_update) == "function" then
|
||||||
|
def.on_update(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ref.get_staticdata = function(self)
|
||||||
|
if type(def.get_staticdata) == "function" then
|
||||||
|
def.get_staticdata(self)
|
||||||
|
end
|
||||||
|
if self.cart then
|
||||||
|
if self.cart:is_loaded() == false then
|
||||||
|
self.cart.timer = 0
|
||||||
|
self.object:remove()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "expired"
|
||||||
|
end
|
||||||
|
for k, v in pairs(def) do
|
||||||
|
ref[k] = ref[k] or v
|
||||||
|
end
|
||||||
|
minetest.register_entity(name, ref)
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:save()
|
||||||
|
local carts = {}
|
||||||
|
for id, cart in pairs(railcart.allcarts) do
|
||||||
|
local ref = {}
|
||||||
|
for k, v in pairs(cart) do
|
||||||
|
ref[k] = v
|
||||||
|
end
|
||||||
|
local inv = {}
|
||||||
|
if ref.inv then
|
||||||
|
local list = ref.inv:get_list("main")
|
||||||
|
for i, stack in ipairs(list) do
|
||||||
|
inv[i] = stack:to_string()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ref.inv = inv
|
||||||
|
table.insert(carts, ref)
|
||||||
|
end
|
||||||
|
local output = io.open(minetest.get_worldpath().."/railcart.txt",'w')
|
||||||
|
if output then
|
||||||
|
output:write(minetest.serialize(carts))
|
||||||
|
io.close(output)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:remove_cart(id)
|
||||||
|
for i, cart in pairs(railcart.allcarts) do
|
||||||
|
if cart.id == id then
|
||||||
|
railcart.allcarts[i] = nil
|
||||||
|
railcart:save()
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_rail_direction(pos)
|
||||||
|
local target = nil
|
||||||
|
local cons = railtrack:get_connections(pos)
|
||||||
|
local ymax = pos.y
|
||||||
|
for _, con in pairs(cons) do
|
||||||
|
if con.y >= ymax then
|
||||||
|
ymax = con.y
|
||||||
|
target = con
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if target then
|
||||||
|
if #cons == 1 then
|
||||||
|
target.y = pos.y
|
||||||
|
end
|
||||||
|
return railtrack:get_direction(target, pos)
|
||||||
|
end
|
||||||
|
return {x=0, y=0, z=0}
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_new_id()
|
||||||
|
local id = 0
|
||||||
|
for _, cart in pairs(railcart.allcarts) do
|
||||||
|
if cart.id > id then
|
||||||
|
id = cart.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return id + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_cart_ref(id)
|
||||||
|
for _, cart in pairs(railcart.allcarts) do
|
||||||
|
if cart.id == id then
|
||||||
|
return cart
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_cart_entity(id)
|
||||||
|
local cart_ref = {}
|
||||||
|
for _, ref in pairs(minetest.luaentities) do
|
||||||
|
if ref.cart then
|
||||||
|
if ref.cart.id == id then
|
||||||
|
cart_ref = ref
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return cart_ref
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_carts_in_radius(pos, rad)
|
||||||
|
local carts = {}
|
||||||
|
for _, cart in pairs(railcart.allcarts) do
|
||||||
|
local px = pos.x - cart.pos.x
|
||||||
|
local py = pos.y - cart.pos.y
|
||||||
|
local pz = pos.z - cart.pos.z
|
||||||
|
if (px * px) + (py * py) + (pz * pz) <= rad * rad then
|
||||||
|
table.insert(carts, cart)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return carts
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_cart_in_sight(p1, p2)
|
||||||
|
local ref = nil
|
||||||
|
local dist = railtrack:get_distance(p1, p2) + 1
|
||||||
|
local dir = railtrack:get_direction(p2, p1)
|
||||||
|
local carts = railcart:get_carts_in_radius(p1, dist)
|
||||||
|
for _, cart in pairs(carts) do
|
||||||
|
if not vector.equals(p1, cart.pos) then
|
||||||
|
local dc = railtrack:get_direction(cart.pos, p1)
|
||||||
|
if vector.equals(dc, dir) then
|
||||||
|
local d = railtrack:get_distance(p1, cart.pos)
|
||||||
|
if d < dist then
|
||||||
|
dist = d
|
||||||
|
ref = cart
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ref
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_delta_time(vel, acc, dist)
|
||||||
|
if vel > 0 then
|
||||||
|
if acc == 0 then
|
||||||
|
return dist / vel
|
||||||
|
end
|
||||||
|
local r = math.sqrt(vel * vel + 2 * acc * dist)
|
||||||
|
if r > 0 then
|
||||||
|
return (-vel + r) / acc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 9999 --INF
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:velocity_to_dir(v)
|
||||||
|
if math.abs(v.x) > math.abs(v.z) then
|
||||||
|
return {x=railtrack:get_sign(v.x), y=railtrack:get_sign(v.y), z=0}
|
||||||
|
else
|
||||||
|
return {x=0, y=railtrack:get_sign(v.y), z=railtrack:get_sign(v.z)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:velocity_to_speed(vel)
|
||||||
|
local speed = math.max(math.abs(vel.x), math.abs(vel.z))
|
||||||
|
if speed < SPEED_MIN then
|
||||||
|
speed = 0
|
||||||
|
elseif speed > SPEED_MAX then
|
||||||
|
speed = SPEED_MAX
|
||||||
|
end
|
||||||
|
return speed
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:get_target(pos, vel)
|
||||||
|
local meta = minetest.get_meta(vector.round(pos))
|
||||||
|
local dir = self:velocity_to_dir(vel)
|
||||||
|
local targets = {}
|
||||||
|
local rots = railtrack.rotations
|
||||||
|
local contype = meta:get_string("contype") or ""
|
||||||
|
local s_junc = meta:get_string("junctions") or ""
|
||||||
|
local s_cons = meta:get_string("connections") or ""
|
||||||
|
local s_rots = meta:get_string("rotations") or ""
|
||||||
|
if contype == "section" then
|
||||||
|
local junctions = minetest.deserialize(s_junc) or {}
|
||||||
|
for _, p in pairs(junctions) do
|
||||||
|
table.insert(targets, p)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local cons = minetest.deserialize(s_cons) or {}
|
||||||
|
for _, p in pairs(cons) do
|
||||||
|
table.insert(targets, p)
|
||||||
|
end
|
||||||
|
if s_rots ~= "" then
|
||||||
|
local fwd = false
|
||||||
|
for _, p in pairs(cons) do
|
||||||
|
if vector.equals(vector.add(pos, dir), p) then
|
||||||
|
fwd = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if fwd == true or #cons == 1 then
|
||||||
|
rots = s_rots
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local rotations = railtrack:get_rotations(rots, dir)
|
||||||
|
for _, r in ipairs(rotations) do
|
||||||
|
for _, t in pairs(targets) do
|
||||||
|
local d = railtrack:get_direction(t, pos)
|
||||||
|
if r.x == d.x and r.z == d.z then
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railcart:update(cart, time, object)
|
||||||
|
if object then
|
||||||
|
cart.pos = object:getpos()
|
||||||
|
cart.vel = object:getvelocity()
|
||||||
|
end
|
||||||
|
if not cart.target then
|
||||||
|
cart.pos = vector.new(cart.prev)
|
||||||
|
cart.target = railcart:get_target(cart.pos, cart.vel)
|
||||||
|
if object then
|
||||||
|
object:moveto(cart.pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local speed = railcart:velocity_to_speed(cart.vel)
|
||||||
|
if cart.target then
|
||||||
|
cart.dir = railtrack:get_direction(cart.target, cart.pos)
|
||||||
|
else
|
||||||
|
speed = 0
|
||||||
|
end
|
||||||
|
if speed > SPEED_MIN then
|
||||||
|
local blocked = false
|
||||||
|
local cis = railcart:get_cart_in_sight(cart.pos, cart.target)
|
||||||
|
if cis then
|
||||||
|
if railcart:velocity_to_speed(cis.vel) == 0 then
|
||||||
|
cart.target = vector.subtract(cis.pos, cart.dir)
|
||||||
|
blocked = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--[[
|
||||||
|
if object then
|
||||||
|
local p1 = vector.add(cart.pos, {x=0, y=1, z=0})
|
||||||
|
local p2 = vector.add(cart.target, {x=0, y=1, z=0})
|
||||||
|
if minetest.get_node_or_nil(p2) then
|
||||||
|
local los, bp = minetest.line_of_sight(p1, p2)
|
||||||
|
if los == false then
|
||||||
|
bp.y = bp.y - 1
|
||||||
|
cart.target = vector.subtract(bp, cart.dir)
|
||||||
|
blocked = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
]]--
|
||||||
|
local d1 = railtrack:get_distance(cart.prev, cart.target)
|
||||||
|
local d2 = railtrack:get_distance(cart.prev, cart.pos)
|
||||||
|
local dist = d1 - d2
|
||||||
|
if dist > SNAP_DISTANCE then
|
||||||
|
local accel = railtrack.accel_flat
|
||||||
|
if cart.dir.y == -1 then
|
||||||
|
accel = railtrack.accel_down
|
||||||
|
elseif cart.dir.y == 1 then
|
||||||
|
accel = railtrack.accel_up
|
||||||
|
end
|
||||||
|
accel = cart.accel or accel
|
||||||
|
if object then
|
||||||
|
dist = math.max(dist - SNAP_DISTANCE, 0)
|
||||||
|
end
|
||||||
|
local dt = railcart:get_delta_time(speed, accel, dist)
|
||||||
|
if dt < time then
|
||||||
|
time = dt
|
||||||
|
end
|
||||||
|
local dp = speed * time + 0.5 * accel * time * time
|
||||||
|
local vf = speed + accel * time
|
||||||
|
if object then
|
||||||
|
if vf <= 0 then
|
||||||
|
speed = 0
|
||||||
|
accel = 0
|
||||||
|
end
|
||||||
|
cart.vel = vector.multiply(cart.dir, speed)
|
||||||
|
cart.acc = vector.multiply(cart.dir, accel)
|
||||||
|
elseif dp > 0 then
|
||||||
|
cart.vel = vector.multiply(cart.dir, vf)
|
||||||
|
cart.pos = vector.add(cart.pos, vector.multiply(cart.dir, dp))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if blocked and vector.equals(cart.target, cart.prev) then
|
||||||
|
cart.vel = {x=0, y=0, z=0}
|
||||||
|
cart.acc = {x=0, y=0, z=0}
|
||||||
|
else
|
||||||
|
cart.pos = vector.new(cart.target)
|
||||||
|
cart.prev = vector.new(cart.target)
|
||||||
|
cart.accel = railtrack:get_acceleration(cart.target)
|
||||||
|
cart.target = nil
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
cart.dir = railcart:get_rail_direction(cart.pos)
|
||||||
|
cart.vel = {x=0, y=0, z=0}
|
||||||
|
cart.acc = {x=0, y=0, z=0}
|
||||||
|
end
|
||||||
|
if object then
|
||||||
|
if cart.dir.y == -1 then
|
||||||
|
object:set_animation({x=1, y=1}, 1, 0)
|
||||||
|
elseif cart.dir.y == 1 then
|
||||||
|
object:set_animation({x=2, y=2}, 1, 0)
|
||||||
|
else
|
||||||
|
object:set_animation({x=0, y=0}, 1, 0)
|
||||||
|
end
|
||||||
|
if cart.dir.x < 0 then
|
||||||
|
object:setyaw(math.pi / 2)
|
||||||
|
elseif cart.dir.x > 0 then
|
||||||
|
object:setyaw(3 * math.pi / 2)
|
||||||
|
elseif cart.dir.z < 0 then
|
||||||
|
object:setyaw(math.pi)
|
||||||
|
elseif cart.dir.z > 0 then
|
||||||
|
object:setyaw(0)
|
||||||
|
end
|
||||||
|
object:setvelocity(cart.vel)
|
||||||
|
object:setacceleration(cart.acc)
|
||||||
|
end
|
||||||
|
return time
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
for _, cart in pairs(railcart.allcarts) do
|
||||||
|
cart:on_step(dtime)
|
||||||
|
end
|
||||||
|
railcart.timer = railcart.timer + dtime
|
||||||
|
if railcart.timer > OBJECT_SAVE_TIME then
|
||||||
|
railcart:save()
|
||||||
|
railcart.timer = 0
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 114 B After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 696 B |
After Width: | Height: | Size: 413 B |
|
@ -0,0 +1,14 @@
|
||||||
|
Minetest Mod - Railtrack [railtrack]
|
||||||
|
====================================
|
||||||
|
|
||||||
|
License Source Code: LGPL v2.1
|
||||||
|
|
||||||
|
License of media (textures, sounds and models not otherwise specified): CC-0
|
||||||
|
|
||||||
|
Authors of media files:
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
rarkenin:
|
||||||
|
|
||||||
|
cart_rail_*.png
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
Minetest Mod - Railtrack [railtrack]
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Minetest version: 0.4.13
|
||||||
|
|
||||||
|
Depends: default
|
||||||
|
|
||||||
|
Proof of concept rail networking system which enables rail-carts to travel
|
||||||
|
through unloaded map chunks.
|
||||||
|
|
||||||
|
Please note, this mod makes heavy use of metadata so that much of the processing
|
||||||
|
gets done as tracks are laid, for this reason a 'rails' privilege is required in
|
||||||
|
order to place rails when using multiplayer mode.
|
||||||
|
|
||||||
|
Crafting
|
||||||
|
--------
|
||||||
|
|
||||||
|
R = Rail [default:rail]
|
||||||
|
F = Mese Crystal Fragment [default:mese_crystal_fragment]
|
||||||
|
C = Coal Lump [default:coal_lump]
|
||||||
|
D = Diamond [default:diamond]
|
||||||
|
M = Mese Block [default:mese]
|
||||||
|
|
||||||
|
Powered Rail: [railtrack:powerrail]
|
||||||
|
|
||||||
|
By default these rails apply a positive acceleration during the time a cart
|
||||||
|
remains on a given section of track. When used with the mesecons mod the rails
|
||||||
|
will require power from a mesecon source to become active.
|
||||||
|
|
||||||
|
+---+---+---+
|
||||||
|
| R | F | R |
|
||||||
|
+---+---+---+
|
||||||
|
|
||||||
|
Braking Rail: [railtrack:brakerail]
|
||||||
|
|
||||||
|
By default these rails apply a negative acceleration during the time a cart
|
||||||
|
remains on a given section of track. When used with the mesecons mod the rails
|
||||||
|
will require power from a mesecon source to become active.
|
||||||
|
|
||||||
|
+---+---+---+
|
||||||
|
| R | C | R |
|
||||||
|
+---+---+---+
|
||||||
|
|
||||||
|
Superconducting Rail: [railtrack:superrail]
|
||||||
|
|
||||||
|
Zero friction rails that are easier to manage and are also a little less
|
||||||
|
cpu-intensive by avoiding the use of square root calculations.
|
||||||
|
|
||||||
|
+---+---+---+
|
||||||
|
| R | D | R |
|
||||||
|
+---+---+---+
|
||||||
|
|
||||||
|
Switching Rail: [railtrack:switchrail]
|
||||||
|
|
||||||
|
Currently depends on mesecons to do much other than provide a convenient, zero
|
||||||
|
friction union to join long sections of superconducting rails.
|
||||||
|
|
||||||
|
+---+---+---+
|
||||||
|
| R | M | R |
|
||||||
|
+---+---+---+
|
||||||
|
|
||||||
|
Misc Items
|
||||||
|
----------
|
||||||
|
|
||||||
|
Rail Fixer: [railtrack:fixer]
|
||||||
|
|
||||||
|
Only available in creative menu or with give(me) privileges.
|
||||||
|
|
||||||
|
Rail Inspector [railtrack:inspector]
|
||||||
|
|
||||||
|
Only available in creative menu or with give(me) privileges.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
default
|
|
@ -0,0 +1,200 @@
|
||||||
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
|
dofile(modpath.."/railtrack.lua")
|
||||||
|
|
||||||
|
railtrack:register_rail(":default:rail", {
|
||||||
|
description = "Rail",
|
||||||
|
tiles = {"default_rail.png", "default_rail_curved.png",
|
||||||
|
"default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||||
|
railtype = "rail",
|
||||||
|
})
|
||||||
|
|
||||||
|
railtrack:register_rail("railtrack:superrail", {
|
||||||
|
description = "Superconducting Rail",
|
||||||
|
tiles = {"carts_rail_sup.png", "carts_rail_curved_sup.png",
|
||||||
|
"carts_rail_t_junction_sup.png", "carts_rail_crossing_sup.png"},
|
||||||
|
railtype = "superrail",
|
||||||
|
acceleration = 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
railtrack:register_rail("railtrack:powerrail", {
|
||||||
|
description = "Powered Rail",
|
||||||
|
tiles = {"carts_rail_pwr.png", "carts_rail_curved_pwr.png",
|
||||||
|
"carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"},
|
||||||
|
railtype = "powerrail",
|
||||||
|
acceleration = 4,
|
||||||
|
mesecons = {
|
||||||
|
effector = {
|
||||||
|
action_on = function(pos, node)
|
||||||
|
railtrack:set_acceleration(pos, 4)
|
||||||
|
end,
|
||||||
|
action_off = function(pos, node)
|
||||||
|
railtrack:set_acceleration(pos, nil)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
railtrack:register_rail("railtrack:brakerail", {
|
||||||
|
description = "Braking Rail",
|
||||||
|
tiles = {"carts_rail_brk.png", "carts_rail_curved_brk.png",
|
||||||
|
"carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"},
|
||||||
|
railtype = "brakerail",
|
||||||
|
acceleration = -4,
|
||||||
|
mesecons = {
|
||||||
|
effector = {
|
||||||
|
action_on = function(pos, node)
|
||||||
|
railtrack:set_acceleration(pos, -4)
|
||||||
|
end,
|
||||||
|
action_off = function(pos, node)
|
||||||
|
railtrack:set_acceleration(pos, nil)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
railtrack:register_rail("railtrack:switchrail", {
|
||||||
|
description = "Switching Rail",
|
||||||
|
tiles = {"carts_rail_swt.png", "carts_rail_curved_swt.png",
|
||||||
|
"carts_rail_t_junction_swt.png", "carts_rail_crossing_swt.png"},
|
||||||
|
railtype = "switchrail",
|
||||||
|
acceleration = 0,
|
||||||
|
mesecons = {
|
||||||
|
effector = {
|
||||||
|
action_on = function(pos, node)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("rotations", "RFLB")
|
||||||
|
end,
|
||||||
|
action_off = function(pos, node)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("rotations", nil)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_privilege("rails", "Player can dig and place rails.")
|
||||||
|
|
||||||
|
minetest.register_tool("railtrack:fixer", {
|
||||||
|
description = "Rail Fixer",
|
||||||
|
inventory_image = "railtrack_fixer.png",
|
||||||
|
wield_image = "railtrack_fixer.png",
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
local pos = minetest.get_pointed_thing_position(pointed_thing, false)
|
||||||
|
local name = user:get_player_name()
|
||||||
|
if not pos or not name or pointed_thing.type ~= "node" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not railtrack:is_railnode(pos) then
|
||||||
|
minetest.chat_send_player(name, "Not a rail node!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not minetest.is_singleplayer() then
|
||||||
|
if not minetest.check_player_privs(name, {rails=true}) then
|
||||||
|
minetest.chat_send_player(name, "Requires rails privilege")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if node then
|
||||||
|
minetest.remove_node(pos)
|
||||||
|
minetest.set_node(pos, node)
|
||||||
|
local def = minetest.registered_items[node.name] or {}
|
||||||
|
local itemstack = ItemStack(node.name)
|
||||||
|
if type(def.after_place_node) == "function" then
|
||||||
|
def.after_place_node(pos, user, itemstack)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_tool("railtrack:inspector", {
|
||||||
|
description = "Rail Inspector",
|
||||||
|
inventory_image = "railtrack_inspector.png",
|
||||||
|
wield_image = "railtrack_inspector.png",
|
||||||
|
on_use = function(itemstack, user, pointed_thing)
|
||||||
|
local name = user:get_player_name()
|
||||||
|
local pos = minetest.get_pointed_thing_position(pointed_thing, false)
|
||||||
|
if not name or not pos then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local node = minetest.get_node(pos) or {}
|
||||||
|
if not railtrack:is_railnode(pos) or not node.name then
|
||||||
|
minetest.chat_send_player(name, "Not a rail node!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local ref = minetest.registered_items[node.name] or {}
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local form = ""
|
||||||
|
local size = 2.5
|
||||||
|
form = form.."label[0.5,0.5;POS: "..minetest.pos_to_string(pos).."]"
|
||||||
|
local railtype = ref.railtype or "NIL"
|
||||||
|
form = form.."label[0.5,1.0;RAILTYPE: "..railtype.."]"
|
||||||
|
local contype = meta:get_string("contype") or "NIL"
|
||||||
|
form = form.."label[0.5,1.5;CONTYPE: "..contype.."]"
|
||||||
|
local accel = meta:get_string("acceleration") or "NIL"
|
||||||
|
form = form.."label[0.5,2.0;ACCEL: "..accel.."]"
|
||||||
|
local s_junc = meta:get_string("junctions")
|
||||||
|
if s_junc then
|
||||||
|
local junctions = minetest.deserialize(s_junc)
|
||||||
|
if junctions then
|
||||||
|
form = form.."label[0.5,2.5;JUNCTIONS:]"
|
||||||
|
for i, p in ipairs(junctions) do
|
||||||
|
size = size + 0.5
|
||||||
|
form = form.."label[0.5,"..size..";#"..i.." "
|
||||||
|
..minetest.pos_to_string(p).."]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local s_cons = meta:get_string("connections")
|
||||||
|
if s_cons then
|
||||||
|
local cons = minetest.deserialize(s_cons)
|
||||||
|
if cons then
|
||||||
|
size = size + 0.5
|
||||||
|
form = form.."label[0.5,"..size..";CONNECTIONS:]"
|
||||||
|
for i, p in pairs(cons) do
|
||||||
|
size = size + 0.5
|
||||||
|
form = form.."label[0.5,"..size..";#"..i.." "
|
||||||
|
..minetest.pos_to_string(p).."]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local s_rots = meta:get_string("rotations")
|
||||||
|
if s_rots then
|
||||||
|
size = size + 0.5
|
||||||
|
form = form.."label[0.5,"..size..";ROTATIONS: "..s_rots.."]"
|
||||||
|
end
|
||||||
|
form = form.."button_exit[3.0,"..(size + 1)..";2,0.5;;Ok]"
|
||||||
|
form = "size[8,"..(size + 2).."]"..form
|
||||||
|
minetest.show_formspec(name, "info", form)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "railtrack:powerrail 2",
|
||||||
|
recipe = {
|
||||||
|
{"default:rail", "default:mese_crystal_fragment", "default:rail"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "railtrack:brakerail 2",
|
||||||
|
recipe = {
|
||||||
|
{"default:rail", "default:coal_lump", "default:rail"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "railtrack:switchrail 2",
|
||||||
|
recipe = {
|
||||||
|
{"default:rail", "default:mese", "default:rail"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "railtrack:superrail 2",
|
||||||
|
recipe = {
|
||||||
|
{"default:rail", "default:diamond", "default:rail"},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
local MAX_SECTION_LEN = 20
|
||||||
|
|
||||||
|
railtrack = {
|
||||||
|
rotations = "FLR",
|
||||||
|
accel_flat = -0.5,
|
||||||
|
accel_up = -2,
|
||||||
|
accel_down = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
railtrack.default_rail = {
|
||||||
|
description = "Rail",
|
||||||
|
drawtype = "raillike",
|
||||||
|
tiles = {"default_rail.png", "default_rail_curved.png",
|
||||||
|
"default_rail_t_junction.png", "default_rail_crossing.png"},
|
||||||
|
paramtype = "light",
|
||||||
|
sunlight_propagates = true,
|
||||||
|
walkable = false,
|
||||||
|
is_ground_content = false,
|
||||||
|
selection_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
|
||||||
|
},
|
||||||
|
groups = {bendy = 2, dig_immediate = 2, attached_node = 1,
|
||||||
|
connect_to_raillike = minetest.raillike_group("rail")},
|
||||||
|
railtype = "rail",
|
||||||
|
after_place_node = function(pos, placer, itemstack)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local def = itemstack:get_definition() or {}
|
||||||
|
if def.acceleration then
|
||||||
|
meta:set_string("acceleration", def.acceleration)
|
||||||
|
end
|
||||||
|
local junc = {}
|
||||||
|
local contype = meta:get_string("contype") or ""
|
||||||
|
local s_cons = meta:get_string("connections") or ""
|
||||||
|
if contype == "section" then
|
||||||
|
railtrack:limit_section_len(placer, pos, meta)
|
||||||
|
elseif s_cons ~= "" then
|
||||||
|
local cons = minetest.deserialize(s_cons)
|
||||||
|
for _, con in pairs(cons) do
|
||||||
|
if railtrack:limit_section_len(placer, con) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_construct = function(pos)
|
||||||
|
railtrack:update_rails(pos)
|
||||||
|
end,
|
||||||
|
after_destruct = function(pos, oldnode)
|
||||||
|
local cons = railtrack:get_connections(pos)
|
||||||
|
for _, p in pairs(cons) do
|
||||||
|
railtrack:update_rails(p)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
function railtrack:copy(t)
|
||||||
|
if type(t) ~= "table" then
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
local copy = {}
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
copy[k] = v
|
||||||
|
end
|
||||||
|
return copy
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:register_rail(name, def)
|
||||||
|
local udef = {}
|
||||||
|
for k, v in pairs(railtrack.default_rail) do
|
||||||
|
if not def[k] then
|
||||||
|
def[k] = railtrack:copy(v)
|
||||||
|
end
|
||||||
|
udef[k] = railtrack:copy(def[k])
|
||||||
|
end
|
||||||
|
def.inventory_image = def.inventory_image or def.tiles[1]
|
||||||
|
def.wield_image = def.wield_image or def.tiles[1]
|
||||||
|
minetest.register_node(name, def)
|
||||||
|
udef.drop = name
|
||||||
|
udef.railtype = udef.railtype.."_union"
|
||||||
|
udef.groups.not_in_creative_inventory=1
|
||||||
|
minetest.register_node(name.."_union", udef)
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:limit_section_len(player, pos, meta)
|
||||||
|
meta = meta or minetest.get_meta(pos)
|
||||||
|
local contype = meta:get_string("contype") or ""
|
||||||
|
if contype == "section" then
|
||||||
|
local s_junc = meta:get_string("junctions") or ""
|
||||||
|
if s_junc ~= "" then
|
||||||
|
local junc = minetest.deserialize(s_junc)
|
||||||
|
if #junc == 2 then
|
||||||
|
local dist = railtrack:get_distance(junc[1], junc[2])
|
||||||
|
if dist > MAX_SECTION_LEN then
|
||||||
|
local node = minetest.get_node(pos) or {}
|
||||||
|
if node.name then
|
||||||
|
minetest.swap_node(pos, {name=node.name.."_union"})
|
||||||
|
railtrack:update_rails(pos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:is_railnode(pos)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if node then
|
||||||
|
return minetest.get_item_group(node.name, "connect_to_raillike") > 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_sign(z)
|
||||||
|
if z == 0 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return z / math.abs(z)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_rotations(s_rots, dir)
|
||||||
|
local rots = {}
|
||||||
|
for i = 1, string.len(s_rots) do
|
||||||
|
local r = string.sub(s_rots, i, i)
|
||||||
|
local rot = nil
|
||||||
|
if r == "F" then
|
||||||
|
rot = {x=dir.x, z=dir.z}
|
||||||
|
elseif r == "L" then
|
||||||
|
rot = {x=-dir.z, z=dir.x}
|
||||||
|
elseif r == "R" then
|
||||||
|
rot = {x=dir.z, z=-dir.x}
|
||||||
|
elseif r == "B" then
|
||||||
|
rot = {x=-dir.x, z=-dir.z}
|
||||||
|
end
|
||||||
|
if rot then
|
||||||
|
table.insert(rots, rot)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return rots
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_acceleration(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local accel = meta:get_string("acceleration") or ""
|
||||||
|
if accel ~= "" then
|
||||||
|
return tonumber(accel)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_direction(p1, p2)
|
||||||
|
local v = vector.subtract(p1, p2)
|
||||||
|
return {
|
||||||
|
x = railtrack:get_sign(v.x),
|
||||||
|
y = railtrack:get_sign(v.y),
|
||||||
|
z = railtrack:get_sign(v.z),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_distance(p1, p2)
|
||||||
|
local dx = p1.x - p2.x
|
||||||
|
local dz = p1.z - p2.z
|
||||||
|
return math.abs(dx) + math.abs(dz)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function railtrack:get_railtype(pos)
|
||||||
|
local node = minetest.get_node(pos) or {}
|
||||||
|
if node.name then
|
||||||
|
local ref = minetest.registered_items[node.name] or {}
|
||||||
|
return ref.railtype
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_connection_type(pos, cons)
|
||||||
|
local railtype = railtrack:get_railtype(pos)
|
||||||
|
if #cons == 0 then
|
||||||
|
return "single"
|
||||||
|
elseif #cons == 1 then
|
||||||
|
return "junction"
|
||||||
|
elseif #cons == 2 then
|
||||||
|
if cons[1].x == cons[2].x or cons[1].z == cons[2].z then
|
||||||
|
if (cons[1].y == cons[2].y and cons[1].y == pos.y) or
|
||||||
|
(math.abs(cons[1].y - cons[2].y) == 2) then
|
||||||
|
if railtype == railtrack:get_railtype(cons[1]) and
|
||||||
|
railtype == railtrack:get_railtype(cons[2]) then
|
||||||
|
return "section"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return "junction"
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_connections(pos)
|
||||||
|
local connections = {}
|
||||||
|
for y = 1, -1, -1 do
|
||||||
|
for x = -1, 1 do
|
||||||
|
for z = -1, 1 do
|
||||||
|
if math.abs(x) ~= math.abs(z) then
|
||||||
|
local p = vector.add(pos, {x=x, y=y, z=z})
|
||||||
|
if railtrack:is_railnode(p) then
|
||||||
|
table.insert(connections, p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return connections
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:get_junctions(pos, last_pos, junctions)
|
||||||
|
junctions = junctions or {}
|
||||||
|
local cons = railtrack:get_connections(pos)
|
||||||
|
local contype = railtrack:get_connection_type(pos, cons)
|
||||||
|
if contype == "junction" then
|
||||||
|
table.insert(junctions, pos)
|
||||||
|
elseif contype == "section" then
|
||||||
|
if last_pos then
|
||||||
|
for i, p in pairs(cons) do
|
||||||
|
if vector.equals(p, last_pos) then
|
||||||
|
cons[i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, p in pairs(cons) do
|
||||||
|
railtrack:get_junctions(p, pos, junctions)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return junctions
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:set_acceleration(pos, accel)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local contype = meta:get_string("contype")
|
||||||
|
if contype == "section" then
|
||||||
|
local s_junc = meta:get_string("junctions") or ""
|
||||||
|
local junc = minetest.deserialize(s_junc) or {}
|
||||||
|
if #junc == 2 then
|
||||||
|
local p = vector.new(junc[2])
|
||||||
|
local dir = railtrack:get_direction(junc[1], junc[2])
|
||||||
|
local dist = railtrack:get_distance(junc[1], junc[2])
|
||||||
|
for i = 0, dist do
|
||||||
|
local m = minetest.get_meta(p)
|
||||||
|
if m then
|
||||||
|
m:set_string("acceleration", tostring(accel))
|
||||||
|
end
|
||||||
|
p = vector.add(dir, p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
meta:set_string("acceleration", tostring(accel))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function railtrack:update_rails(pos, last_pos, level)
|
||||||
|
local connections = {}
|
||||||
|
local junctions = {}
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local cons = railtrack:get_connections(pos)
|
||||||
|
local contype = railtrack:get_connection_type(pos, cons)
|
||||||
|
level = level or 0
|
||||||
|
for i, p in pairs(cons) do
|
||||||
|
connections[i] = p
|
||||||
|
end
|
||||||
|
if contype == "junction" then
|
||||||
|
level = level + 1
|
||||||
|
end
|
||||||
|
if contype == "section" or level < 2 then
|
||||||
|
if last_pos then
|
||||||
|
for i, p in pairs(cons) do
|
||||||
|
if vector.equals(p, last_pos) then
|
||||||
|
cons[i] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, p in pairs(cons) do
|
||||||
|
railtrack:update_rails(p, pos, level)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if contype == "section" then
|
||||||
|
junctions = railtrack:get_junctions(pos)
|
||||||
|
connections = {}
|
||||||
|
end
|
||||||
|
meta:set_string("connections", minetest.serialize(connections))
|
||||||
|
meta:set_string("junctions", minetest.serialize(junctions))
|
||||||
|
meta:set_string("contype", contype)
|
||||||
|
end
|
||||||
|
|
After Width: | Height: | Size: 437 B |
After Width: | Height: | Size: 385 B |
Before Width: | Height: | Size: 392 B After Width: | Height: | Size: 392 B |
After Width: | Height: | Size: 392 B |
After Width: | Height: | Size: 378 B |
After Width: | Height: | Size: 376 B |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 381 B |
After Width: | Height: | Size: 381 B |
After Width: | Height: | Size: 379 B |
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 437 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 383 B |
After Width: | Height: | Size: 383 B |