All-in-one patch (see ext description)

* Removed PilzAdam's carts
* Replaced by SmallJoker's Boost_cart
(https://github.com/SmallJoker/boost_cart)
* Modified to fully replace carts
* Modified for MFF :
- desactivate mesecons
- power_rail: accelerate, max_speed set in init.lua
- brake_rail: deccelerate, min_speed set in init.lua (so the cart
doesn't stop and runs at very low speed)
- default:rail / rail_cooper : no friction, keep the current speed
- no collision (avoid the "walled_in" bug)
This commit is contained in:
Coethium 2016-08-08 15:01:43 +02:00
parent dbe81d676e
commit a6afae440f
45 changed files with 746 additions and 907 deletions

34
mods/carts/README.txt Executable file → Normal file
View File

@ -1,17 +1,20 @@
Minetest 0.4 mod: carts
=======================
by PilzAdam
This version is modified by Kilarin (Donald Hines), all changes CC-0
modifications include:
New Controls:LEFT or RIGHT to switch track at junction
DOWN for hand break
JUMP lock the users view to the view of the cart
SNEAK unlock the users view from the cart
Touring Rails: Try to maintain a speed of 4.5
Chat notification of controls when cart is placed
Track rail count in debug.txt
punch by driver patch from spillz
get_voxel when hit ignore patch by minermoder27
Minetest mod: carts for MFF
===========================
Based on boost_cart and modified to fully *replace* carts (@Coethium)
- desactivate mesecons
- power_rail: accelerate, max_speed set in init.lua
- brake_rail: deccelerate, min_speed set in init.lua (so the cart doesn't stop and runs at very low speed)
- default:rail / rail_cooper : no friction, keep the current speed
- no collision (avoid the "walled_in" bug)
Boost_cart
==========
Based on (and fully compatible with) the mod "carts" by PilzAdam
Target: Run smoothly and do not use too much CPU
License of source code:
-----------------------
@ -31,6 +34,3 @@ kddekadenz:
Zeg9:
cart.x
cart.png
rarkenin:
cart_rail_*.png

2
mods/carts/depends.txt Executable file → Normal file
View File

@ -1 +1,3 @@
default
mesecons?
moreores?

58
mods/carts/detector.lua Normal file
View File

@ -0,0 +1,58 @@
local mesecons_rules = mesecon.rules.flat
function carts:turnoff_detector_rail(pos)
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name, "detector_rail") == 1 then
if node.name == "carts:detectorrail_on" then --has not been dug
minetest.swap_node(pos, {name = "carts:detectorrail", param2=node.param2})
end
mesecon.receptor_off(pos, mesecons_rules)
end
end
function carts:signal_detector_rail(pos)
local node = minetest.get_node(pos)
if minetest.get_item_group(node.name, "detector_rail") ~= 1 then
return
end
if node.name == "carts:detectorrail" then
minetest.swap_node(pos, {name = "carts:detectorrail_on", param2=node.param2})
end
mesecon.receptor_on(pos, mesecons_rules)
minetest.after(0.5, carts.turnoff_detector_rail, carts, pos)
end
carts:register_rail("carts:detectorrail", {
description = "Detector rail",
tiles = {
"carts_rail_dtc.png", "carts_rail_curved_dtc.png",
"carts_rail_t_junction_dtc.png", "carts_rail_crossing_dtc.png"
},
groups = carts:get_rail_groups({detector_rail = 1}),
mesecons = {receptor = {state = "off", rules = mesecons_rules}},
})
carts:register_rail("carts:detectorrail_on", {
description = "Detector rail ON (you hacker you)",
tiles = {
"carts_rail_dtc_on.png", "carts_rail_curved_dtc_on.png",
"carts_rail_t_junction_dtc_on.png", "carts_rail_crossing_dtc_on.png"
},
groups = carts:get_rail_groups({
detector_rail = 1, not_in_creative_inventory = 1
}),
drop = "carts:detectorrail",
mesecons = {receptor = {state = "on", rules = mesecons_rules}},
})
minetest.register_craft({
output = "carts:detectorrail 6",
recipe = {
{"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"},
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
{"default:steel_ingot", "mesecons:wire_00000000_off", "default:steel_ingot"},
},
})

267
mods/carts/functions.lua Executable file → Normal file
View File

@ -1,89 +1,226 @@
--
-- Helper functions
--
cart_func = {}
function cart_func:get_sign(z)
function carts:get_sign(z)
if z == 0 then
return 0
else
return z/math.abs(z)
return z / math.abs(z)
end
end
-- Returns the velocity as a unit vector
-- The smaller part of the vector will be turned to 0
function cart_func:velocity_to_dir(v)
function carts:manage_attachment(player, status, obj)
if not player then
return
end
local player_name = player:get_player_name()
if default.player_attached[player_name] == status then
return
end
default.player_attached[player_name] = status
if status then
player:set_attach(obj, "", {x=0, y=6, z=0}, {x=0, y=0, z=0})
player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
else
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
end
end
function carts:velocity_to_dir(v)
if math.abs(v.x) > math.abs(v.z) then
return {x=cart_func:get_sign(v.x), y=cart_func:get_sign(v.y), z=0}
return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0}
else
return {x=0, y=cart_func:get_sign(v.y), z=cart_func:get_sign(v.z)}
return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)}
end
end
function cart_func:is_rail(p)
local nn = minetest.get_node(p).name
--print("*!* is_rail p x=",p.x," y=",p.y," z=",p.z," nn=",nn," group rail=", minetest.get_item_group(nn, "rail"))
if nn == "ignore" then
nn=cart_func:get_content_voxel(p)
print("carts: is_rail hit ignore, trying again with get_content: now nn=",nn," group rail=", minetest.get_item_group(nn, "rail"),"p x=",p.x," y=",p.y," z=",p.z)
end
return minetest.get_item_group(nn, "rail") ~= 0
end
function cart_func:check_rail_in_direction(pos, dir)
local p = cart_func.v3:add(pos, dir)
if cart_func:is_rail(p) then
function carts: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
else
return false
end
end -- cart:check_rail_in_direction
function cart_func:is_int(z)
z = math.abs(z)
return math.abs(math.floor(z+0.5)-z) <= 0.1
return minetest.get_item_group(node, "connect_to_raillike") == railtype
end
cart_func.v3 = {}
function carts:check_front_up_down(pos, dir_, check_up, railtype)
local dir = vector.new(dir_)
local cur = nil
function cart_func.v3:add(v1, v2)
return {x=v1.x+v2.x, y=v1.y+v2.y, z=v1.z+v2.z}
-- Front
dir.y = 0
cur = vector.add(pos, dir)
if carts:is_rail(cur, railtype) then
return dir
end
-- Up
if check_up then
dir.y = 1
cur = vector.add(pos, dir)
if carts:is_rail(cur, railtype) then
return dir
end
end
-- Down
dir.y = -1
cur = vector.add(pos, dir)
if carts:is_rail(cur, railtype) then
return dir
end
return nil
end
function cart_func.v3:copy(v)
return {x=v.x, y=v.y, z=v.z}
function carts: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 = carts: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 = carts:check_front_up_down(pos, right, false, railtype)
if cur then
return cur, 2
end
right_check = true
end
end
-- Normal
cur = carts:check_front_up_down(pos, dir, true, railtype)
if cur then
return cur
end
-- Left, if not already checked
if left_check then
cur = carts: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 = carts:check_front_up_down(pos, right, false, railtype)
if cur then
return cur
end
end
-- Backwards
if not old_switch then
cur = carts: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 cart_func.v3:round(v)
return {
x = math.floor(v.x+0.5),
y = math.floor(v.y+0.5),
z = math.floor(v.z+0.5),
function carts:pathfinder(pos_, expected_pos, old_dir, ctrl, pf_switch, railtype)
local pos = vector.round(pos_)
local pf_pos = vector.round(expected_pos)
local pf_dir = vector.new(old_dir)
for i = 1, 3 do
if vector.equals(pf_pos, pos) then
-- Success! Cart moved on correctly
return true
end
pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype)
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
-- No way forwards
return false
end
pf_pos = vector.add(pf_pos, pf_dir)
end
-- Cart not found
return false
end
function carts: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
function carts:register_rail(name, def)
local def_default = {
drawtype = "raillike",
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},
}
}
for k, v in pairs(def_default) do
def[k] = v
end
if not def.inventory_image then
def.wield_image = def.tiles[1]
def.inventory_image = def.tiles[1]
end
minetest.register_node(name, def)
end
function cart_func.v3:equal(v1, v2)
return v1.x == v2.x and v1.y == v2.y and v1.z == v2.z
end
function cart_func:get_content_voxel(pos)
local t1 = os.clock()
local vm = minetest.get_voxel_manip()
local pos1, pos2 = vm:read_from_map(vector.add(pos, {x=-1,y=-1,z=-1}),vector.add(pos, {x=1,y=1,z=1}))
local a = VoxelArea:new{
MinEdge=pos1,
MaxEdge=pos2,
}
local data = vm:get_data()
local vi = a:indexp(pos)
local railid = data[vi]
local real_name = minetest.get_name_from_content_id(railid)
print(string.format("voxel-ing rail: elapsed time: %.2fms", (os.clock() - t1) * 1000))
return real_name
function carts:get_rail_groups(additional_groups)
-- Get the default rail groups and add more when a table is given
local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1}
if type(additional_groups) == "table" then
for k, v in pairs(additional_groups) do
groups[k] = v
end
end
return groups
end

891
mods/carts/init.lua Executable file → Normal file
View File

@ -1,594 +1,400 @@
dofile(minetest.get_modpath("carts").."/functions.lua")
dofile(minetest.get_modpath("carts").."/rails.lua")
local cart = {
physical = true, -- Set to false to not make carts collide with other entities such as carts or the player.
carts = {}
carts.modpath = minetest.get_modpath("carts")
-- Maximal speed of the cart in m/s
carts.speed_max = minetest.setting_get("movement_speed_walk")*3
-- Minimal speed of the cart on brake rail
carts.brake_speed_min = minetest.setting_get("movement_speed_walk")/2
-- Set to nil to disable punching the cart from inside (min = -1)
carts.punch_speed_min = 7
-- 1 disable mesecons / 0 enable mesecons
carts.mesecon_disabled = 1
if not carts.modpath then
error("\nWrong mod directory name! Please change it to 'carts'.\n" ..
"See also: http://dev.minetest.net/Installing_Mods")
end
function vector.floor(v)
return {
x = math.floor(v.x),
y = math.floor(v.y),
z = math.floor(v.z)
}
end
dofile(carts.modpath.."/functions.lua")
dofile(carts.modpath.."/rails.lua")
if not carts.mesecon_disabled and mesecon then
dofile(carts.modpath.."/detector.lua")
end
-- Support for non-default games
if not default.player_attached then
default.player_attached = {}
end
carts.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"}, -- Set to "invisible.png" to make the cart invisible, which is sometimes useful for videos and custom maps.
textures = {"cart.png"},
driver = nil,
velocity = {x=0, y=0, z=0},
punched = false, -- used to re-send velocity and position
velocity = {x=0, y=0, z=0}, -- only used on punch
old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch
old_pos = nil,
old_velocity = nil,
pre_stop_dir = nil,
MAX_V = minetest.setting_get("movement_speed_walk")*3, -- Limit of the velocity (speed). default: 3 times the walk 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.
old_switch = 0,
railtype = nil,
attached_items = {}
}
function cart:on_rightclick(clicker)
function carts.cart:on_rightclick(clicker)
if not clicker or not clicker:is_player() then
return
end
if self.driver and clicker == self.driver then
local player_name = clicker:get_player_name()
if self.driver and player_name == self.driver then
self.driver = nil
clicker:set_detach()
carts:manage_attachment(clicker, false)
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})
self.driver = player_name
carts:manage_attachment(clicker, true, self.object)
end
end
function cart:on_activate(staticdata, dtime_s)
function carts.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
if string.sub(staticdata, 1, string.len("return")) ~= "return" then
return
end
local data = minetest.deserialize(staticdata)
if not data or type(data) ~= "table" then
return
end
self.railtype = data.railtype
if data.old_dir then
self.old_dir = data.old_dir
end
self.old_pos = self.object:getpos()
self.old_velocity = self.velocity
end
function cart:get_staticdata()
function carts.cart:get_staticdata()
return minetest.serialize({
velocity = self.velocity,
pre_stop_dir = self.pre_stop_dir,
railtype = self.railtype,
old_dir = self.old_dir
})
end
-- Remove the cart if holding a tool or accelerate it
function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
function carts.cart:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
local pos = self.object:getpos()
if not self.railtype then
local bar = vector.floor(vector.add(pos, 0.1))
local node = minetest.get_node(bar).name
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
end
if not puncher or not puncher:is_player() then
local cart_dir = carts:get_rail_direction(pos, self.old_dir, 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
minetest.log("action", "carts:cart removed at " .. pos_to_string(vector.round(self.object:getpos())) .. ", " .. self.railcount .. " rails travelled.")
-- Pick up cart: Drop all attachments
if self.driver then
if self.old_pos then
self.object:setpos(self.old_pos)
end
local player = minetest.get_player_by_name(self.driver)
carts:manage_attachment(player, false)
end
for _,obj_ in ipairs(self.attached_items) do
if obj_ then
obj_:set_detach()
end
end
local leftover = puncher:get_inventory():add_item("main", "carts:cart")
if not leftover:is_empty() then
minetest.add_item(self.object:getpos(), leftover)
end
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 = 0--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()
local vel = self.object:getvelocity()
if puncher:get_player_name() == self.driver then
if math.abs(vel.x + vel.z) > carts.punch_speed_min then
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
local punch_dir = carts:velocity_to_dir(puncher:get_look_dir())
punch_dir.y = 0
local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype)
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
return
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--]]
-- get rail type and set acceleration
local rail = minetest.get_node(pos)
local a = 0
if rail.name == "carts:rail_power" then a = 1
elseif rail.name == "carts:rail_brake" then a = -1
else a = 0
end
--a = a*minetest.setting_get("movement_acceleration_default") -- pour plus tard
a = a*0.5
--minetest.chat_send_all(a)
-- 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.0)*cart_func:get_sign(self.velocity.x), --0.03 (frottements)
y = self.velocity.y + (a-0.0)*cart_func:get_sign(self.velocity.y),
z = self.velocity.z + (a-0.0)*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)
--minetest.chat_send_all(self.velocity.x.." "..self.velocity.y.." "..self.velocity.z)
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)
local punch_interval = 1
if tool_capabilities and tool_capabilities.full_punch_interval then
punch_interval = tool_capabilities.full_punch_interval
end
time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval)
local f = 3 * (time_from_last_punch / punch_interval)
self.velocity = vector.multiply(cart_dir, f)
self.old_dir = cart_dir
self.old_pos = nil
self.punched = true
end
minetest.register_entity("carts:cart", cart)
function carts.cart:on_step(dtime)
local vel = self.object:getvelocity()
local update = {}
if self.punched then
vel = vector.add(vel, self.velocity)
self.object:setvelocity(vel)
self.old_dir.y = 0
elseif vector.equals(vel, {x=0, y=0, z=0}) then
return
end
minetest.register_craftitem("carts:cart", {
description = "Cart",
-- dir: New moving direction of the cart
-- last_switch: Currently pressed L/R key, used to ignore the key on the next rail node
local dir, last_switch
local pos = self.object:getpos()
local is_slow = ((vel.x ~= 0 and math.abs(vel.x) <= carts.brake_speed_min) or
(vel.y ~= 0 and math.abs(vel.y) <= carts.brake_speed_min) or
(vel.z ~= 0 and math.abs(vel.z) <= carts.brake_speed_min)) and
string.match(minetest.get_node(pos).name, "brake")
if self.old_pos and not self.punched then
local flo_pos = vector.round(pos)
local flo_old = vector.round(self.old_pos)
if vector.equals(flo_pos, flo_old) and not is_slow then -- Do not check one node multiple times (but check if low speed)
return
end
end
local ctrl, player
-- Get player controls
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
-- Detection for "skipping" nodes
local expected_pos = vector.add(self.old_pos, self.old_dir)
local found_path = carts:pathfinder(
pos, expected_pos, self.old_dir, ctrl, self.old_switch, self.railtype
)
if not found_path and not is_slow then
-- No rail found: reset back to the expected position
pos = expected_pos
update.pos = true
end
end
local cart_dir = carts:velocity_to_dir(vel)
local max_vel = carts.speed_max
if not dir then
dir, last_switch = carts:get_rail_direction(
pos, cart_dir, ctrl, self.old_switch, self.railtype
)
end
local new_acc = {x=0, y=0, z=0}
local speed_mod = 0
if vector.equals(dir, {x=0, y=0, z=0}) then
vel = {x=0, y=0, z=0}
pos = vector.round(pos)
update.pos = true
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 in slopes..
local acc = dir.y * -1.8
-- MFF : Some rails have bad acceleration property, reinit them !
-- this code would be commented when all rails will be corrected
local rail = minetest.get_node(pos)
if string.match(rail.name, "power")
then minetest.get_meta(pos):set_string("cart_acceleration", "1")
elseif string.match(rail.name, "brake") then minetest.get_meta(pos):set_string("cart_acceleration", "-1")
else minetest.get_meta(pos):set_string("cart_acceleration", "0")
end
-- Change acceleration by rail (power/brake)
local speed_mod_string = minetest.get_meta(pos):get_string("cart_acceleration")
if speed_mod_string and speed_mod_string ~= ""
then speed_mod = tonumber(speed_mod_string)
else speed_mod = 0
end
if speed_mod > 0 then speed_mod = 2
elseif speed_mod < 0 then speed_mod = -2
else speed_mod = 0
end
--[[if speed_mod_string == "halt" then --stop rail, not used in MFF
vel = {x=0, y=0, z=0}
acc = 0
pos = vector.round(pos)
update.pos = true
update.vel = true
else--]]if speed_mod and speed_mod ~= 0 then
acc = acc + (speed_mod * 10)
else
--acc = acc - 0.4 --No friction (to be set as an option)
-- Handbrake
if ctrl and ctrl.down then
acc = acc - 1.2
end
end
if self.old_dir.y == 0 and not self.punched then
-- Stop the cart swing between two rail parts (handbrake)
if vector.equals(vector.multiply(self.old_dir, -1), dir) then
vel = {x=0, y=0, z=0}
acc = 0
if self.old_pos then
pos = vector.new(self.old_pos)
update.pos = true
end
dir = vector.new(self.old_dir)
update.vel = true
end
end
new_acc = vector.multiply(dir, acc)
end
if not carts.mesecon_disabled and mesecon then
carts:signal_detector_rail(vector.round(pos))
end
-- Limits
for _,v in ipairs({"x","y","z"}) do
if speed_mod > 0 and math.abs(vel[v]) > max_vel then
vel[v] = carts:get_sign(vel[v]) * max_vel
new_acc[v] = 0
update.vel = true
elseif speed_mod < 0 and vel[v] ~= 0 and math.abs(vel[v]) <= carts.brake_speed_min then
vel[v] = carts:get_sign(vel[v]) * carts.brake_speed_min
new_acc[v] = 0
update.vel = true
end
end
self.object:setacceleration(new_acc)
self.old_pos = vector.new(pos)
if not vector.equals(dir, {x=0, y=0, z=0}) then
self.old_dir = vector.new(dir)
end
self.old_switch = last_switch
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
update.vel = true -- update player animation
end
if not (update.vel or update.pos) then
return
end
local yaw = 0
if self.old_dir.x < 0 then
yaw = 0.5
elseif self.old_dir.x > 0 then
yaw = 1.5
elseif self.old_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", carts.cart)
minetest.register_craftitem(":carts:cart", {
description = "Cart (Sneak+Click to pick up)",
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
if carts:is_rail(pointed_thing.under) then
minetest.add_entity(pointed_thing.under, "carts:cart")
elseif carts: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
else return end
itemstack:take_item()
return itemstack
end,
})
@ -599,10 +405,3 @@ minetest.register_craft({
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
})
if minetest.setting_getbool("log_mods") then
minetest.log("action", "Carbone: [carts] loaded.")
end

BIN
mods/carts/models/cart.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

After

Width:  |  Height:  |  Size: 216 B

0
mods/carts/models/cart.x Executable file → Normal file
View File

View File

@ -1,7 +1,10 @@
minetest.register_node(":default:rail", {
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"},
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",
@ -12,184 +15,64 @@ minetest.register_node(":default:rail", {
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 = {
groups = carts:get_rail_groups(),
})
-- Copper rail
if minetest.get_modpath("moreores") then
-- Moreores' copper rail
minetest.register_alias("carts:rail_copper", "moreores:copper_rail")
else
carts:register_rail(":carts:rail_copper", {
description = "Copper rail",
tiles = {
"carts_rail_cp.png", "carts_rail_curved_cp.png",
"carts_rail_t_junction_cp.png", "carts_rail_crossing_cp.png"
},
groups = carts:get_rail_groups(),
})
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"},
}
})
end
-- Speed up
-- Rail Power
carts:register_rail(":carts:rail_power", {
description = "Powered rail",
tiles = {
"carts_rail_pwr.png", "carts_rail_curved_pwr.png",
"carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"
},
groups = carts:get_rail_groups(),
after_place_node = function(pos, placer, itemstack)
if not mesecon then
minetest.get_meta(pos):set_string("cart_acceleration", "1")
end
end,
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)
action_on = function(pos, node)
carts:boost_rail(pos, 1)
end,
action_on = function(pos, node)
action_off = 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", "1")
--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", "-1")
--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_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({
@ -198,16 +81,80 @@ minetest.register_craft({
recipe = {"group:rail", "default:mese_crystal_fragment"},
})
-- Rail Brake
carts:register_rail(":carts:rail_brake", {
description = "Brake rail",
tiles = {
"carts_rail_brk.png", "carts_rail_curved_brk.png",
"carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"
},
groups = carts:get_rail_groups(),
after_place_node = function(pos, placer, itemstack)
if not mesecon then
minetest.get_meta(pos):set_string("cart_acceleration", "-1")
end
end,
mesecons = {
effector = {
action_on = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "-1")
end,
action_off = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})
minetest.register_craft({
type = "shapeless",
output = "carts:rail_brake",
recipe = {"group:rail", "default:coal_lump"},
})
-- Start stop rail (temporary removed for mff)
--[[carts:register_rail("carts:startstoprail", {
description = "Start-stop rail",
tiles = {
"carts_rail_ss.png", "carts_rail_curved_ss.png",
"carts_rail_t_junction_ss.png", "carts_rail_crossing_ss.png"
},
groups = carts:get_rail_groups(),
after_place_node = function(pos, placer, itemstack)
if not mesecon then
minetest.get_meta(pos):set_string("cart_acceleration", "halt")
end
end,
mesecons = {
effector = {
action_on = function(pos, node)
carts:boost_rail(pos, 0.5)
end,
action_off = function(pos, node)
minetest.get_meta(pos):set_string("cart_acceleration", "halt")
end,
},
},
})
minetest.register_craft({
type = "shapeless",
output = "carts:startstoprail 2",
recipe = {"carts:powerrail", "carts:brakerail"},
})--]]
--Alias
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:brake_rail", "carts:rail_brake")

0
mods/carts/textures/cart_bottom.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 114 B

BIN
mods/carts/textures/cart_side.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

After

Width:  |  Height:  |  Size: 147 B

0
mods/carts/textures/cart_top.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 131 B

After

Width:  |  Height:  |  Size: 131 B

BIN
mods/carts/textures/carts_rail_brk.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

BIN
mods/carts/textures/carts_rail_crossing_brk.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 654 B

BIN
mods/carts/textures/carts_rail_crossing_pwr.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 B

After

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 B

BIN
mods/carts/textures/carts_rail_curved_brk.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

BIN
mods/carts/textures/carts_rail_curved_pwr.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 B

BIN
mods/carts/textures/carts_rail_pwr.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

BIN
mods/carts/textures/carts_rail_t_junction_brk.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 375 B

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

BIN
mods/carts/textures/carts_rail_t_junction_pwr.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

View File

@ -1,104 +0,0 @@
--[[local t = tonumber(minetest.get_meta(pos):get_string("cart_touring_velocity"))
if not t then t=0 end
t = 0
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--]]
--[[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({
type = "shapeless",
output = "carts:rail_tour",
recipe = {"group:rail", "default:clay_lump"},
})--]]
--minetest.register_alias("carts:tourrail", "carts:rail_tour")
-- 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
})--]]