Skip to content

Commit ecea536

Browse files
SmallJokerparamat
authored andcommitted
Update carts from boost_cart
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.
1 parent 59dbeeb commit ecea536

File tree

3 files changed

+74
-30
lines changed

3 files changed

+74
-30
lines changed

mods/carts/cart_entity.lua

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ function cart_entity:on_rightclick(clicker)
2727
elseif not self.driver then
2828
self.driver = player_name
2929
carts:manage_attachment(clicker, self.object)
30+
31+
-- player_api does not update the animation
32+
-- when the player is attached, reset to default animation
33+
player_api.set_animation(clicker, "stand")
3034
end
3135
end
3236

@@ -36,7 +40,7 @@ function cart_entity:on_activate(staticdata, dtime_s)
3640
return
3741
end
3842
local data = minetest.deserialize(staticdata)
39-
if not data or type(data) ~= "table" then
43+
if type(data) ~= "table" then
4044
return
4145
end
4246
self.railtype = data.railtype
@@ -52,6 +56,13 @@ function cart_entity:get_staticdata()
5256
})
5357
end
5458

59+
-- 0.5.x and later: When the driver leaves
60+
function cart_entity:on_detach_child(child)
61+
if child and child:get_player_name() == self.driver then
62+
self.driver = nil
63+
end
64+
end
65+
5566
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
5667
local pos = self.object:get_pos()
5768
local vel = self.object:get_velocity()
@@ -82,7 +93,7 @@ function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities,
8293
local player = minetest.get_player_by_name(self.driver)
8394
carts:manage_attachment(player, nil)
8495
end
85-
for _,obj_ in ipairs(self.attached_items) do
96+
for _, obj_ in ipairs(self.attached_items) do
8697
if obj_ then
8798
obj_:set_detach()
8899
end
@@ -165,6 +176,7 @@ local function get_railparams(pos)
165176
return carts.railparams[node.name] or {}
166177
end
167178

179+
local v3_len = vector.length
168180
local function rail_on_step(self, dtime)
169181
local vel = self.object:get_velocity()
170182
if self.punched then
@@ -201,17 +213,23 @@ local function rail_on_step(self, dtime)
201213

202214
local stop_wiggle = false
203215
if self.old_pos and same_dir then
204-
-- Detection for "skipping" nodes
205-
local found_path = carts:pathfinder(
206-
pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype
216+
-- Detection for "skipping" nodes (perhaps use average dtime?)
217+
-- It's sophisticated enough to take the acceleration in account
218+
local acc = self.object:get_acceleration()
219+
local distance = dtime * (v3_len(vel) + 0.5 * dtime * v3_len(acc))
220+
221+
local new_pos, new_dir = carts:pathfinder(
222+
pos, self.old_pos, self.old_dir, distance, ctrl,
223+
self.old_switch, self.railtype
207224
)
208225

209-
if not found_path then
210-
-- No rail found: reset back to the expected position
211-
pos = vector.new(self.old_pos)
226+
if new_pos then
227+
-- No rail found: set to the expected position
228+
pos = new_pos
212229
update.pos = true
230+
cart_dir = new_dir
213231
end
214-
elseif self.old_pos and cart_dir.y ~= -1 and not self.punched then
232+
elseif self.old_pos and self.old_dir.y ~= 1 and not self.punched then
215233
-- Stop wiggle
216234
stop_wiggle = true
217235
end
@@ -223,12 +241,14 @@ local function rail_on_step(self, dtime)
223241
local dir, switch_keys = carts:get_rail_direction(
224242
pos, cart_dir, ctrl, self.old_switch, self.railtype
225243
)
244+
local dir_changed = not vector.equals(dir, self.old_dir)
226245

227246
local new_acc = {x=0, y=0, z=0}
228247
if stop_wiggle or vector.equals(dir, {x=0, y=0, z=0}) then
229248
vel = {x = 0, y = 0, z = 0}
230249
local pos_r = vector.round(pos)
231-
if not carts:is_rail(pos_r, self.railtype) then
250+
if not carts:is_rail(pos_r, self.railtype)
251+
and self.old_pos then
232252
pos = self.old_pos
233253
elseif not stop_wiggle then
234254
pos = pos_r
@@ -239,7 +259,7 @@ local function rail_on_step(self, dtime)
239259
update.vel = true
240260
else
241261
-- Direction change detected
242-
if not vector.equals(dir, self.old_dir) then
262+
if dir_changed then
243263
vel = vector.multiply(dir, math.abs(vel.x + vel.z))
244264
update.vel = true
245265
if dir.y ~= self.old_dir.y then
@@ -291,7 +311,7 @@ local function rail_on_step(self, dtime)
291311
end
292312

293313
self.object:set_acceleration(new_acc)
294-
self.old_pos = vector.new(pos)
314+
self.old_pos = vector.round(pos)
295315
if not vector.equals(dir, {x=0, y=0, z=0}) and not stop_wiggle then
296316
self.old_dir = vector.new(dir)
297317
end
@@ -338,9 +358,15 @@ local function rail_on_step(self, dtime)
338358
end
339359
self.object:set_animation(anim, 1, 0)
340360

341-
self.object:set_velocity(vel)
361+
if update.vel then
362+
self.object:set_velocity(vel)
363+
end
342364
if update.pos then
343-
self.object:set_pos(pos)
365+
if dir_changed then
366+
self.object:set_pos(pos)
367+
else
368+
self.object:move_to(pos)
369+
end
344370
end
345371

346372
-- call event handler

mods/carts/functions.lua

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -99,21 +99,31 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
9999
right.z = -dir.x
100100
end
101101

102+
local straight_priority = ctrl and dir.y ~= 0
103+
104+
-- Normal, to disallow rail switching up- & downhill
105+
if straight_priority then
106+
cur = self:check_front_up_down(pos, dir, true, railtype)
107+
if cur then
108+
return cur
109+
end
110+
end
111+
102112
if ctrl then
103113
if old_switch == 1 then
104114
left_check = false
105115
elseif old_switch == 2 then
106116
right_check = false
107117
end
108118
if ctrl.left and left_check then
109-
cur = carts:check_front_up_down(pos, left, false, railtype)
119+
cur = self:check_front_up_down(pos, left, false, railtype)
110120
if cur then
111121
return cur, 1
112122
end
113123
left_check = false
114124
end
115125
if ctrl.right and right_check then
116-
cur = carts:check_front_up_down(pos, right, false, railtype)
126+
cur = self:check_front_up_down(pos, right, false, railtype)
117127
if cur then
118128
return cur, 2
119129
end
@@ -122,9 +132,11 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
122132
end
123133

124134
-- Normal
125-
cur = carts:check_front_up_down(pos, dir, true, railtype)
126-
if cur then
127-
return cur
135+
if not straight_priority then
136+
cur = self:check_front_up_down(pos, dir, true, railtype)
137+
if cur then
138+
return cur
139+
end
128140
end
129141

130142
-- Left, if not already checked
@@ -158,33 +170,37 @@ function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
158170
return {x=0, y=0, z=0}
159171
end
160172

161-
function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype)
162-
if vector.equals(old_pos, pos_) then
163-
return true
164-
end
173+
function carts:pathfinder(pos_, old_pos, old_dir, distance, ctrl,
174+
pf_switch, railtype)
165175

166176
local pos = vector.round(pos_)
177+
if vector.equals(old_pos, pos) then
178+
return
179+
end
180+
167181
local pf_pos = vector.round(old_pos)
168182
local pf_dir = vector.new(old_dir)
183+
distance = math.min(carts.path_distance_max,
184+
math.floor(distance + 1))
169185

170-
for i = 1, 3 do
171-
pf_dir, pf_switch = carts:get_rail_direction(
172-
pf_pos, pf_dir, ctrl, pf_switch, railtype)
186+
for i = 1, distance do
187+
pf_dir, pf_switch = self:get_rail_direction(
188+
pf_pos, pf_dir, ctrl, pf_switch or 0, railtype)
173189

174190
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
175191
-- No way forwards
176-
return false
192+
return pf_pos, pf_dir
177193
end
178194

179195
pf_pos = vector.add(pf_pos, pf_dir)
180196

181197
if vector.equals(pf_pos, pos) then
182198
-- Success! Cart moved on correctly
183-
return true
199+
return
184200
end
185201
end
186-
-- Cart not found
187-
return false
202+
-- Not found. Put cart to predicted position
203+
return pf_pos, pf_dir
188204
end
189205

190206
function carts:register_rail(name, def_overwrite, railparams)

mods/carts/init.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ carts.railparams = {}
77
carts.speed_max = 7
88
-- Set to -1 to disable punching the cart from inside (min = -1)
99
carts.punch_speed_max = 5
10+
-- Maximal distance for the path correction (for dtime peaks)
11+
carts.path_distance_max = 3
1012

1113

1214
dofile(carts.modpath.."/functions.lua")

0 commit comments

Comments
 (0)