Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix server->client jerky movement #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ bool OS::InitializeWindow(

// attach the context
glfwMakeContextCurrent(this->window);

if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
l->critical("[OS] Can initialize glad");
return false;
Expand Down Expand Up @@ -166,7 +166,7 @@ bool OS::InitializeWindow(
glfwSetCharCallback(this->window, &OS::CharacterEventCallback);
glfwSetMouseButtonCallback(this->window, &OS::MouseButtonEventCallback);
glfwSetScrollCallback(this->window, &OS::MouseScrollEventCallback);
glfwSetWindowFocusCallback(this->window, &OS::WindowFocusChangeCallback);
//glfwSetWindowFocusCallback(this->window, &OS::WindowFocusChangeCallback);
glfwSetDropCallback(this->window, &OS::FileDropCallback);

glfwGetCursorPos(this->window, &this->old_mouse_x, &this->old_mouse_y);
Expand Down
2 changes: 1 addition & 1 deletion client/resources/vorbis-stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ std::shared_ptr<VorbisStream> VorbisStream::Create(const Path& filename) {
file = filename.OpenFile();
}
catch (PathException& e) {
_log->warn("[Vorbis-Stream] Can't open file {}", filename);
_log->warn("[Vorbis-Stream] Can't open file {} ({})", filename, e.what());
stream.reset();
return stream;
}
Expand Down
25 changes: 8 additions & 17 deletions common/controllers/fps-controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <commands.pb.h>

#include "event-list.hpp"
#include "events.hpp"
#include "game-state.hpp"
#include "tec-types.hpp"
Expand Down Expand Up @@ -68,29 +69,19 @@ struct FPSController : public Controller {
FPSController(const eid _entity_id) : Controller(_entity_id) {}
~FPSController() override = default;

FPSController(const FPSController& other) = default;
FPSController(const FPSController& other) = default;

FPSController(FPSController&& other) noexcept :
Controller(std::move(other)),
forward(other.forward),
backward(other.backward),
right_strafe(other.right_strafe),
left_strafe(other.left_strafe),
current_delta(other.current_delta),
mouse_look(other.mouse_look),
orientation(other.orientation),
KEY_A_FIRST(other.KEY_A_FIRST),
KEY_W_FIRST(other.KEY_W_FIRST),
KEY_W_DOWN(other.KEY_W_DOWN),
KEY_A_DOWN(other.KEY_A_DOWN),
KEY_S_DOWN(other.KEY_S_DOWN),
KEY_D_DOWN(other.KEY_D_DOWN) {
}
Controller(std::move(other)), forward(other.forward), backward(other.backward),
right_strafe(other.right_strafe), left_strafe(other.left_strafe), current_delta(other.current_delta),
mouse_look(other.mouse_look), orientation(other.orientation), KEY_A_FIRST(other.KEY_A_FIRST),
KEY_W_FIRST(other.KEY_W_FIRST), KEY_W_DOWN(other.KEY_W_DOWN), KEY_A_DOWN(other.KEY_A_DOWN),
KEY_S_DOWN(other.KEY_S_DOWN), KEY_D_DOWN(other.KEY_D_DOWN) {}

FPSController& operator=(const FPSController& other) {
if (this == &other)
return *this;
Controller::operator =(other);
Controller::operator=(other);
forward = other.forward;
backward = other.backward;
right_strafe = other.right_strafe;
Expand Down
72 changes: 72 additions & 0 deletions common/event-list.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#pragma once

#include "events.hpp"
#include <list>

namespace tec {
struct EventList {
std::list<KeyboardEvent> keyboard_events;
std::list<MouseBtnEvent> mouse_button_events;
std::list<MouseMoveEvent> mouse_move_events;
std::list<MouseClickEvent> mouse_click_events;

EventList() {}

EventList(const EventList&) = delete;
EventList(EventList&& other) noexcept {
this->keyboard_events = std::move(other.keyboard_events);
this->mouse_button_events = std::move(other.mouse_button_events);
this->mouse_move_events = std::move(other.mouse_move_events);
this->mouse_click_events = std::move(other.mouse_click_events);
}

EventList& operator=(const EventList& other) = delete;
EventList& operator=(EventList&& other) noexcept {
if (this != &other) {
this->keyboard_events = std::move(other.keyboard_events);
this->mouse_button_events = std::move(other.mouse_button_events);
this->mouse_move_events = std::move(other.mouse_move_events);
this->mouse_click_events = std::move(other.mouse_click_events);
}
return *this;
}

EventList CollectEvents() {
EventList event_list;

// Combine identical keyboard events
for (const auto& event : keyboard_events) {
auto it = std::find(event_list.keyboard_events.begin(), event_list.keyboard_events.end(), event);
if (it == event_list.keyboard_events.end()) {
event_list.keyboard_events.push_back(event);
}
}

// Combine identical mouse button events
for (const auto& event : mouse_button_events) {
auto it = std::find(event_list.mouse_button_events.begin(), event_list.mouse_button_events.end(), event);
if (it == event_list.mouse_button_events.end()) {
event_list.mouse_button_events.push_back(event);
}
}

// Combine identical mouse move events
for (const auto& event : mouse_move_events) {
auto it = std::find(event_list.mouse_move_events.begin(), event_list.mouse_move_events.end(), event);
if (it == event_list.mouse_move_events.end()) {
event_list.mouse_move_events.push_back(event);
}
}

// Combine identical mouse click events
for (const auto& event : mouse_click_events) {
auto it = std::find(event_list.mouse_click_events.begin(), event_list.mouse_click_events.end(), event);
if (it == event_list.mouse_click_events.end()) {
event_list.mouse_click_events.push_back(event);
}
}

return event_list;
}
};
} // namespace tec
16 changes: 16 additions & 0 deletions common/events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,31 @@ struct KeyboardEvent {
int scancode{0};
KEY_ACTION action;
int mods{0};

bool operator==(const KeyboardEvent& other) const {
return key == other.key && scancode == other.scancode && action == other.action && mods == other.mods;
}
};

struct MouseBtnEvent {
enum MOUSE_BTN_ACTION { DOWN, UP };
enum MOUSE_BTN { LEFT, RIGHT, MIDDLE };
MOUSE_BTN_ACTION action;
MOUSE_BTN button;

bool operator==(const MouseBtnEvent& other) const { return action == other.action && button == other.button; }
};

/** Mouse change of position event */
struct MouseMoveEvent {
double norm_x{0.0}, norm_y{0.0}; /// Resolution independent new x, y (0-1) from upper-left to lower-right.
int old_x{0}, old_y{0}; /// Client space old x, y.
int new_x{0}, new_y{0}; /// Client space new x, y.

bool operator==(const MouseMoveEvent& other) const {
return norm_x == other.norm_x && norm_y == other.norm_y && old_x == other.old_x && old_y == other.old_y
&& new_x == other.new_x && new_y == other.new_y;
}
};

/** Mouse wheel event */
Expand All @@ -43,6 +54,11 @@ struct MouseClickEvent {
MouseBtnEvent::MOUSE_BTN button;
glm::vec3 ray_hit_point_world{0.f, 0.f, 0.f};
double ray_distance;

bool operator==(const MouseClickEvent& other) const {
return button == other.button && ray_hit_point_world == other.ray_hit_point_world
&& ray_distance == other.ray_distance;
}
};

struct WindowResizedEvent {
Expand Down
27 changes: 0 additions & 27 deletions common/game-state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,31 +125,4 @@ struct NewGameStateEvent {
GameState new_state;
};

struct EventList {
std::list<KeyboardEvent> keyboard_events;
std::list<MouseBtnEvent> mouse_button_events;
std::list<MouseMoveEvent> mouse_move_events;
std::list<MouseClickEvent> mouse_click_events;

EventList() {}

EventList(const EventList&) = delete;
EventList(EventList&& other) noexcept {
this->keyboard_events = std::move(other.keyboard_events);
this->mouse_button_events = std::move(other.mouse_button_events);
this->mouse_move_events = std::move(other.mouse_move_events);
this->mouse_click_events = std::move(other.mouse_click_events);
}

EventList& operator=(const EventList& other) = delete;
EventList& operator=(EventList&& other) noexcept {
if (this != &other) {
this->keyboard_events = std::move(other.keyboard_events);
this->mouse_button_events = std::move(other.mouse_button_events);
this->mouse_move_events = std::move(other.mouse_move_events);
this->mouse_click_events = std::move(other.mouse_click_events);
}
return *this;
}
};
} // namespace tec
12 changes: 0 additions & 12 deletions common/physics-system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,6 @@
}
else {
btTransform& body_transform = body->getWorldTransform();
// simulation motion estimation lite
// on the server, this doesn't really do anything
// on the client however, this smooths out the motion between the local estimation and server state
// this provides a crude but effective error correction until a better one is added ;)
if (body_transform.getOrigin().distance(collidable->motion_state.transform.getOrigin()) > 0.01) {
// FIXME there is a race condition outside of PhysicsSystem, where the position of the entity
// is momentarily at origin (0,0,0) during entity creation (affects server)
body->translate(0.5 * (collidable->motion_state.transform.getOrigin() - body_transform.getOrigin()));
// use this to snap back to the current state, it's unpleasent without any form of restitution
//body_transform.setOrigin(collidable->motion_state.transform.getOrigin());
}
// for now, just always update the orientation
body_transform.setBasis(collidable->motion_state.transform.getBasis());
}

Expand Down Expand Up @@ -254,7 +242,7 @@

eid PhysicsSystem::RayCastIgnore(eid source_entity, eid ignore_entity) {
last_rayvalid = false;
glm::vec3 position;

Check warning on line 245 in common/physics-system.cpp

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, x64)

‘position.glm::vec<3, float, glm::packed_highp>::<anonymous>.glm::vec<3, float, glm::packed_highp>::<unnamed union>::y’ may be used uninitialized in this function [-Wmaybe-uninitialized]

Check warning on line 245 in common/physics-system.cpp

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, x64)

‘position.glm::vec<3, float, glm::packed_highp>::<anonymous>.glm::vec<3, float, glm::packed_highp>::<unnamed union>::x’ may be used uninitialized in this function [-Wmaybe-uninitialized]

Check warning on line 245 in common/physics-system.cpp

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, x64)

‘position.glm::vec<3, float, glm::packed_highp>::<anonymous>.glm::vec<3, float, glm::packed_highp>::<unnamed union>::y’ may be used uninitialized in this function [-Wmaybe-uninitialized]

Check warning on line 245 in common/physics-system.cpp

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, x64)

‘position.glm::vec<3, float, glm::packed_highp>::<anonymous>.glm::vec<3, float, glm::packed_highp>::<unnamed union>::x’ may be used uninitialized in this function [-Wmaybe-uninitialized]
if (Entity(source_entity).Has<Position>()) {
position = (Entity(source_entity).Get<Position>())->value;
}
Expand Down
1 change: 1 addition & 0 deletions common/simulation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <queue>
#include <thread>

#include "event-list.hpp"
#include "event-queue.hpp"
#include "physics-system.hpp"
#include "vcomputer-system.hpp"
Expand Down
2 changes: 1 addition & 1 deletion server/save-game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ bool SaveGame::Save(const Path _filepath) {
return SaveFromString(_filepath, json_string);
}
catch (std::runtime_error& err) {
_log->error("Failed to save to file: {:f}", _filepath);
_log->error("Failed to save to file: {:f} ({})", _filepath, err.what());
return false;
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_program(
TARGET
${trillek-test_PROGRAM_NAME}
FILE_LIST
event-list-test.cpp
filesystem_test.cpp
net-message_test.cpp
save-game_test.cpp
Expand Down
35 changes: 35 additions & 0 deletions tests/event-list-test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "event-list.hpp"
#include <gtest/gtest.h>

namespace tec {

TEST(EventListTests, CollectEvents) {
EventList event_list;

KeyboardEvent key_event1{1, 1, KeyboardEvent::KEY_DOWN, 0};
KeyboardEvent key_event2{1, 1, KeyboardEvent::KEY_DOWN, 0};
MouseBtnEvent mouse_btn_event1{MouseBtnEvent::DOWN, MouseBtnEvent::LEFT};
MouseBtnEvent mouse_btn_event2{MouseBtnEvent::DOWN, MouseBtnEvent::LEFT};
MouseMoveEvent mouse_move_event1{0.5, 0.5, 0, 0, 100, 100};
MouseMoveEvent mouse_move_event2{0.5, 0.5, 0, 0, 100, 100};
MouseClickEvent mouse_click_event1{MouseBtnEvent::LEFT, {0.f, 0.f, 0.f}, 1.0};
MouseClickEvent mouse_click_event2{MouseBtnEvent::LEFT, {0.f, 0.f, 0.f}, 1.0};

event_list.keyboard_events.push_back(key_event1);
event_list.keyboard_events.push_back(key_event2);
event_list.mouse_button_events.push_back(mouse_btn_event1);
event_list.mouse_button_events.push_back(mouse_btn_event2);
event_list.mouse_move_events.push_back(mouse_move_event1);
event_list.mouse_move_events.push_back(mouse_move_event2);
event_list.mouse_click_events.push_back(mouse_click_event1);
event_list.mouse_click_events.push_back(mouse_click_event2);

EventList collected_events = event_list.CollectEvents();

EXPECT_EQ(collected_events.keyboard_events.size(), 1);
EXPECT_EQ(collected_events.mouse_button_events.size(), 1);
EXPECT_EQ(collected_events.mouse_move_events.size(), 1);
EXPECT_EQ(collected_events.mouse_click_events.size(), 1);
}

} // namespace tec
Loading