spillz wrote:How do I give them a mesecon signal? (Suggest you add this to the first post)
spillz wrote:Morn76 wrote:Put a mesecons torch next to the power rail.
Every single one?
Morn76 wrote:Yes, just like you would put stone torches next to power rails in MC.
I'm considering doing a fork of the carts mod so you would need fewer power rails per distance. Especially for upward-sloping tracks, the current version of the mod IMO needs an obscene amount of power rails or the carts will slow down and stop. Which is not very good for roller coasters.
spillz wrote:I don't really play MC, but my kids do. So maybe obvious if you are a MC player. But why not have mese as part of powered rail recipe? About as realistic as powering it with a mese torch!
spillz wrote:Probably just need to change a couple of parameters for power and friction. Would also like to be able to hit a stationary cart while inside it to make it move (not a lot but enough to get it moving if it has stopped)
Morn76 wrote:The person who understands the code doesn't seem to be interested in further development to get really mature mods.
diff --git a/init.lua b/init.lua
index 03bc1a3..c299495 100644
--- a/init.lua
+++ b/init.lua
@@ -75,11 +75,24 @@ function cart:on_punch(puncher, time_from_last_punch, tool_capabilities, directi
return
end
- if puncher == self.driver then
+ 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
[The extension patch has been deactivated and can no longer be displayed.]
[The extension patch has been deactivated and can no longer be displayed.]
Sokomine wrote:Morn76 wrote:The person who understands the code doesn't seem to be interested in further development to get really mature mods.
Hm, I think PilzAdam (like many other core devs) is already quite busy with developing Minetest and does not have enough time to really play on servers. There are also technical limitations which the carts cannot easily circumvent.
Sokomine wrote:Morn76 wrote:The person who understands the code doesn't seem to be interested in further development to get really mature mods.
Hm, I think PilzAdam (like many other core devs) is already quite busy with developing Minetest and does not have enough time to really play on servers. There are also technical limitations which the carts cannot easily circumvent.
Morn76 wrote:Spillz, I think the Minetest devs deliberately keep the default game very minimalistic (e.g. no mobs). This is why the Freeminer fork happened which seems to aim for a more full-featured default game like it was in Minetest-classic/-c55.
But no matter whether a mod like carts or nether is or isn't part of the default game, it's pretty clear that many players want mods like these, so they need to be improved anyway.
spillz wrote:Arguably so is mesecons. All the whining about lua being too slow is a total distraction - just like with any other scriptable platform, you gradually add stuff to the c/c++ api to work around the actual performance bottlenecks instead of the hypothetical ones.
Spillz wrote:Here's a quickie patch that lets the driver of a slowly moving (or stationary) cart punch it to accelerate it. Gotta love open source
Kilarin wrote:Spillz wrote:Here's a quickie patch that lets the driver of a slowly moving (or stationary) cart punch it to accelerate it. Gotta love open source
Cool, thank you very much! Works great!
*!* grd* top pos x= 842 y= 32 z= -527
*!* grd* dir x= 0 y= 0 z= -1
*!* grd* d x= 0 y= 0 z= -1
*!* grd* front d.y set 0 x= 0 y= 0 z= -1
*!* grd* addf p x= 842 y= 32 z= -528
*!* is_rail p x= 842 y= 32 z= -528 nn= default:rail group rail= 1
*!* grd* israil front
*!* crd after grd dir x= 0 y= 0 z= -1
(above works fine, obviously, but then on the next node we get:)
*!* grd* top pos x= 842 y= 32 z= -528
*!* grd* dir x= 0 y= 0 z= -1
*!* grd* d x= 0 y= 0 z= -1
*!* grd* front d.y set 0 x= 0 y= 0 z= -1
*!* grd* addf p x= 842 y= 32 z= -529
*!* is_rail p x= 842 y= 32 z= -529 nn= ignore group rail= 0
*!* grd* down d.y set -1 x= 0 y= -1 z= -1
*!* grd* addd p x= 842 y= 31 z= -529
*!* is_rail p x= 842 y= 31 z= -529 nn= default:cobble group rail= 0
*!* grd* up d.y set 1 x= 0 y= 1 z= -1
*!* grd* addu p x= 842 y= 33 z= -529
*!* is_rail p x= 842 y= 33 z= -529 nn= ignore group rail= 0
*!* grd* checking l and r
*!* is_rail p x= 843 y= 32 z= -528 nn= air group rail= 0
*!* is_rail p x= 843 y= 31 z= -528 nn= air group rail= 0
*!* is_rail p x= 841 y= 32 z= -528 nn= air group rail= 0
*!* is_rail p x= 841 y= 31 z= -528 nn= air group rail= 0
*!* grd* end return 0,0,0
*!* crd after grd dir x= 0 y= 0 z= 0
dofile(minetest.get_modpath("carts").."/functions.lua")
--
-- Cart entity
--
local 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,
velocity = {x=0, y=0, z=0},
old_pos = nil,
old_velocity = nil,
pre_stop_dir = nil,
MAX_V = 8, -- Limit of the velocity -- *!* changed from 8 to 10
}
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
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 then
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)
local d = cart_func.v3:copy(dir)
print("*!* grd* top pos x=",pos.x," y=",pos.y," z=",pos.z)
print("*!* grd* dir x=",dir.x," y=",dir.y," z=",dir.z)
print("*!* grd* d x=",d.x," y=",d.y," z=",d.z)
-- Check front
d.y = 0
print("*!* grd* front d.y set 0 x=",d.x," y=",d.y," z=",d.z)
local p = cart_func.v3:add(cart_func.v3:copy(pos), d)
print("*!* grd* addf p x=",p.x," y=",p.y," z=",p.z)
if cart_func:is_rail(p) then
print("*!* grd* israil front")
return d
end
-- Check downhill
d.y = -1
print("*!* grd* down d.y set -1 x=",d.x," y=",d.y," z=",d.z)
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
print("*!* grd* addd p x=",p.x," y=",p.y," z=",p.z)
if cart_func:is_rail(p) then
print("*!* grd* israil down")
return d
end
-- Check uphill
d.y = 1
print("*!* grd* up d.y set 1 x=",d.x," y=",d.y," z=",d.z)
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
print("*!* grd* addu p x=",p.x," y=",p.y," z=",p.z)
if cart_func:is_rail(p) then
print("*!* grd* israil up")
return d
end
d.y = 0
-- Check left and right
local view_dir
local other_dir
local a
print("*!* grd* checking l and r ")
if d.x == 0 and d.z ~= 0 then
view_dir = "z"
other_dir = "x"
if d.z < 0 then
a = {1, -1}
else
a = {-1, 1}
end
elseif d.z == 0 and d.x ~= 0 then
view_dir = "x"
other_dir = "z"
if d.x > 0 then
a = {1, -1}
else
a = {-1, 1}
end
else
return {x=0, y=0, z=0}
end
d[view_dir] = 0
d[other_dir] = a[1]
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = -1
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = 0
d[other_dir] = a[2]
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = -1
p = cart_func.v3:add(cart_func.v3:copy(pos), d)
if cart_func:is_rail(p) then
return d
end
d.y = 0
print("*!* grd* end return 0,0,0") --*!* debug
return {x=0, y=0, z=0}
end
function cart:calc_rail_direction(pos, vel)
print("*!* crd top vel x=",vel.x," y=",vel.y," z=",vel.z)
local velocity = cart_func.v3:copy(vel)
print("*!* crd copy velocity x=",velocity.x," y=",velocity.y," z=",velocity.z)
local p = cart_func.v3:copy(pos)
if cart_func:is_int(p.x) and cart_func:is_int(p.z) then
print("*!* crd inside if")
local dir = cart_func:velocity_to_dir(velocity)
print("*!* crd after vtd velocity x=",velocity.x," y=",velocity.y," z=",velocity.z)
local dir_old = cart_func.v3:copy(dir)
dir = self:get_rail_direction(cart_func.v3:round(p), dir)
print("*!* crd after grd dir x=",dir.x," y=",dir.y," z=",dir.z)
local v = math.max(math.abs(velocity.x), math.abs(velocity.z))
print("*!* crd after math.max v=",v)
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}) then
print("*!* calc_rail_direction vel=0,0,0") --*!* debug
-- 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
return {x=0, y=0, z=0}, p
end
if not cart_func.v3:equal(dir, dir_old) then
print("*!* calc_rail_direction not equal dir,dir_old : v.x=",velocity.x," v.y=",velocity.y," v.z=",velocity.z) --*!* debug
return velocity, cart_func.v3:round(p)
end
end
print("*!* calc rail direction final return v.x=",velocity.x," v.y=",velocity.y," v.z=",velocity.z) --*!* debug
return velocity, p
end
function cart:on_step(dtime)
local pos = self.object:getpos()
local dir = cart_func:velocity_to_dir(self.velocity)
print("*!* on_step top dir.x=",dir.x," dir.y=",dir.y," dir.z=",dir.z," v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
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)
print("*!* on_step after pre_stop v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
end
-- Stop the cart if the velocity is nearly 0
-- Only if on a flat railway
print("*!* on_step beofore if dir.y==0 v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
if dir.y == 0 then
print("*!* on_step flat top v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
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.env: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
print("*!* on_step flat set velocity to zero") --*!* debug
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
print("*!* on_step flat bot v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
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)
print("*!* on_step recalc olddir.x=",old_dir.x," olddir.y=",old_dir.y," olddir.z=",old_dir.z," v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
print("*!* on_step recalc dir.x=",dir.x," dir.y=",dir.y," dir.z=",dir.z) --*!* debug
print("*!* on_step recalc oldvel.x=",self.old_velocity.x," oldvel.y=",self.old_velocity.y," oldvel.z=",self.old_velocity.z) --*!* debug
print("*!* on_step recalc oldpos.x=",self.old_pos.x," oldpos.y=",self.old_pos.y," oldpos.z=",self.old_pos.z) --*!* debug
print("*!* on_step recalc pos.x=",pos.x," pos.y=",pos.y," pos.z=",pos.z) --*!* debug
if old_dir.x ~= 0 then
local sign = cart_func:get_sign(pos.x-self.old_pos.x)
print("*!* on_step recalc in old_dir.x ~= 0 sign=",sign) --*!* debug
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
print("*!* on_step recalc if1top v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
self.velocity = self.old_velocity
pos = self.old_pos
self.object:setpos(self.old_pos)
print("*!* on_step recalc if1bot v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
break
end
end
elseif old_dir.z ~= 0 then
local sign = cart_func:get_sign(pos.z-self.old_pos.z)
print("*!* on_step recalc in old_dir.z ~= 0 sign=",sign) --*!* debug
while true do
print("*!* on_step recalc whiletrue top sign=",sign," oldpos.x=",self.old_pos.x," oldpos.y=",self.old_pos.y," oldpos.z=",self.old_pos.z) --*!* debug
print("*!* on_step recalc pos.x=",pos.x," pos.y=",pos.y," pos.z=",pos.z) --*!* debug
print("*!* on_step recalc oldvel.x=",self.old_velocity.x," oldvel.y=",self.old_velocity.y," oldvel.z=",self.old_velocity.z) --*!* debug
if sign ~= cart_func:get_sign(pos.z-self.old_pos.z) or pos.z == self.old_pos.z then
print("*!* on_step recalc break") --*!* debug
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
print("*!* on_step recalc bfr crd oldpos.x=",self.old_pos.x," oldpos.y=",self.old_pos.y," oldpos.z=",self.old_pos.z) --*!* debug
print("*!* on_step recalc bfr crd oldvel.x=",self.old_velocity.x," oldvel.y=",self.old_velocity.y," oldvel.z=",self.old_velocity.z) --*!* debug
self.old_velocity, self.old_pos = self:calc_rail_direction(self.old_pos, self.old_velocity)
print("*!* on_step recalc aft crd oldpos.x=",self.old_pos.x," oldpos.y=",self.old_pos.y," oldpos.z=",self.old_pos.z) --*!* debug
print("*!* on_step recalc aft crd oldvel.x=",self.old_velocity.x," oldvel.y=",self.old_velocity.y," oldvel.z=",self.old_velocity.z) --*!* debug
old_dir = cart_func:velocity_to_dir(self.old_velocity)
print("*!* on_step recalc dropped oldvel.x=",self.old_velocity.x," oldvel.y=",self.old_velocity.y," oldvel.z=",self.old_velocity.z) --*!* debug
print("*!* on_step recalc dropped oldpos.x=",self.old_pos.x," oldpos.y=",self.old_pos.y," oldpos.z=",self.old_pos.z) --*!* debug
print("*!* on_step recalc dropped olddir.x=",old_dir.x," olddir.y=",old_dir.y," olddir.z=",old_dir.z) --*!* debug
if not cart_func.v3:equal(cart_func:velocity_to_dir(self.old_velocity), dir) then
print("*!* on_step recalc if2top v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
self.velocity = self.old_velocity
print("*!* on_step recalc if2bot v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
pos = self.old_pos
self.object:setpos(self.old_pos)
break
end
print("*!* on_step recalc whiletrue bot sign=",sign," oldpos.x=",self.old_pos.x," oldpos.y=",self.old_pos.y," oldpos.z=",self.old_pos.z) --*!* debug
print("*!* on_step recalc pos.x=",pos.x," pos.y=",pos.y," pos.z=",pos.z) --*!* debug
print("*!* on_step recalc oldvel.x=",self.old_velocity.x," oldvel.y=",self.old_velocity.y," oldvel.z=",self.old_velocity.z) --*!* debug
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.env:get_meta(pos):get_string("cart_acceleration"))
if not a then
a = 0
end
print("*!* on_step acel-decl top v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
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
print("*!* on_step acel-decl bot v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
end
-- Dont switch moving direction
-- Only if on flat railway
if dir.y == 0 then
print("*!* on_step flat-chng dir top v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
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
print("*!* on_step flat-chng dir bot v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
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,
}
print("*!* on_step aft onedir v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
-- 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
print("*!* on_step aft limit dir top v.x=",self.velocity.x," v.y=",self.velocity.y," v.z=",self.velocity.z) --*!* debug
self.object:setvelocity(self.velocity)
self.old_pos = self.object:getpos()
self.old_velocity = cart_func.v3:copy(self.velocity)
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
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 = "Minecart",
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
minetest.env:add_entity(pointed_thing.under, "carts:cart")
if not minetest.setting_getbool("creative_mode") then
itemstack:take_item()
end
return itemstack
elseif cart_func:is_rail(pointed_thing.above) then
minetest.env: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",
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
-- but how to specify the dimensions for curved and sideways rails?
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy=2,snappy=1,dig_immediate=2,attached_node=1,rail=1,connect_to_raillike=1},
})
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",
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
-- but how to specify the dimensions for curved and sideways rails?
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy=2,snappy=1,dig_immediate=2,attached_node=1,rail=1,connect_to_raillike=1},
after_place_node = function(pos, placer, itemstack)
if not mesecon then
minetest.env:get_meta(pos):set_string("cart_acceleration", "0.5")
end
end,
mesecons = {
effector = {
action_on = function(pos, node)
minetest.env:get_meta(pos):set_string("cart_acceleration", "0.5")
end,
action_off = function(pos, node)
minetest.env:get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})
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",
is_ground_content = true,
walkable = false,
selection_box = {
type = "fixed",
-- but how to specify the dimensions for curved and sideways rails?
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
},
groups = {bendy=2,snappy=1,dig_immediate=2,attached_node=1,rail=1,connect_to_raillike=1},
after_place_node = function(pos, placer, itemstack)
if not mesecon then
minetest.env:get_meta(pos):set_string("cart_acceleration", "-0.2")
end
end,
mesecons = {
effector = {
action_on = function(pos, node)
minetest.env:get_meta(pos):set_string("cart_acceleration", "-0.2")
end,
action_off = function(pos, node)
minetest.env:get_meta(pos):set_string("cart_acceleration", "0")
end,
},
},
})
minetest.register_craft({
output = "carts:powerrail 2",
recipe = {
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
{"default:steel_ingot", "default:stick", "default:steel_ingot"},
{"default:steel_ingot", "", "default:steel_ingot"},
}
})
minetest.register_craft({
output = "carts:powerrail 2",
recipe = {
{"default:steel_ingot", "", "default:steel_ingot"},
{"default:steel_ingot", "default:stick", "default:steel_ingot"},
{"default:steel_ingot", "default:mese_crystal_fragment", "default:steel_ingot"},
}
})
minetest.register_craft({
output = "carts:brakerail 2",
recipe = {
{"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
{"default:steel_ingot", "default:stick", "default:steel_ingot"},
{"default:steel_ingot", "", "default:steel_ingot"},
}
})
minetest.register_craft({
output = "carts:brakerail 2",
recipe = {
{"default:steel_ingot", "", "default:steel_ingot"},
{"default:steel_ingot", "default:stick", "default:steel_ingot"},
{"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
}
})
--
-- Helper functions
--
cart_func = {}
function cart_func:get_sign(z)
if z == 0 then
return 0
else
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)
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}
else
return {x=0, y=cart_func:get_sign(v.y), z=cart_func:get_sign(v.z)}
end
end
function cart_func:is_rail(p)
local nn = minetest.env: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"))
return minetest.get_item_group(nn, "rail") ~= 0
end
function cart_func:is_int(z)
z = math.abs(z)
return math.abs(math.floor(z+0.5)-z) <= 0.1
end
cart_func.v3 = {}
function cart_func.v3:add(v1, v2)
return {x=v1.x+v2.x, y=v1.y+v2.y, z=v1.z+v2.z}
end
function cart_func.v3:copy(v)
return {x=v.x, y=v.y, z=v.z}
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),
}
end
function cart_func.v3:equal(v1, v2)
return v1.x == v2.x and v1.y == v2.y and v1.z == v2.z
end
Temperest wrote:this is an engine issue and is unrelated to the carts mod itself.
minermoder27 wrote:Maybe try calling the function again if you get node=ignore
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
end
function cart_func:is_rail(p, is_voxel)
local nn = minetest.env:get_node(p).name
++ if nn=="ignore" then
++ print("oops")
++ nn=cart_func:get_content_voxel(p)
++ end
return minetest.get_item_group(nn, "rail") ~= 0
end
minermoder27 wrote:I realized you could use Voxel Manipulator to get a block's name.
celeron55 wrote:It seems like the original problem might be fully fixed by this:
https://github.com/minetest/minetest/co … 17d44be8fb
Please test with latest git.
minermoder27 wrote:Made a pull request to fix the bug on non-latest-git builds
Users browsing this forum: No registered users and 38 guests