summaryrefslogtreecommitdiff
path: root/boost_cart
diff options
context:
space:
mode:
Diffstat (limited to 'boost_cart')
-rw-r--r--boost_cart/cart_entity.lua100
-rw-r--r--boost_cart/functions.lua56
-rw-r--r--boost_cart/init.lua20
3 files changed, 96 insertions, 80 deletions
diff --git a/boost_cart/cart_entity.lua b/boost_cart/cart_entity.lua
index 257aae6..0105cf5 100644
--- a/boost_cart/cart_entity.lua
+++ b/boost_cart/cart_entity.lua
@@ -1,17 +1,17 @@
local HAVE_MESECONS_ENABLED = minetest.global_exists("mesecon")
-function boost_cart:on_rail_step(pos)
+function boost_cart:on_rail_step(entity, pos, distance)
-- Play rail sound
- if self.sound_counter <= 0 then
+ if entity.sound_counter <= 0 then
minetest.sound_play("cart_rail", {
pos = pos,
max_hear_distance = 40,
gain = 0.5
})
- self.sound_counter = math.random(4, 15)
+ entity.sound_counter = math.random(4, 15)
end
- self.sound_counter = self.sound_counter - 1
+ entity.sound_counter = entity.sound_counter - distance
if HAVE_MESECONS_ENABLED then
boost_cart:signal_detector_rail(pos)
@@ -65,7 +65,7 @@ function cart_entity:on_activate(staticdata, dtime_s)
return
end
local data = minetest.deserialize(staticdata)
- if not data or type(data) ~= "table" then
+ if type(data) ~= "table" then
return
end
self.railtype = data.railtype
@@ -82,8 +82,8 @@ function cart_entity:get_staticdata()
end
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
- local pos = self.object:getpos()
- local vel = self.object:getvelocity()
+ local pos = self.object:get_pos()
+ local vel = self.object:get_velocity()
if not self.railtype or vector.equals(vel, {x=0, y=0, z=0}) then
local node = minetest.get_node(pos).name
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
@@ -103,7 +103,7 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
-- Pick up cart: Drop all attachments
if self.driver then
if self.old_pos then
- self.object:setpos(self.old_pos)
+ self.object:set_pos(self.old_pos)
end
local player = minetest.get_player_by_name(self.driver)
boost_cart:manage_attachment(player, nil)
@@ -149,20 +149,23 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
self.punched = true
end
+local v3_len = vector.length
function cart_entity:on_step(dtime)
- local vel = self.object:getvelocity()
+ local vel = self.object:get_velocity()
if self.punched then
vel = vector.add(vel, self.velocity)
- self.object:setvelocity(vel)
+ self.object:set_velocity(vel)
self.old_dir.y = 0
elseif vector.equals(vel, {x=0, y=0, z=0}) then
return
end
- local pos = self.object:getpos()
+ local pos = self.object:get_pos()
+ local cart_dir = boost_cart:velocity_to_dir(vel)
+ local same_dir = vector.equals(cart_dir, self.old_dir)
local update = {}
- if self.old_pos and not self.punched then
+ if self.old_pos and not self.punched and same_dir then
local flo_pos = vector.round(pos)
local flo_old = vector.round(self.old_pos)
if vector.equals(flo_pos, flo_old) then
@@ -172,6 +175,7 @@ function cart_entity:on_step(dtime)
end
local ctrl, player
+ local distance = 1
-- Get player controls
if self.driver then
@@ -181,37 +185,53 @@ function cart_entity:on_step(dtime)
end
end
- if self.old_pos then
- -- Detection for "skipping" nodes
- local found_path = boost_cart:pathfinder(
- pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype
+ local stop_wiggle = false
+ if self.old_pos and same_dir then
+ -- Detection for "skipping" nodes (perhaps use average dtime?)
+ -- It's sophisticated enough to take the acceleration in account
+ local acc = self.object:get_acceleration()
+ distance = dtime * (v3_len(vel) + 0.5 * dtime * v3_len(acc))
+
+ local new_pos, new_dir = boost_cart:pathfinder(
+ pos, self.old_pos, self.old_dir, distance, ctrl,
+ self.old_switch, self.railtype
)
- if not found_path then
- -- No rail found: reset back to the expected position
- pos = vector.new(self.old_pos)
+ if new_pos then
+ -- No rail found: set to the expected position
+ pos = new_pos
update.pos = true
+ cart_dir = new_dir
end
+ elseif self.old_pos and cart_dir.y ~= -1 and not self.punched then
+ -- Stop wiggle
+ stop_wiggle = true
end
- local cart_dir = boost_cart:velocity_to_dir(vel)
-
-- dir: New moving direction of the cart
- -- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node
+ -- switch_keys: Currently pressed L(1) or R(2) key,
+ -- used to ignore the key on the next rail node
local dir, switch_keys = boost_cart:get_rail_direction(
pos, cart_dir, ctrl, self.old_switch, self.railtype
)
local new_acc = {x=0, y=0, z=0}
- if vector.equals(dir, {x=0, y=0, z=0}) then
+ if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then
vel = {x=0, y=0, z=0}
- pos = vector.round(pos)
+ local pos_r = vector.round(pos)
+ if not boost_cart:is_rail(pos_r, self.railtype) then
+ pos = self.old_pos
+ elseif not stop_wiggle then
+ pos = pos_r
+ else
+ pos.y = math.floor(pos.y + 0.5)
+ end
update.pos = true
update.vel = true
else
-- Direction change detected
if not vector.equals(dir, self.old_dir) then
- vel = vector.multiply(dir, math.abs(vel.x + vel.z))
+ vel = vector.multiply(dir, v3_len(vel))
update.vel = true
if dir.y ~= self.old_dir.y then
pos = vector.round(pos)
@@ -272,23 +292,8 @@ function cart_entity:on_step(dtime)
acc = 0
end
- if self.old_dir.y ~= 1 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
- boost_cart.on_rail_step(self, vector.round(pos))
-- Limits
local max_vel = boost_cart.speed_max
@@ -300,13 +305,14 @@ function cart_entity:on_step(dtime)
end
end
- self.object:setacceleration(new_acc)
- self.old_pos = pos
- if not vector.equals(dir, {x=0, y=0, z=0}) then
+ self.object:set_acceleration(new_acc)
+ self.old_pos = vector.round(pos)
+ if not vector.equals(dir, {x=0, y=0, z=0}) and not stop_wiggle then
self.old_dir = dir
end
self.old_switch = switch_keys
+ boost_cart:on_rail_step(self, self.old_pos, distance)
if self.punched then
-- Collect dropped items
@@ -336,7 +342,7 @@ function cart_entity:on_step(dtime)
elseif self.old_dir.z < 0 then
yaw = 1
end
- self.object:setyaw(yaw * math.pi)
+ self.object:set_yaw(yaw * math.pi)
local anim = {x=0, y=0}
if dir.y == -1 then
@@ -346,9 +352,9 @@ function cart_entity:on_step(dtime)
end
self.object:set_animation(anim, 1, 0)
- self.object:setvelocity(vel)
+ self.object:set_velocity(vel)
if update.pos then
- self.object:setpos(pos)
+ self.object:set_pos(pos)
end
end
@@ -376,7 +382,7 @@ if not boost_cart.mtg_compat then
return
end
- if not minetest.setting_getbool("creative_mode") then
+ if not minetest.settings:get_bool("creative_mode") then
itemstack:take_item()
end
return itemstack
diff --git a/boost_cart/functions.lua b/boost_cart/functions.lua
index 86f8535..9f5b7e9 100644
--- a/boost_cart/functions.lua
+++ b/boost_cart/functions.lua
@@ -30,14 +30,16 @@ end
function boost_cart:velocity_to_dir(v)
if math.abs(v.x) > math.abs(v.z) then
- return {x=boost_cart:get_sign(v.x), y=boost_cart:get_sign(v.y), z=0}
+ return {x=self:get_sign(v.x), y=self:get_sign(v.y), z=0}
else
- return {x=0, y=boost_cart:get_sign(v.y), z=boost_cart:get_sign(v.z)}
+ return {x=0, y=self:get_sign(v.y), z=self:get_sign(v.z)}
end
end
+local get_node = minetest.get_node
+local get_item_group = minetest.get_item_group
function boost_cart:is_rail(pos, railtype)
- local node = minetest.get_node(pos).name
+ local node = get_node(pos).name
if node == "ignore" then
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(pos, pos)
@@ -49,13 +51,13 @@ function boost_cart:is_rail(pos, railtype)
local vi = area:indexp(pos)
node = minetest.get_name_from_content_id(data[vi])
end
- if minetest.get_item_group(node, "rail") == 0 then
+ if get_item_group(node, "rail") == 0 then
return false
end
if not railtype then
return true
end
- return minetest.get_item_group(node, "connect_to_raillike") == railtype
+ return get_item_group(node, "connect_to_raillike") == railtype
end
function boost_cart:check_front_up_down(pos, dir_, check_up, railtype)
@@ -65,21 +67,21 @@ function boost_cart:check_front_up_down(pos, dir_, check_up, railtype)
-- Front
dir.y = 0
cur = vector.add(pos, dir)
- if boost_cart:is_rail(cur, railtype) then
+ if self:is_rail(cur, railtype) then
return dir
end
-- Up
if check_up then
dir.y = 1
cur = vector.add(pos, dir)
- if boost_cart:is_rail(cur, railtype) then
+ if self:is_rail(cur, railtype) then
return dir
end
end
-- Down
dir.y = -1
cur = vector.add(pos, dir)
- if boost_cart:is_rail(cur, railtype) then
+ if self:is_rail(cur, railtype) then
return dir
end
return nil
@@ -108,14 +110,14 @@ function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
right_check = false
end
if ctrl.left and left_check then
- cur = boost_cart:check_front_up_down(pos, left, false, railtype)
+ cur = self:check_front_up_down(pos, left, false, railtype)
if cur then
return cur, 1
end
left_check = false
end
if ctrl.right and right_check then
- cur = boost_cart:check_front_up_down(pos, right, false, railtype)
+ cur = self:check_front_up_down(pos, right, false, railtype)
if cur then
return cur, 2
end
@@ -124,14 +126,14 @@ function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
end
-- Normal
- cur = boost_cart:check_front_up_down(pos, dir, true, railtype)
+ cur = self:check_front_up_down(pos, dir, true, railtype)
if cur then
return cur
end
-- Left, if not already checked
if left_check then
- cur = boost_cart:check_front_up_down(pos, left, false, railtype)
+ cur = self:check_front_up_down(pos, left, false, railtype)
if cur then
return cur
end
@@ -139,7 +141,7 @@ function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
-- Right, if not already checked
if right_check then
- cur = boost_cart:check_front_up_down(pos, right, false, railtype)
+ cur = self:check_front_up_down(pos, right, false, railtype)
if cur then
return cur
end
@@ -147,7 +149,7 @@ function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
-- Backwards
if not old_switch then
- cur = boost_cart:check_front_up_down(pos, {
+ cur = self:check_front_up_down(pos, {
x = -dir.x,
y = dir.y,
z = -dir.z
@@ -160,33 +162,37 @@ function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
return {x=0, y=0, z=0}
end
-function boost_cart:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype)
- if vector.equals(old_pos, pos_) then
- return true
- end
+function boost_cart:pathfinder(pos_, old_pos, old_dir, distance, ctrl,
+ pf_switch, railtype)
local pos = vector.round(pos_)
+ if vector.equals(old_pos, pos) then
+ return
+ end
+
local pf_pos = vector.round(old_pos)
local pf_dir = vector.new(old_dir)
+ distance = math.min(boost_cart.path_distance_max,
+ math.floor(distance + 1))
- for i = 1, 3 do
- pf_dir, pf_switch = boost_cart:get_rail_direction(
- pf_pos, pf_dir, ctrl, pf_switch, railtype)
+ for i = 1, distance do
+ pf_dir, pf_switch = self:get_rail_direction(
+ pf_pos, pf_dir, ctrl, pf_switch or 0, railtype)
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
-- No way forwards
- return false
+ return pf_pos, pf_dir
end
pf_pos = vector.add(pf_pos, pf_dir)
if vector.equals(pf_pos, pos) then
-- Success! Cart moved on correctly
- return true
+ return
end
end
- -- Cart not found
- return false
+ -- Not found. Put cart to predicted position
+ return pf_pos, pf_dir
end
function boost_cart:boost_rail(pos, amount)
diff --git a/boost_cart/init.lua b/boost_cart/init.lua
index 9bcd785..1b2afa2 100644
--- a/boost_cart/init.lua
+++ b/boost_cart/init.lua
@@ -3,18 +3,22 @@ boost_cart = {}
boost_cart.modpath = minetest.get_modpath("boost_cart")
--- Settings glue for <= 0.4.15
-local setting_getter = minetest.setting_get
-if minetest.settings then
- setting_getter = function (key)
- return minetest.settings:get(key)
- end
+if not minetest.settings then
+ error("[boost_cart] Your Minetest version is no longer supported."
+ .. " (Version <= 0.4.15)")
+end
+
+local function getNum(setting)
+ return tonumber(minetest.settings:get(setting))
end
-- Maximal speed of the cart in m/s
-boost_cart.speed_max = tonumber(setting_getter("boost_cart.speed_max")) or 10
+boost_cart.speed_max = getNum("boost_cart.speed_max") or 10
-- Set to -1 to disable punching the cart from inside
-boost_cart.punch_speed_max = tonumber(setting_getter("boost_cart.punch_speed_max")) or 7
+boost_cart.punch_speed_max = getNum("boost_cart.punch_speed_max") or 7
+-- Maximal distance for the path correction (for dtime peaks)
+boost_cart.path_distance_max = 3
+
-- Support for non-default games
if not default.player_attached then