1
0
mirror of https://github.com/sys4-fr/server-nalc.git synced 2024-11-05 10:00:26 +01:00
server-nalc/mods/carts/init.lua
YouniS Bensalah 392af4281f Carts mod patch. Fix #366
Hack that makes sure cart doesn't leave rails and hangs in the air.
This patch now seems to fix that.
(thx for testing with me @fabienwang)
2016-01-06 06:13:08 +01:00

904 lines
30 KiB
Lua
Executable File

dofile(minetest.get_modpath("carts").."/functions.lua")
local cart = {
physical = true, -- Set to false to not make carts collide with other entities such as carts or the player.
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"}, -- Set to "invisible.png" to make the cart invisible, which is sometimes useful for videos and custom maps.
driver = nil,
velocity = {x=0, y=0, z=0},
old_pos = nil,
old_velocity = nil,
pre_stop_dir = nil,
MAX_V = 9.6, -- Limit of the velocity (speed).
TARGET_TOUR_V = 6, -- Target touring velocity, currently unused.
railcount = 0,
ignorekeypos = nil,
lockyaw = false, -- Set to true to lock camera by default. If set to false, player has to press the "jump" key to lock camera.
yawtarget = nil,
YAW_STEP = math.pi/64 -- Larger YAW_STEP makes for slower camera turning.
}
function cart:on_rightclick(clicker)
if not clicker or not clicker:is_player() then
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
function cart:on_activate(staticdata, dtime_s)
self.object:set_armor_groups({immortal=1})
if staticdata then
local tmp = minetest.deserialize(staticdata)
if tmp then
self.velocity = tmp.velocity
end
if tmp and tmp.pre_stop_dir then
self.pre_stop_dir = tmp.pre_stop_dir
end
end
self.old_pos = self.object:getpos()
self.old_velocity = self.velocity
end
function cart:get_staticdata()
return minetest.serialize({
velocity = self.velocity,
pre_stop_dir = self.pre_stop_dir,
})
end
-- Remove the cart if holding a tool or accelerate it
function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
if not puncher or not puncher:is_player() then
return
end
if puncher:get_player_control().sneak then
minetest.log("action", "carts:cart removed at " .. pos_to_string(vector.round(self.object:getpos())) .. ", " .. self.railcount .. " rails travelled.")
self.object:remove()
local inv = puncher:get_inventory()
if minetest.setting_getbool("creative_mode") then
if not inv:contains_item("main", "carts:cart") then
inv:add_item("main", "carts:cart")
end
else
inv:add_item("main", "carts:cart")
end
return
end
if puncher == self.driver and (math.abs(self.velocity.x)>1 or math.abs(self.velocity.z)>1) then
return
end
local d = cart_func:velocity_to_dir(direction)
if d.x==0 and d.z==0 then
local fd = minetest.dir_to_facedir(puncher:get_look_dir())
if fd == 0 then
d.x = 1
elseif fd == 1 then
d.z = -1
elseif fd == 2 then
d.x = -1
elseif fd == 3 then
d.z = 1
end
end
local s = self.velocity
if time_from_last_punch > tool_capabilities.full_punch_interval then
time_from_last_punch = tool_capabilities.full_punch_interval
end
local f = 4*(time_from_last_punch/tool_capabilities.full_punch_interval)
local v = {x=s.x+d.x*f, y=s.y, z=s.z+d.z*f}
if math.abs(v.x) < 6 and math.abs(v.z) < 6 then
self.velocity = v
else
if math.abs(self.velocity.x) < 6 and math.abs(v.x) >= 6 then
self.velocity.x = 6*cart_func:get_sign(self.velocity.x)
end
if math.abs(self.velocity.z) < 6 and math.abs(v.z) >= 6 then
self.velocity.z = 6*cart_func:get_sign(self.velocity.z)
end
end
end
-- Returns the direction as a unit vector
function cart:get_rail_direction(pos, dir)
--minetest.log("action", "get_rail_direction top pos="..pos_to_string(pos).." dir="..pos_to_string(dir))
local fwd=cart_func.v3:copy(dir)
fwd.y=0
local up=cart_func.v3:copy(dir)
up.y=1
local down=cart_func.v3:copy(dir)
down.y=-1
-- figure out 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 --left is opposite sign from z
right.x=dir.z --right is same sign as z
elseif dir.x ~= 0 and dir.z == 0 then
left.z=dir.x --left is same sign as x
right.z=-dir.x --right is opposite sign from x
end --left and right
local leftdown=cart_func.v3:copy(left)
leftdown.y=-1
local rightdown=cart_func.v3:copy(right)
rightdown.y=-1
--minetest.log("action", " fwd="..pos_to_string(fwd))
--minetest.log("action", " down="..pos_to_string(down))
--minetest.log("action", " up="..pos_to_string(up))
--minetest.log("action", " left="..pos_to_string(left))
--minetest.log("action", " leftdown="..pos_to_string(leftdown))
--minetest.log("action", " right="..pos_to_string(right))
--minetest.log("action", " rightdown="..pos_to_string(rightdown))
local ignorekeys=false
--ignorekeypos stores a position where we changed direction because the
--player was pressing left or right keys. once we have changed direction,
--we want to ignore those keys until you have changed to a different rail
--(otherwise you end up reversing)
--I use the ignorekeys boolean to make the key logic more readable
if self.ignorekeypos then --ignorekeypos was set
if cart_func.v3:equal(self.ignorekeypos,pos) then
ignorekeys=true --if still at same position, ignore left and right keys
else
self.ignorekeypos=nil --if ignorekeypos was set but pos does not match anymore, clear it
end
end
local ctrl=nil
if self.driver and not ignorekeys then
ctrl = self.driver:get_player_control()
end
if ctrl and ctrl.left then --left key pressed, check left first
if cart_func:check_rail_in_direction(pos,left) then
self.ignorekeypos=cart_func.v3:copy(pos) --ignore keys until pos changes
return left
elseif cart_func:check_rail_in_direction(pos,leftdown) then
self.ignorekeypos=cart_func.v3:copy(pos)
return leftdown
end
elseif ctrl and ctrl.right then --right key pressed, check right first
if cart_func:check_rail_in_direction(pos,right) then
self.ignorekeypos=cart_func.v3:copy(pos)
return right
elseif cart_func:check_rail_in_direction(pos,rightdown) then
self.ignorekeypos=cart_func.v3:copy(pos)
return rightdown
end
end --ctrl.left ctrl.right
--now for normal checks
if cart_func:check_rail_in_direction(pos,fwd) then
return fwd
elseif cart_func:check_rail_in_direction(pos,down) then
return down
elseif cart_func:check_rail_in_direction(pos,up) then
return up
elseif (not ctrl or not ctrl.left) --only check left if we didnt above
and cart_func:check_rail_in_direction(pos,left) then
return left
elseif (not ctrl or not ctrl.left)
and cart_func:check_rail_in_direction(pos,leftdown) then
return leftdown
elseif (not ctrl or not ctrl.right) --only check right if we didnt above
and cart_func:check_rail_in_direction(pos,right) then
return right
elseif (not ctrl or not ctrl.right)
and cart_func:check_rail_in_direction(pos,rightdown) then
return rightdown
else
return {x=0, y=0, z=0}
end --normal rail checks
end --get_rail_direction
function cart:calc_rail_direction(pos, vel)
local velocity = cart_func.v3:copy(vel)
local p = cart_func.v3:copy(pos)
if cart_func:is_int(p.x) and cart_func:is_int(p.z) then
local dir = cart_func:velocity_to_dir(velocity)
local dir_old = cart_func.v3:copy(dir)
dir = self:get_rail_direction(cart_func.v3:round(p), dir)
local v = math.max(math.abs(velocity.x), math.abs(velocity.z))
velocity = {
x = v * dir.x,
y = v * dir.y,
z = v * dir.z,
}
if cart_func.v3:equal(velocity, {x=0, y=0, z=0}) and not cart_func:is_rail(p) then
-- First try this HACK
-- Move the cart on the rail if above or under it
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=1, z=0})) and vel.y >= 0 then
p = cart_func.v3:add(p, {x=0, y=1, z=0})
return self:calc_rail_direction(p, vel)
end
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-1, z=0})) and vel.y <= 0 then
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
return self:calc_rail_direction(p, vel)
end
-- Now the HACK gets really dirty
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=2, z=0})) and vel.y >= 0 then
p = cart_func.v3:add(p, {x=0, y=1, z=0})
return self:calc_rail_direction(p, vel)
end
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-2, z=0})) and vel.y <= 0 then
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
return self:calc_rail_direction(p, vel)
end
-- NOW the hack gets even dirtier
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=3, z=0})) and vel.y >= 0 then
p = cart_func.v3:add(p, {x=0, y=1, z=0})
return self:calc_rail_direction(p, vel)
end
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-3, z=0})) and vel.y <= 0 then
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
return self:calc_rail_direction(p, vel)
end
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=4, z=0})) and vel.y >= 0 then
p = cart_func.v3:add(p, {x=0, y=1, z=0})
return self:calc_rail_direction(p, vel)
end
if cart_func:is_rail(cart_func.v3:add(p, {x=0, y=-4, z=0})) and vel.y <= 0 then
p = cart_func.v3:add(p, {x=0, y=-1, z=0})
return self:calc_rail_direction(p, vel)
end
return {x=0, y=0, z=0}, p
end
if not cart_func.v3:equal(dir, dir_old) then
return velocity, cart_func.v3:round(p)
end
end
return velocity, p
end
-- built in pos_to_string doesn't handle nil.
function pos_to_string(pos)
if pos==nil then return "(nil)"
else return minetest.pos_to_string(pos)
end --poss==nil
end --pos_to_string
function cart:on_step(dtime)
local pos = self.object:getpos()
local dir = cart_func:velocity_to_dir(self.velocity)
-- *!* Debug.
if self.old_pos then
local cmp_old=vector.round(self.old_pos)
local cmp_new=vector.round(pos)
if cmp_old.x~=cmp_new.x or cmp_old.y~=cmp_new.y or cmp_old.z~=cmp_new.z then
self.railcount=self.railcount+1
-- local a = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
-- local railtype=""
-- if a and a>0 then railtype="power" end
-- minetest.chat_send_all("-- cart pos="..pos_to_string(vector.round(pos)).." railcount="..self.railcount.." vel="..pos_to_string(self.velocity).." "..railtype) --*!*debug
end
end
-- *!* Debug.
local ctrl=nil
if self.driver then
ctrl = self.driver:get_player_control()
if ctrl and ctrl.jump and not self.lockyaw then
self.lockyaw=true
self.yawtarget=self.object:getyaw()
-- minetest.chat_send_player(self.driver:get_player_name(),"Player view locked to cart, sneak to unlock.")
elseif ctrl and ctrl.sneak and self.lockyaw then
self.lockyaw=false
-- minetest.chat_send_player(self.driver:get_player_name(),"Player view unlocked from cart, jump to lock.")
end
end -- Check lockyaw if self.driver.
if not cart_func.v3:equal(self.velocity, {x=0,y=0,z=0}) then
self.pre_stop_dir = cart_func:velocity_to_dir(self.velocity)
end
-- Stop the cart if the velocity is nearly 0, only if on a flat railway.
if dir.y == 0 then
if math.abs(self.velocity.x) < 0.1 and math.abs(self.velocity.z) < 0.1 then
-- Start the cart if powered from mesecons.
local a = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
if a and a ~= 0 then
if self.pre_stop_dir and cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), self.pre_stop_dir), self.pre_stop_dir) then
self.velocity = {
x = self.pre_stop_dir.x * 0.2,
y = self.pre_stop_dir.y * 0.2,
z = self.pre_stop_dir.z * 0.2,
}
self.old_velocity = self.velocity
return
end
for _,y in ipairs({0,-1,1}) do
for _,z in ipairs({1,-1}) do
if cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), {x=0, y=y, z=z}), {x=0, y=y, z=z}) then
self.velocity = {
x = 0,
y = 0.2*y,
z = 0.2*z,
}
self.old_velocity = self.velocity
return
end
end
for _,x in ipairs({1,-1}) do
if cart_func.v3:equal(self:get_rail_direction(self.object:getpos(), {x=x, y=y, z=0}), {x=x, y=y, z=0}) then
self.velocity = {
x = 0.2*x,
y = 0.2*y,
z = 0,
}
self.old_velocity = self.velocity
return
end
end
end
end
self.velocity = {x=0, y=0, z=0}
self.object:setvelocity(self.velocity)
self.old_velocity = self.velocity
self.old_pos = self.object:getpos()
return
end
end
--
-- Set the new moving direction
--
-- Recalcualte the rails that are passed since the last server step
local old_dir = cart_func:velocity_to_dir(self.old_velocity)
if old_dir.x ~= 0 then
local sign = cart_func:get_sign(pos.x-self.old_pos.x)
while true do
if sign ~= cart_func:get_sign(pos.x-self.old_pos.x) or pos.x == self.old_pos.x then
break
end
self.old_pos.x = self.old_pos.x + cart_func:get_sign(pos.x-self.old_pos.x)*0.1
self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.x-self.old_pos.x)*0.1*old_dir.y
self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
old_dir = cart_func:velocity_to_dir(self.old_velocity)
if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
self.velocity = self.old_velocity
pos = self.old_pos
self.object:setpos(self.old_pos)
break
end
end
elseif old_dir.z ~= 0 then
local sign = cart_func:get_sign(pos.z-self.old_pos.z)
while true do
if sign ~= cart_func:get_sign(pos.z-self.old_pos.z) or pos.z == self.old_pos.z then
break
end
self.old_pos.z = self.old_pos.z + cart_func:get_sign(pos.z-self.old_pos.z)*0.1
self.old_pos.y = self.old_pos.y + cart_func:get_sign(pos.z-self.old_pos.z)*0.1*old_dir.y
self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
old_dir = cart_func:velocity_to_dir(self.old_velocity)
if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
self.velocity = self.old_velocity
pos = self.old_pos
self.object:setpos(self.old_pos)
break
end
end
end
-- Calculate the new step
self.velocity, pos = self:calc_rail_direction(pos, self.velocity)
self.object:setpos(pos)
dir = cart_func:velocity_to_dir(self.velocity)
-- Accelerate or decelerate the cart according to the pitch and acceleration of the rail node
local a = tonumber(minetest.get_meta(pos):get_string("cart_acceleration"))
if not a then
a = 0
end
local t = tonumber(minetest.get_meta(pos):get_string("cart_touring_velocity"))
if not t then t=0 end
if t>0 then
local vx=math.abs(self.velocity.x)
local vy=math.abs(self.velocity.y)
local vz=math.abs(self.velocity.z)
-- make v the largest of the 3 velocities
local v=vx
if vy>v then v=vy end
if vz>v then v=vz end
--
local diff=0
local acelordecl=0
if v>t then
diff=v-t
acelordecl=-1
elseif v<t then
diff=t-v
acelordecl=1
end --v>t
--minetest.log("action", " on_step t1 v="..v.." t="..t.." diff="..diff.." a="..a.." acelordecl="..acelordecl)
--adjust for grav
if self.velocity.y<0 then --going downhill so grav will acel by extra 0.13
--if we are decel then add an extra 0.13 to how much we need to decel
--if we are accel then subtract an extra 0.13 from how much we need to acel
diff=diff-(0.13*acelordecl)
elseif self.velocity.y>0 then --going uphill grav will decl by extra 0.10
--if we are decel then subtract 0.1 from how much we need to decel
--if we are acel then add 0.1 to how much we need to acel
diff=diff+(0.1*acelordecl)
end -- self.velocity.y<0
--so now diff is the difference between cart velocity (after this turns grav)
--and our target touring velocity
--minetest.log("action", "*!* on_step t2 grav v="..v.." diff="..diff.." a="..a)
if diff<a then --we dont want to over acel or decel
a=diff
elseif diff>a*4 then
a=a*2 --if big difference, play catchup fast!
elseif diff>a*3 then
a=a*1.5 --if big difference, play catchup fast!
end --diff<a
a=a*acelordecl
end -- if t>0
-- Check if down arrow is being pressed (handbrake).
if self.driver then
local ctrl = self.driver:get_player_control()
if ctrl and ctrl.down then
a=a-0.1 -- Same as uphill.
end -- If handbrake.
end -- If self.driver.
if self.velocity.y < 0 then
self.velocity = {
x = self.velocity.x + (a+0.13)*cart_func:get_sign(self.velocity.x),
y = self.velocity.y + (a+0.13)*cart_func:get_sign(self.velocity.y),
z = self.velocity.z + (a+0.13)*cart_func:get_sign(self.velocity.z),
}
elseif self.velocity.y > 0 then
self.velocity = {
x = self.velocity.x + (a-0.1)*cart_func:get_sign(self.velocity.x),
y = self.velocity.y + (a-0.1)*cart_func:get_sign(self.velocity.y),
z = self.velocity.z + (a-0.1)*cart_func:get_sign(self.velocity.z),
}
else
self.velocity = {
x = self.velocity.x + (a-0.03)*cart_func:get_sign(self.velocity.x),
y = self.velocity.y + (a-0.03)*cart_func:get_sign(self.velocity.y),
z = self.velocity.z + (a-0.03)*cart_func:get_sign(self.velocity.z),
}
-- Place the cart exactly on top of the rail
if cart_func:is_rail(cart_func.v3:round(pos)) then
self.object:setpos({x=pos.x, y=math.floor(pos.y+0.5), z=pos.z})
pos = self.object:getpos()
end
end
-- Dont switch moving direction
-- Only if on flat railway
if dir.y == 0 then
if cart_func:get_sign(dir.x) ~= cart_func:get_sign(self.velocity.x) then
self.velocity.x = 0
end
if cart_func:get_sign(dir.y) ~= cart_func:get_sign(self.velocity.y) then
self.velocity.y = 0
end
if cart_func:get_sign(dir.z) ~= cart_func:get_sign(self.velocity.z) then
self.velocity.z = 0
end
end
-- Allow only one moving direction (multiply the other one with 0)
dir = cart_func:velocity_to_dir(self.velocity)
self.velocity = {
x = math.abs(self.velocity.x) * dir.x,
y = self.velocity.y,
z = math.abs(self.velocity.z) * dir.z,
}
-- Move cart exactly on the rail
if dir.x ~= 0 and not cart_func:is_int(pos.z) then
pos.z = math.floor(0.5+pos.z)
self.object:setpos(pos)
elseif dir.z ~= 0 and not cart_func:is_int(pos.x) then
pos.x = math.floor(0.5+pos.x)
self.object:setpos(pos)
end
-- Limit the velocity.
if math.abs(self.velocity.x) > self.MAX_V then
self.velocity.x = self.MAX_V*cart_func:get_sign(self.velocity.x)
end
if math.abs(self.velocity.y) > self.MAX_V then
self.velocity.y = self.MAX_V*cart_func:get_sign(self.velocity.y)
end
if math.abs(self.velocity.z) > self.MAX_V then
self.velocity.z = self.MAX_V*cart_func:get_sign(self.velocity.z)
end
self.object:setvelocity(self.velocity)
self.old_pos = self.object:getpos()
self.old_velocity = cart_func.v3:copy(self.velocity)
local oldyaw=self.object:getyaw()
if dir.x < 0 then
self.object:setyaw(math.pi/2)
elseif dir.x > 0 then
self.object:setyaw(3*math.pi/2)
elseif dir.z < 0 then
self.object:setyaw(math.pi)
elseif dir.z > 0 then
self.object:setyaw(0)
end
local newyaw=self.object:getyaw()
-- Now if driver and lockyaw, change drivers direction.
if self.driver and self.lockyaw then
if oldyaw~=newyaw then
self.yawtarget=newyaw -- Set new target.
-- minetest.log("action", "--Cart yawtarget set "..self.yawtarget)
end
if self.driver:get_look_yaw() == nil then
return
end
local playeryaw=self.driver:get_look_yaw()-1.57
if playeryaw<0 then playeryaw=playeryaw+(math.pi*2) end
if self.yawtarget and playeryaw ~= self.yawtarget then
local diff = self.yawtarget - playeryaw
if diff>math.pi then
diff=diff-(2*math.pi)
elseif diff<(-math.pi) then
diff=diff+(2*math.pi)
end
local yawdir=cart_func:get_sign(diff)
local step=self.YAW_STEP
if math.abs(diff)<=self.YAW_STEP then
step=diff
self.yawtarget=nil
end
local setyaw=playeryaw+(step*yawdir)
self.driver:set_look_yaw(setyaw)
end -- Move yaw.
end -- lockyaw set.
if dir.y == -1 then
self.object:set_animation({x=1, y=1}, 1, 0)
elseif dir.y == 1 then
self.object:set_animation({x=2, y=2}, 1, 0)
else
self.object:set_animation({x=0, y=0}, 1, 0)
end
end
minetest.register_entity("carts: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 cart_func:is_rail(pointed_thing.under) then
local obj=minetest.add_entity(pointed_thing.under, "carts:cart")
minetest.log("action", "carts:cart placed at " .. pos_to_string(vector.round(obj:getpos())) .. ".")
-- minetest.chat_send_player(placer:get_player_name(),"Right click to ride, left click to push, sneak + left click to put back in inventory, jump to lock view to cart, sneak to unlock view from cart, move left and right to switch tracks, move backwards to apply handbrake.")
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
elseif cart_func:is_rail(pointed_thing.above) then
minetest.add_entity(pointed_thing.above, "carts:cart")
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
end
end,
})
minetest.register_craft({
output = "carts:cart",
recipe = {
{"default:steel_ingot", "", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
})
--
-- Mesecon support
--
minetest.register_node(":default: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 = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
mesecons = {
effector = {
action_off = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
end,
action_on = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})
minetest.register_node("carts:rail_copper", {
description = "Copper Rail",
drawtype = "raillike",
tiles = {"carts_rail_copper.png", "carts_rail_copper_curved.png", "carts_rail_copper_t_junction.png", "carts_rail_copper_crossing.png"},
inventory_image = "carts_rail_copper.png",
wield_image = "carts_rail_copper.png",
paramtype = "light",
sunlight_propagates = true,
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
})
minetest.register_node("carts:rail_invisible", {
description = "Invisible Rail",
stack_max = 10000,
range = 12,
drawtype = "raillike",
tiles = {"invisible.png", "invisible.png", "invisible.png", "invisible.png"},
inventory_image = "default_rail.png^default_steel_ingot.png",
wield_image = "default_rail.png^default_steel_ingot.png",
paramtype = "light",
sunlight_propagates = true,
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
drop = "",
groups = {unbreakable = 1, rail = 1, connect_to_raillike = 1, not_in_creative_inventory = 1},
})
minetest.register_node("carts:rail_power", {
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 = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
after_place_node = function(pos, placer, itemstack)
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
end,
mesecons = {
effector = {
action_off = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
end,
action_on = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})
minetest.register_node("carts:rail_power_invisible", {
description = "Invisible Powered Rail",
stack_max = 10000,
range = 12,
drawtype = "raillike",
tiles = {"invisible.png", "invisible.png", "invisible.png", "invisible.png"},
inventory_image = "default_rail.png^default_mese_crystal_fragment.png",
wield_image = "default_rail.png^default_mese_crystal_fragment.png",
paramtype = "light",
sunlight_propagates = true,
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
drop = "",
groups = {unbreakable = 1, rail = 1, connect_to_raillike = 1, not_in_creative_inventory = 1},
after_place_node = function(pos, placer, itemstack)
minetest.get_meta(pos):set_string("cart_acceleration", "10")
minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
end,
})
minetest.register_node("carts:rail_brake", {
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 = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1},
after_place_node = function(pos, placer, itemstack)
minetest.get_meta(pos):set_string("cart_acceleration", "-0.2")
minetest.get_meta(pos):set_string("cart_touring_velocity", cart.TARGET_TOUR_V)
end,
mesecons = {
effector = {
action_off = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "-0.2")
end,
action_on = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})
minetest.register_node("carts:rail_brake_invisible", {
description = "Invisible Brake Rail",
stack_max = 10000,
range = 12,
drawtype = "raillike",
tiles = {"invisible.png", "invisible.png", "invisible.png", "invisible.png"},
inventory_image = "default_rail.png^default_coal_lump.png",
wield_image = "default_rail.png^default_coal_lump.png",
paramtype = "light",
sunlight_propagates = true,
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
drop = "",
groups = {bendy = 2, snappy = 1, dig_immediate = 2, rail = 1, connect_to_raillike = 1, not_in_creative_inventory = 1},
after_place_node = function(pos, placer, itemstack)
minetest.get_meta(pos):set_string("cart_acceleration", "-10")
minetest.get_meta(pos):set_string("cart_touring_velocity", cart:get_staticdata().velocity)
end,
})
--[[
minetest.register_node("carts:rail_tour", {
description = "Touring Rail",
drawtype = "raillike",
tiles = {"carts_rail_tour.png", "carts_rail_curved_tour.png", "carts_rail_t_junction_tour.png", "carts_rail_crossing_tour.png"},
inventory_image = "carts_rail_tour.png",
wield_image = "carts_rail_tour.png",
paramtype = "light",
sunlight_propagates = true,
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy = 2, snappy = 1, dig_immediate = 2, 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")
minetest.get_meta(pos):set_string("cart_touring_velocity", cart.TARGET_TOUR_V)
end
end,
mesecons = {
effector = {
action_on = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0.5")
end,
action_off = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})
--]]
minetest.register_craft({
output = "carts:rail_copper 16",
recipe = {
{"default:copper_ingot", "group:stick", "default:copper_ingot"},
{"default:copper_ingot", "group:stick", "default:copper_ingot"},
{"default:copper_ingot", "group:stick", "default:copper_ingot"},
}
})
minetest.register_craft({
type = "shapeless",
output = "carts:rail_power",
recipe = {"group:rail", "default:mese_crystal_fragment"},
})
minetest.register_craft({
type = "shapeless",
output = "carts:rail_brake",
recipe = {"group:rail", "default:coal_lump"},
})
minetest.register_craft({
type = "shapeless",
output = "carts:rail_tour",
recipe = {"group:rail", "default:clay_lump"},
})
minetest.register_alias("carts:powerrail", "carts:rail_power")
minetest.register_alias("carts:power_rail", "carts:rail_power")
minetest.register_alias("carts:brakerail", "carts:rail_brake")
minetest.register_alias("carts:brake_rail", "carts:rail_power")
minetest.register_alias("carts:tourrail", "carts:rail_tour")
if minetest.setting_getbool("log_mods") then
minetest.log("action", "Carbone: [carts] loaded.")
end
-- temporary
minetest.register_abm({
nodes = {"group:rail"},
func = function(pos)
local name = minetest.get_node(pos).name
minetest.remove_node(pos)
minetest.place_node(pos,{name = name})
end
})