@@ -48,9 +48,10 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name):
48
48
light_color(255 ,255 ,255 ,255 ),
49
49
m_sneak_node(32767 ,32767 ,32767 ),
50
50
m_sneak_node_exists(false ),
51
+ m_need_to_get_new_sneak_node(true ),
52
+ m_sneak_node_bb_ymax(0 ),
51
53
m_old_node_below(32767 ,32767 ,32767 ),
52
54
m_old_node_below_type(" air" ),
53
- m_need_to_get_new_sneak_node(true ),
54
55
m_can_jump(false ),
55
56
m_cao(NULL )
56
57
{
@@ -179,25 +180,26 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
179
180
If sneaking, keep in range from the last walked node and don't
180
181
fall off from it
181
182
*/
182
- if (control.sneak && m_sneak_node_exists &&
183
+ if (control.sneak && m_sneak_node_exists &&
183
184
!(fly_allowed && g_settings->getBool (" free_move" )) && !in_liquid &&
184
- physics_override_sneak)
185
- {
186
- f32 maxd = 0.5 *BS + sneak_max;
185
+ physics_override_sneak) {
186
+ f32 maxd = 0.5 * BS + sneak_max;
187
187
v3f lwn_f = intToFloat (m_sneak_node, BS);
188
188
position.X = rangelim (position.X , lwn_f.X -maxd, lwn_f.X +maxd);
189
189
position.Z = rangelim (position.Z , lwn_f.Z -maxd, lwn_f.Z +maxd);
190
190
191
- if (!is_climbing)
192
- {
193
- f32 min_y = lwn_f.Y + 0.5 *BS;
194
- if (position.Y < min_y)
195
- {
196
- position.Y = min_y;
197
-
198
- if (m_speed.Y < 0 )
199
- m_speed.Y = 0 ;
200
- }
191
+ if (!is_climbing) {
192
+ // Move up if necessary
193
+ f32 new_y = (lwn_f.Y - 0.5 * BS) + m_sneak_node_bb_ymax;
194
+ if (position.Y < new_y)
195
+ position.Y = new_y;
196
+ /*
197
+ Collision seems broken, since player is sinking when
198
+ sneaking over the edges of current sneaking_node.
199
+ TODO (when fixed): Set Y-speed only to 0 when position.Y < new_y.
200
+ */
201
+ if (m_speed.Y < 0 )
202
+ m_speed.Y = 0 ;
201
203
}
202
204
}
203
205
@@ -230,27 +232,28 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
230
232
player is sneaking from, if any. If the node from under
231
233
the player has been removed, the player falls.
232
234
*/
233
- v3s16 current_node = floatToInt (position - v3f (0 , 0.05 * BS, 0 ), BS);
234
- if (m_sneak_node_exists &&
235
- nodemgr->get (map->getNodeNoEx (m_old_node_below)).name == " air" &&
236
- m_old_node_below_type != " air" )
237
- {
235
+ f32 position_y_mod = 0.05 * BS;
236
+ if (m_sneak_node_bb_ymax > 0 )
237
+ position_y_mod = m_sneak_node_bb_ymax - position_y_mod;
238
+ v3s16 current_node = floatToInt (position - v3f (0 , position_y_mod, 0 ), BS);
239
+ if (m_sneak_node_exists &&
240
+ nodemgr->get (map->getNodeNoEx (m_old_node_below)).name == " air" &&
241
+ m_old_node_below_type != " air" ) {
238
242
// Old node appears to have been removed; that is,
239
243
// it wasn't air before but now it is
240
244
m_need_to_get_new_sneak_node = false ;
241
245
m_sneak_node_exists = false ;
242
- }
243
- else if (nodemgr->get (map->getNodeNoEx (current_node)).name != " air" )
244
- {
246
+ } else if (nodemgr->get (map->getNodeNoEx (current_node)).name != " air" ) {
245
247
// We are on something, so make sure to recalculate the sneak
246
248
// node.
247
249
m_need_to_get_new_sneak_node = true ;
248
250
}
249
- if (m_need_to_get_new_sneak_node && physics_override_sneak)
250
- {
251
- v3s16 pos_i_bottom = floatToInt (position - v3f (0 , 0.05 * BS ,0 ), BS);
251
+
252
+ if (m_need_to_get_new_sneak_node && physics_override_sneak) {
253
+ m_sneak_node_bb_ymax = 0 ;
254
+ v3s16 pos_i_bottom = floatToInt (position - v3f (0 , position_y_mod, 0 ), BS);
252
255
v2f player_p2df (position.X , position.Z );
253
- f32 min_distance_f = 100000.0 * BS;
256
+ f32 min_distance_f = 100000.0 * BS;
254
257
// If already seeking from some node, compare to it.
255
258
/* if(m_sneak_node_exists)
256
259
{
@@ -298,11 +301,24 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
298
301
new_sneak_node = p;
299
302
}
300
303
301
- bool sneak_node_found = (min_distance_f < 100000.0 *BS* 0.9 );
304
+ bool sneak_node_found = (min_distance_f < 100000.0 * BS * 0.9 );
302
305
303
306
m_sneak_node = new_sneak_node;
304
307
m_sneak_node_exists = sneak_node_found;
305
308
309
+ if (sneak_node_found) {
310
+ f32 cb_max = 0 ;
311
+ MapNode n = map->getNodeNoEx (m_sneak_node);
312
+ std::vector<aabb3f> nodeboxes = n.getCollisionBoxes (nodemgr);
313
+ for (std::vector<aabb3f>::iterator it = nodeboxes.begin ();
314
+ it != nodeboxes.end (); ++it) {
315
+ aabb3f box = *it;
316
+ if (box.MaxEdge .Y > cb_max)
317
+ cb_max = box.MaxEdge .Y ;
318
+ }
319
+ m_sneak_node_bb_ymax = cb_max;
320
+ }
321
+
306
322
/*
307
323
If sneaking, the player's collision box can be in air, so
308
324
this has to be set explicitly
0 commit comments