Update carts from boost_cart
authorSmallJoker <SmallJoker@users.noreply.github.com>
Sat, 7 Jul 2018 01:08:36 +0000 (03:08 +0200)
committerParamat <paramat@users.noreply.github.com>
Sat, 7 Jul 2018 01:08:36 +0000 (02:08 +0100)
Better pathfinder algorithm, allows tuning the lag spike compensation.
Smoother movement (when it's laggy).
Set the player animation to stand on attach.
Remove driver when they leave.
Only update velocity when it's necessary.

mods/carts/cart_entity.lua
mods/carts/functions.lua
mods/carts/init.lua

index 434ea943f9b01b41f82697fead530769dfe2ad43..38337dbcb9898685c6c00fc498914337a4797b08 100644 (file)
@@ -27,6 +27,10 @@ function cart_entity:on_rightclick(clicker)
        elseif not self.driver then
                self.driver = player_name
                carts:manage_attachment(clicker, self.object)
+
+               -- player_api does not update the animation
+               -- when the player is attached, reset to default animation
+               player_api.set_animation(clicker, "stand")
        end
 end
 
@@ -36,7 +40,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
@@ -52,6 +56,13 @@ function cart_entity:get_staticdata()
        })
 end
 
+-- 0.5.x and later: When the driver leaves
+function cart_entity:on_detach_child(child)
+       if child and child:get_player_name() == self.driver then
+               self.driver = nil
+       end
+end
+
 function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
        local pos = self.object:get_pos()
        local vel = self.object:get_velocity()
@@ -82,7 +93,7 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
                        local player = minetest.get_player_by_name(self.driver)
                        carts:manage_attachment(player, nil)
                end
-               for _,obj_ in ipairs(self.attached_items) do
+               for _, obj_ in ipairs(self.attached_items) do
                        if obj_ then
                                obj_:set_detach()
                        end
@@ -165,6 +176,7 @@ local function get_railparams(pos)
        return carts.railparams[node.name] or {}
 end
 
+local v3_len = vector.length
 local function rail_on_step(self, dtime)
        local vel = self.object:get_velocity()
        if self.punched then
@@ -201,17 +213,23 @@ local function rail_on_step(self, dtime)
 
        local stop_wiggle = false
        if self.old_pos and same_dir then
-               -- Detection for "skipping" nodes
-               local found_path = carts:pathfinder(
-                       pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype
+               -- Detection for "skipping" nodes (perhaps use average dtime?)
+               -- It's sophisticated enough to take the acceleration in account
+               local acc = self.object:get_acceleration()
+               local distance = dtime * (v3_len(vel) + 0.5 * dtime * v3_len(acc))
+
+               local new_pos, new_dir = carts: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
+       elseif self.old_pos and self.old_dir.y ~= 1 and not self.punched then
                -- Stop wiggle
                stop_wiggle = true
        end
@@ -223,12 +241,14 @@ local function rail_on_step(self, dtime)
        local dir, switch_keys = carts:get_rail_direction(
                pos, cart_dir, ctrl, self.old_switch, self.railtype
        )
+       local dir_changed = not vector.equals(dir, self.old_dir)
 
        local new_acc = {x=0, y=0, z=0}
        if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then
                vel = {x = 0, y = 0, z = 0}
                local pos_r = vector.round(pos)
-               if not carts:is_rail(pos_r, self.railtype) then
+               if not carts:is_rail(pos_r, self.railtype)
+                               and self.old_pos then
                        pos = self.old_pos
                elseif not stop_wiggle then
                        pos = pos_r
@@ -239,7 +259,7 @@ local function rail_on_step(self, dtime)
                update.vel = true
        else
                -- Direction change detected
-               if not vector.equals(dir, self.old_dir) then
+               if dir_changed then
                        vel = vector.multiply(dir, math.abs(vel.x + vel.z))
                        update.vel = true
                        if dir.y ~= self.old_dir.y then
@@ -291,7 +311,7 @@ local function rail_on_step(self, dtime)
        end
 
        self.object:set_acceleration(new_acc)
-       self.old_pos = vector.new(pos)
+       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 = vector.new(dir)
        end
@@ -338,9 +358,15 @@ local function rail_on_step(self, dtime)
        end
        self.object:set_animation(anim, 1, 0)
 
-       self.object:set_velocity(vel)
+       if update.vel then
+               self.object:set_velocity(vel)
+       end
        if update.pos then
-               self.object:set_pos(pos)
+               if dir_changed then
+                       self.object:set_pos(pos)
+               else
+                       self.object:move_to(pos)
+               end
        end
 
        -- call event handler
index 8408cc1a900ce23ed706cd57c3fed682715c5098..a54b5948b60e30fc336b0578a6f35e8b4f1b1167 100644 (file)
@@ -99,6 +99,16 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
                right.z = -dir.x
        end
 
+       local straight_priority = ctrl and dir.y ~= 0
+
+       -- Normal, to disallow rail switching up- & downhill
+       if straight_priority then
+               cur = self:check_front_up_down(pos, dir, true, railtype)
+               if cur then
+                       return cur
+               end
+       end
+
        if ctrl then
                if old_switch == 1 then
                        left_check = false
@@ -106,14 +116,14 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
                        right_check = false
                end
                if ctrl.left and left_check then
-                       cur = carts: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 = carts: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
@@ -122,9 +132,11 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
        end
 
        -- Normal
-       cur = carts:check_front_up_down(pos, dir, true, railtype)
-       if cur then
-               return cur
+       if not straight_priority then
+               cur = self:check_front_up_down(pos, dir, true, railtype)
+               if cur then
+                       return cur
+               end
        end
 
        -- Left, if not already checked
@@ -158,33 +170,37 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
        return {x=0, y=0, z=0}
 end
 
-function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype)
-       if vector.equals(old_pos, pos_) then
-               return true
-       end
+function carts: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(carts.path_distance_max,
+               math.floor(distance + 1))
 
-       for i = 1, 3 do
-               pf_dir, pf_switch = carts: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 carts:register_rail(name, def_overwrite, railparams)
index b2ba5f373992dc37207d49b76f9be57d73047ffe..fe45303ad52a57af1ae1be2d14bd599f77b57db5 100644 (file)
@@ -7,6 +7,8 @@ carts.railparams = {}
 carts.speed_max = 7
 -- Set to -1 to disable punching the cart from inside (min = -1)
 carts.punch_speed_max = 5
+-- Maximal distance for the path correction (for dtime peaks)
+carts.path_distance_max = 3
 
 
 dofile(carts.modpath.."/functions.lua")