@@ -68,7 +68,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name):
68
68
m_sneak_node(32767 ,32767 ,32767 ),
69
69
m_sneak_node_exists(false ),
70
70
m_need_to_get_new_sneak_node(true ),
71
- m_sneak_node_bb_ymax( 0 ),
71
+ m_sneak_node_bb_top( 0 , 0 , 0 , 0 , 0 , 0 ),
72
72
m_old_node_below(32767 ,32767 ,32767 ),
73
73
m_old_node_below_type(" air" ),
74
74
m_can_jump(false ),
@@ -91,6 +91,21 @@ LocalPlayer::~LocalPlayer()
91
91
{
92
92
}
93
93
94
+ static aabb3f getTopBoundingBox (const std::vector<aabb3f> &nodeboxes, float max_d=1 /16 *BS)
95
+ {
96
+ aabb3f b_max;
97
+ b_max.reset (-BS, -BS, -BS);
98
+ for (std::vector<aabb3f>::const_iterator it = nodeboxes.begin ();
99
+ it != nodeboxes.end (); ++it) {
100
+ aabb3f box = *it;
101
+ if (box.MaxEdge .Y > b_max.MaxEdge .Y )
102
+ b_max = box;
103
+ else if (box.MaxEdge .Y == b_max.MaxEdge .Y )
104
+ b_max.addInternalBox (box);
105
+ }
106
+ return aabb3f (v3f (b_max.MinEdge .X , b_max.MaxEdge .Y , b_max.MinEdge .Z ), b_max.MaxEdge );
107
+ }
108
+
94
109
void LocalPlayer::move (f32 dtime, Environment *env, f32 pos_max_d,
95
110
std::vector<CollisionInfo> *collision_info)
96
111
{
@@ -198,8 +213,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
198
213
// This should always apply, otherwise there are glitches
199
214
sanity_check (d > pos_max_d);
200
215
201
- // Maximum distance over border for sneaking
202
- f32 sneak_max = BS*0.4 ;
216
+ // Max. distance (X, Z) over border for sneaking determined by collision box
217
+ // * 0.49 to keep the center just barely on the node
218
+ v3f sneak_max = m_collisionbox.getExtent () * 0.49 ;
203
219
204
220
/*
205
221
If sneaking, keep in range from the last walked node and don't
@@ -208,30 +224,22 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
208
224
if (control.sneak && m_sneak_node_exists &&
209
225
!(fly_allowed && g_settings->getBool (" free_move" )) && !in_liquid &&
210
226
physics_override_sneak && !got_teleported) {
211
- f32 maxd = 0.5 * BS + sneak_max;
212
- v3f lwn_f = intToFloat (m_sneak_node, BS);
213
- position.X = rangelim (position.X , lwn_f.X -maxd, lwn_f.X +maxd);
214
- position.Z = rangelim (position.Z , lwn_f.Z -maxd, lwn_f.Z +maxd);
215
-
216
- if (!is_climbing) {
217
- // Move up if necessary
218
- f32 new_y = (lwn_f.Y - 0.5 * BS) + m_sneak_node_bb_ymax;
219
- if (position.Y < new_y)
220
- position.Y = new_y;
221
- /*
222
- Collision seems broken, since player is sinking when
223
- sneaking over the edges of current sneaking_node.
224
- TODO (when fixed): Set Y-speed only to 0 when position.Y < new_y.
225
- */
226
- if (m_speed.Y < 0 )
227
- m_speed.Y = 0 ;
228
- }
227
+ v3f sn_f = intToFloat (m_sneak_node, BS);
228
+ const v3f bmin = m_sneak_node_bb_top.MinEdge ;
229
+ const v3f bmax = m_sneak_node_bb_top.MaxEdge ;
230
+
231
+ position.X = rangelim (position.X ,
232
+ sn_f.X +bmin.X - sneak_max.X , sn_f.X +bmax.X + sneak_max.X );
233
+ position.Z = rangelim (position.Z ,
234
+ sn_f.Z +bmin.Z - sneak_max.Z , sn_f.Z +bmax.Z + sneak_max.Z );
235
+ // Because we keep the player collision box on the node,
236
+ // limiting position.Y is not necessary
229
237
}
230
238
231
239
if (got_teleported)
232
240
got_teleported = false ;
233
241
234
- // this shouldn't be hardcoded but transmitted from server
242
+ // TODO: this shouldn't be hardcoded but transmitted from server
235
243
float player_stepheight = touching_ground ? (BS*0.6 ) : (BS*0.2 );
236
244
237
245
#ifdef __ANDROID__
@@ -255,15 +263,18 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
255
263
256
264
// bool standing_on_unloaded = result.standing_on_unloaded;
257
265
266
+ // We want the top of the sneak node to be below the players feet
267
+ f32 position_y_mod;
268
+ if (m_sneak_node_exists)
269
+ position_y_mod = m_sneak_node_bb_top.MaxEdge .Y - 0.05 * BS;
270
+ else
271
+ position_y_mod = (1.0 - 0.05 ) * BS;
272
+ v3s16 current_node = floatToInt (position - v3f (0 , position_y_mod, 0 ), BS);
258
273
/*
259
274
Check the nodes under the player to see from which node the
260
275
player is sneaking from, if any. If the node from under
261
276
the player has been removed, the player falls.
262
277
*/
263
- f32 position_y_mod = 0.05 * BS;
264
- if (m_sneak_node_bb_ymax > 0 )
265
- position_y_mod = m_sneak_node_bb_ymax - position_y_mod;
266
- v3s16 current_node = floatToInt (position - v3f (0 , position_y_mod, 0 ), BS);
267
278
if (m_sneak_node_exists &&
268
279
nodemgr->get (map->getNodeNoEx (m_old_node_below)).name == " air" &&
269
280
m_old_node_below_type != " air" ) {
@@ -278,21 +289,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
278
289
}
279
290
280
291
if (m_need_to_get_new_sneak_node && physics_override_sneak) {
281
- m_sneak_node_bb_ymax = 0 ;
282
292
v3s16 pos_i_bottom = floatToInt (position - v3f (0 , position_y_mod, 0 ), BS);
283
293
v2f player_p2df (position.X , position.Z );
284
294
f32 min_distance_f = 100000.0 * BS;
285
- // If already seeking from some node, compare to it.
286
- /* if(m_sneak_node_exists)
287
- {
288
- v3f sneaknode_pf = intToFloat(m_sneak_node, BS);
289
- v2f sneaknode_p2df(sneaknode_pf.X, sneaknode_pf.Z);
290
- f32 d_horiz_f = player_p2df.getDistanceFrom(sneaknode_p2df);
291
- f32 d_vert_f = fabs(sneaknode_pf.Y + BS*0.5 - position.Y);
292
- // Ignore if player is not on the same level (likely dropped)
293
- if(d_vert_f < 0.15*BS)
294
- min_distance_f = d_horiz_f;
295
- }*/
296
295
v3s16 new_sneak_node = m_sneak_node;
297
296
for (s16 x=-1 ; x<=1 ; x++)
298
297
for (s16 z=-1 ; z<=1 ; z++)
@@ -301,12 +300,10 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
301
300
v3f pf = intToFloat (p, BS);
302
301
v2f node_p2df (pf.X , pf.Z );
303
302
f32 distance_f = player_p2df.getDistanceFrom (node_p2df);
304
- f32 max_axis_distance_f = MYMAX (
305
- fabs (player_p2df.X -node_p2df.X ),
306
- fabs (player_p2df.Y -node_p2df.Y ));
307
303
308
- if (distance_f > min_distance_f ||
309
- max_axis_distance_f > 0.5 *BS + sneak_max + 0.1 *BS)
304
+ if (distance_f > min_distance_f ||
305
+ fabs (player_p2df.X -node_p2df.X ) > (.5 +.1 )*BS + sneak_max.X ||
306
+ fabs (player_p2df.Y -node_p2df.Y ) > (.5 +.1 )*BS + sneak_max.Z )
310
307
continue ;
311
308
312
309
@@ -316,11 +313,10 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
316
313
continue ;
317
314
// And the node above it has to be nonwalkable
318
315
node = map->getNodeNoEx (p + v3s16 (0 ,1 ,0 ), &is_valid_position);
319
- if (!is_valid_position || nodemgr->get (node).walkable ) {
316
+ if (!is_valid_position || nodemgr->get (node).walkable )
320
317
continue ;
321
- }
322
318
if (!physics_override_sneak_glitch) {
323
- node =map->getNodeNoEx (p + v3s16 (0 ,2 ,0 ), &is_valid_position);
319
+ node = map->getNodeNoEx (p + v3s16 (0 ,2 ,0 ), &is_valid_position);
324
320
if (!is_valid_position || nodemgr->get (node).walkable )
325
321
continue ;
326
322
}
@@ -329,31 +325,17 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
329
325
new_sneak_node = p;
330
326
}
331
327
332
- bool sneak_node_found = (min_distance_f < 100000.0 * BS * 0.9 );
333
-
328
+ bool sneak_node_found = (min_distance_f < 100000.0 * BS);
334
329
m_sneak_node = new_sneak_node;
335
330
m_sneak_node_exists = sneak_node_found;
336
331
332
+ // Update saved top bounding box of sneak node
337
333
if (sneak_node_found) {
338
- f32 cb_max = 0 ;
339
334
MapNode n = map->getNodeNoEx (m_sneak_node);
340
335
std::vector<aabb3f> nodeboxes;
341
336
n.getCollisionBoxes (nodemgr, &nodeboxes);
342
- for (std::vector<aabb3f>::iterator it = nodeboxes.begin ();
343
- it != nodeboxes.end (); ++it) {
344
- aabb3f box = *it;
345
- if (box.MaxEdge .Y > cb_max)
346
- cb_max = box.MaxEdge .Y ;
347
- }
348
- m_sneak_node_bb_ymax = cb_max;
337
+ m_sneak_node_bb_top = getTopBoundingBox (nodeboxes);
349
338
}
350
-
351
- /*
352
- If sneaking, the player's collision box can be in air, so
353
- this has to be set explicitly
354
- */
355
- if (sneak_node_found && control.sneak )
356
- touching_ground = true ;
357
339
}
358
340
359
341
/*
2 commit comments
Brackston commentedon Mar 20, 2017
This move to remove the sneak is wrong. while I can appreciate the need to fix some of the mis-uses of sneak, don't disable a feature used daily by hundreds of players. The sneak ladder is realistic in climbing. what you have done is ruin the game for many of us players.
If we all use hacked clients in the future, will we retain the ability to have NORMAL mobility?
We don't have many players as it is and sneak was a feature that got me to leave MC and come to minetest. I am afraid we will loose more players now. Sorry if I commented in th wrong place, I just signed up to github to make a comment someplace and basically the site is confusing.
paramat commentedon Mar 20, 2017
The best place to discuss is here #5327 i recommend reading the discussion.
Climbing using handholds cut into walls is reasonable, but the speed of 6n/s (sprinting speed) was not (and was not realistic) and was out of balance with the more realistic speeds used elsewhere in MT.
Mods are being written right now to act as replacements, i recommend using these when they appear.