Skip to content

Commit fa0bf3d

Browse files
Merge pull request #182 from konstructs/fix-head-inside-blocks-bug
Fix head inside blocks bug
2 parents 975f062 + 58e5437 commit fa0bf3d

5 files changed

Lines changed: 92 additions & 48 deletions

File tree

src/main.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#define KONSTRUCTS_KEY_RIGHT 'D'
4141
#define KONSTRUCTS_KEY_JUMP GLFW_KEY_SPACE
4242
#define KONSTRUCTS_KEY_FLY GLFW_KEY_TAB
43+
#define KONSTRUCTS_KEY_SNEAK GLFW_KEY_LEFT_SHIFT
4344
#define KONSTRUCTS_KEY_INVENTORY 'E'
4445
using std::cout;
4546
using std::cerr;
@@ -134,7 +135,7 @@ class Konstructs: public nanogui::Screen {
134135
auto &l = *looking_at;
135136
if(button == GLFW_MOUSE_BUTTON_1 && down) {
136137
client.click_at(1, l.second.position, translate_button(button), hud.get_selection());
137-
} else if(button == GLFW_MOUSE_BUTTON_2 && down) {
138+
} else if(button == GLFW_MOUSE_BUTTON_2 && down && player.can_place(l.first.position, world, blocks)) {
138139
optional<ItemStack> selected = hud.selected();
139140
if(selected) {
140141
std::shared_ptr<ChunkData> updated_chunk =
@@ -273,6 +274,7 @@ class Konstructs: public nanogui::Screen {
273274
int sx = 0;
274275
int sz = 0;
275276
bool jump = false;
277+
bool sneak = false;
276278
double now = glfwGetTime();
277279
double dt = now - last_frame;
278280
dt = MIN(dt, 0.2);
@@ -294,8 +296,11 @@ class Konstructs: public nanogui::Screen {
294296
if(glfwGetKey(mGLFWWindow, KONSTRUCTS_KEY_JUMP)) {
295297
jump = true;
296298
}
299+
if(glfwGetKey(mGLFWWindow, KONSTRUCTS_KEY_SNEAK)) {
300+
sneak = true;
301+
}
297302
client.position(player.update_position(sz, sx, (float)dt, world,
298-
blocks, near_distance, jump),
303+
blocks, near_distance, jump, sneak),
299304
player.rx(), player.ry());
300305
}
301306

src/player.cpp

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ namespace konstructs {
1111
static float CAMERA_OFFSET = 0.5f;
1212
static Vector3f CAMERA_OFFSET_VECTOR = Vector3f(0, CAMERA_OFFSET, 0);
1313

14-
Player::Player(const int _id, const Vector3f _position, const float _rx,
15-
const float _ry):
16-
id(_id), position(_position), mrx(_rx), mry(_ry), flying(false), dy(0) {}
14+
Player::Player(const int id, const Vector3f position, const float rx,
15+
const float ry):
16+
id(id), position(position), mrx(rx), mry(ry), flying(false), dy(0) {}
1717

1818
Matrix4f Player::direction() const {
1919
return (Affine3f(AngleAxisf(mrx, Vector3f::UnitX())) *
@@ -43,9 +43,30 @@ namespace konstructs {
4343
return vec;
4444
}
4545

46+
Vector3i Player::feet() const {
47+
return Vector3i(roundf(position[0]), roundf(position[1]) - 1, roundf(position[2]));
48+
}
49+
50+
bool Player::can_place(Vector3i block, const World &world, const BlockData &blocks) {
51+
Vector3i f = feet();
52+
/* Are we trying to place blocks on ourselves? */
53+
if(block(0) == f(0) && block(2) == f(2) && block(1) >= f(1) && block(1) < f(1) + 2) {
54+
/* We may place on our feet under certain circumstances */
55+
if(f(1) == block(1)) {
56+
/* Allow placing on our feet if the block above our head is not an obstacle*/
57+
return !blocks.is_obstacle[world.get_block(Vector3i(f(0), f(1) + 2, f(2)))];
58+
} else {
59+
/* We are never allowed to place on our head */
60+
return false;
61+
}
62+
}
63+
return true;
64+
}
65+
4666
Vector3f Player::update_position(int sz, int sx, float dt,
4767
const World &world, const BlockData &blocks,
48-
const float near_distance, const bool jump) {
68+
const float near_distance, const bool jump,
69+
const bool sneaking) {
4970
float vx = 0, vy = 0, vz = 0;
5071
if (!sz && !sx) { // Not mowing in X or Z
5172
vx = 0;
@@ -114,7 +135,7 @@ namespace konstructs {
114135
dy = std::max(dy, -250.0f);
115136
}
116137
position += Vector3f(vx, vy + dy * ut, vz);
117-
if (collide(world, blocks, near_distance)) {
138+
if (collide(world, blocks, near_distance, sneaking)) {
118139
dy = 0;
119140
}
120141
}
@@ -178,7 +199,8 @@ namespace konstructs {
178199
return mry;
179200
}
180201

181-
int Player::collide(const World &world, const BlockData &blocks, const float near_distance) {
202+
int Player::collide(const World &world, const BlockData &blocks,
203+
const float near_distance, const bool sneaking) {
182204
int result = 0;
183205
float x = position[0];
184206
float y = position[1];
@@ -194,45 +216,54 @@ namespace konstructs {
194216
float py = y - ny;
195217
float pz = z - nz;
196218
float pad = near_distance * 2;
197-
int r = 1;
198-
for (int dp = -r; dp <= r; dp++) {
199-
for (int dq = -r; dq <= r; dq++) {
200-
for (int dk = -r; dk <= r; dk++) {
201-
try {
202-
ChunkData *chunk = world.chunk(Vector3i(p + dp, q + dq, k + dk)).get();
203-
if (blocks.is_obstacle[chunk->get(Vector3i(nx, ny-1, nz))]) {
204-
position[1] += 1.0f;
205-
return 1;
206-
}
207-
for (int dy = 0; dy < height; dy++) {
208-
if (px < -pad && blocks.is_obstacle[chunk->get(Vector3i(nx - 1, ny - dy, nz))]) {
209-
position[0] = nx - pad;
210-
}
211-
if (px > pad && blocks.is_obstacle[chunk->get(Vector3i(nx + 1, ny - dy, nz))]) {
212-
position[0] = nx + pad;
213-
}
214-
if (py < -pad && blocks.is_obstacle[chunk->get(Vector3i(nx, ny - dy - 1, nz))]) {
215-
position[1] = ny - pad;
216-
result = 1;
217-
}
218-
if (py > (pad - CAMERA_OFFSET) && blocks.is_obstacle[chunk->get(Vector3i(nx, ny - dy + 1, nz))]) {
219-
position[1] = ny + pad - CAMERA_OFFSET;
220-
result = 1;
221-
}
222-
if (pz < -pad && blocks.is_obstacle[chunk->get(Vector3i(nx, ny - dy, nz - 1))]) {
223-
position[2] = nz - pad;
224-
}
225-
if (pz > pad && blocks.is_obstacle[chunk->get(Vector3i(nx, ny - dy, nz + 1))]) {
226-
position[2] = nz + pad;
227-
}
228-
}
229-
} catch(std::out_of_range e) {
230-
continue;
231-
}
219+
220+
try {
221+
222+
if (blocks.is_obstacle[world.get_block(feet())]) {
223+
position[1] += 1.0f;
224+
return 1;
225+
}
226+
227+
if(sneaking) {
228+
if (px < -pad && !blocks.is_obstacle[world.get_block(Vector3i(nx - 1, ny - 2, nz))]) {
229+
position[0] = nx - pad;
230+
}
231+
if (px > pad && !blocks.is_obstacle[world.get_block(Vector3i(nx + 1, ny - 2, nz))]) {
232+
position[0] = nx + pad;
233+
}
234+
if (pz < -pad && !blocks.is_obstacle[world.get_block(Vector3i(nx, ny - 2, nz - 1))]) {
235+
position[2] = nz - pad;
236+
}
237+
if (pz > pad && !blocks.is_obstacle[world.get_block(Vector3i(nx, ny - 2, nz + 1))]) {
238+
position[2] = nz + pad;
232239
}
233240
}
241+
for (int dy = 0; dy < height; dy++) {
242+
if (px < -pad && blocks.is_obstacle[world.get_block(Vector3i(nx - 1, ny - dy, nz))]) {
243+
position[0] = nx - pad;
244+
}
245+
if (px > pad && blocks.is_obstacle[world.get_block(Vector3i(nx + 1, ny - dy, nz))]) {
246+
position[0] = nx + pad;
247+
}
248+
if (py < -pad && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy - 1, nz))]) {
249+
position[1] = ny - pad;
250+
result = 1;
251+
}
252+
if (py > (pad - CAMERA_OFFSET) && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy + 1, nz))]) {
253+
position[1] = ny + pad - CAMERA_OFFSET;
254+
result = 1;
255+
}
256+
if (pz < -pad && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy, nz - 1))]) {
257+
position[2] = nz - pad;
258+
}
259+
if (pz > pad && blocks.is_obstacle[world.get_block(Vector3i(nx, ny - dy, nz + 1))]) {
260+
position[2] = nz + pad;
261+
}
262+
}
263+
} catch(std::out_of_range e) {
264+
/* chunk was not loaded yet */
265+
return result;
234266
}
235-
236267
return result;
237268
}
238269
};

src/player.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ namespace konstructs {
1414

1515
class Player {
1616
public:
17-
Player(const int _id, const Vector3f _position,
18-
const float _rx, const float _ry);
17+
Player(const int id, const Vector3f position,
18+
const float rx, const float ry);
1919
Matrix4f direction() const;
2020
Matrix4f translation() const;
2121
Matrix4f view() const;
2222
Vector3f camera() const;
2323
Vector3f camera_direction() const;
24+
Vector3i feet() const;
25+
bool can_place(Vector3i block, const World &world, const BlockData &blocks);
2426
Vector3f update_position(int sz, int sx, float dt,
2527
const World &world, const BlockData &blocks,
26-
const float near_distance, const bool jump);
28+
const float near_distance, const bool jump, const bool sneaking);
2729
optional<pair<Block, Block>> looking_at(const World &world,
2830
const BlockData &blocks) const;
2931
void rotate_x(float speed);
@@ -34,7 +36,8 @@ namespace konstructs {
3436
float ry();
3537
Vector3f position;
3638
private:
37-
int collide(const World &world, const BlockData &blocks, const float near_distance);
39+
int collide(const World &world, const BlockData &blocks,
40+
const float near_distance, const bool sneaking);
3841
float mrx;
3942
float mry;
4043
bool flying;

src/world.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ namespace konstructs {
4444
requested.erase(pos);
4545
}
4646

47+
const char World::get_block(const Vector3i &block_pos) const {
48+
return chunks.at(chunked_vec_int(block_pos))->get(block_pos);
49+
}
50+
4751
const std::shared_ptr<ChunkData> World::chunk_at(const Vector3i &block_pos) const {
4852
return chunks.at(chunked_vec_int(block_pos));
4953
}

src/world.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace konstructs {
1717
bool chunk_updated_since_requested(const Vector3i &pos) const;
1818
void delete_unused_chunks(const Vector3f position, const int radi);
1919
void insert(std::shared_ptr<ChunkData> data);
20+
const char get_block(const Vector3i &block_pos) const;
2021
const std::shared_ptr<ChunkData> chunk_at(const Vector3i &block_pos) const;
2122
const std::shared_ptr<ChunkData> chunk(const Vector3i &chunk_pos) const;
2223
const std::vector<std::shared_ptr<ChunkData>> atAndAround(const Vector3i &pos) const;

0 commit comments

Comments
 (0)