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

Handle Camera's direction and Disconnect Request #56

Merged
merged 5 commits into from
Nov 25, 2024
Merged
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
2 changes: 1 addition & 1 deletion Flakkari/Engine/EntityComponentSystem/Factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void RegistryEntityByTemplate(Registry &registry, Entity entity, const nl_templa
Engine::Math::Vector3f(componentContent["position"]["x"], componentContent["position"]["y"],
componentContent["position"]["z"]);
transform._rotation =
Engine::Math::Vector3f(componentContent["rotation"]["x"], componentContent["rotation"]["y"],
Engine::Math::Vector3d(componentContent["rotation"]["x"], componentContent["rotation"]["y"],
componentContent["rotation"]["z"]);
transform._scale = Engine::Math::Vector3f(componentContent["scale"]["x"], componentContent["scale"]["y"],
componentContent["scale"]["z"]);
Expand Down
48 changes: 30 additions & 18 deletions Flakkari/Engine/Math/Vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ template <typename Type> struct Vector {
return Vector<Type>(v[0] * other.v[0], v[1] * other.v[1], v[2] * other.v[2], v[3] * other.v[3]);
}

Vector<float> multiplyWithFloatVector(const Vector<float> &other) const
{
return Vector<float>((float) v[0] * other.v[0], (float) v[1] * other.v[1], (float) v[2] * other.v[2],
(float) v[3] * other.v[3]);
}

Vector<Type> operator/(const Vector<Type> &other) const
{
return Vector<Type>(v[0] / other.v[0], v[1] / other.v[1], v[2] / other.v[2], v[3] / other.v[3]);
Expand Down Expand Up @@ -193,9 +199,7 @@ template <typename Type> struct Vector {

Type operator[](const int &index) const { return v[index]; }

Type length() const { return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]); }

Type lengthSquared() const { return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]; }
Type length() const { return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); }

Vector<Type> &normalize()
{
Expand All @@ -205,7 +209,6 @@ template <typename Type> struct Vector {
v[0] /= len;
v[1] /= len;
v[2] /= len;
v[3] /= len;
return *this;
}

Expand All @@ -214,7 +217,7 @@ template <typename Type> struct Vector {
Type len = length();
if (len == 0)
return *this;
return Vector<Type>(v[0] / len, v[1] / len, v[2] / len, v[3] / len);
return Vector<Type>(v[0] / len, v[1] / len, v[2] / len);
}

Type dot(const Vector<Type> &other) const
Expand Down Expand Up @@ -307,19 +310,28 @@ template <typename Type> struct Vector {
v[1] = y;
}

void rotate(const Vector<Type> &axis, double angleRadians)
void quaternionRotate(Type x, Type y, Type z, Type w)
{
Type c = cos(angleRadians);
Type s = sin(angleRadians);
Type x = v[0] * (c + axis.x * axis.x * (1 - c)) + v[1] * (axis.x * axis.y * (1 - c) - axis.z * s) +
v[2] * (axis.x * axis.z * (1 - c) + axis.y * s);
Type y = v[0] * (axis.y * axis.x * (1 - c) + axis.z * s) + v[1] * (c + axis.y * axis.y * (1 - c)) +
v[2] * (axis.y * axis.z * (1 - c) - axis.x * s);
Type z = v[0] * (axis.z * axis.x * (1 - c) - axis.y * s) + v[1] * (axis.z * axis.y * (1 - c) + axis.x * s) +
v[2] * (c + axis.z * axis.z * (1 - c));
v[0] = x;
v[1] = y;
v[2] = z;
v[0] = v[3] * x + v[0] * w + v[1] * z - v[2] * y;
v[1] = v[3] * y - v[0] * z + v[1] * w + v[2] * x;
v[2] = v[3] * z + v[0] * y - v[1] * x + v[2] * w;
v[3] = v[3] * w - v[0] * x - v[1] * y - v[2] * z;
}

/**
* @brief Rotate the vector around an axis by an angle in radians.
*
* @param axis The axis to rotate around.
* @param angleRadians The angle in radians.
*/
void rotate(const Vector<Type> &axis, float angleDegrees)
{
double _pi = 3.14159265358979323846;
double angleRadians = (angleDegrees * _pi / 180) / 2.0;
double sinHalfAngle = sin(angleRadians);
auto normalizedAxis = axis.normalized();
quaternionRotate(normalizedAxis.v[0] * sinHalfAngle, normalizedAxis.v[1] * sinHalfAngle,
normalizedAxis.v[2] * sinHalfAngle, cos(angleRadians));
}
};

Expand All @@ -335,7 +347,7 @@ using Vector4f = Vector<float>;
using Vector4d = Vector<double>;
using Vector4i = Vector<int>;
using Vector4u = Vector<unsigned int>;
using Quaternion = Vector4f;
using Quaternion = Vector4d;
using Color = Vector4f;

template <typename Type> std::ostream &operator<<(std::ostream &os, const Vector<Type> &vector);
Expand Down
8 changes: 2 additions & 6 deletions Flakkari/Protocol/Commands.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,8 @@ enum class CommandId : uint8_t {
REQ_ENTITY_SHOOT = 28, // Server -> Client [Shoot entity]: (id)(component (position, rotation, velocity, etc))
REP_ENTITY_SHOOT = 29, // Client -> Server [Entity shot]: ()
// 30 - 39: User
REQ_USER_UPDATE = 30, // Client -> Server [Update user]: (event_id, state)
REP_USER_UPDATE = 31, // Server -> Client [User updated]: ()
REQ_USER_UPDATES = 32, // Client -> Server [Update user multi-events]: (event_id, state|event_id, float)
REP_USER_UPDATES = 33, // Server -> Client [User updated]: ()
REQ_USER_UPDATES = 30, // Client -> Server [Update user multi-events]: (event_id, state|event_id, float)
REP_USER_UPDATES = 31, // Server -> Client [User updated]: ()
// 40 - 49: Chat
// 50 - 59: Matchmaking
REQ_CREATE_ROOM = 50, // Client -> Server [Create room]: (user_id)
Expand Down Expand Up @@ -244,8 +242,6 @@ class Commands final {
case CommandId::REP_ENTITY_MOVED: return "REP_ENTITY_MOVED";
case CommandId::REQ_ENTITY_SHOOT: return "REQ_ENTITY_SHOOT";
case CommandId::REP_ENTITY_SHOOT: return "REP_ENTITY_SHOOT";
case CommandId::REQ_USER_UPDATE: return "REQ_USER_UPDATE";
case CommandId::REP_USER_UPDATE: return "REP_USER_UPDATE";
case CommandId::REQ_USER_UPDATES: return "REQ_USER_UPDATES";
case CommandId::REP_USER_UPDATES: return "REP_USER_UPDATES";
case CommandId::REQ_CREATE_ROOM: return "REQ_CREATE_ROOM";
Expand Down
19 changes: 9 additions & 10 deletions Flakkari/Protocol/Events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,14 @@ enum class EventId : uint8_t {
MOVE_DOWN = 3,
MOVE_FRONT = 4,
MOVE_BACK = 5,
LOOK_LEFT = 6,
LOOK_RIGHT = 7,
LOOK_UP = 8,
LOOK_DOWN = 9,
SHOOT = 10,
MAX_EVENT
};

enum class EventAxisId : uint8_t {
LOOK_LEFT = 1,
LOOK_RIGHT = 2,
LOOK_UP = 3,
LOOK_DOWN = 4,
SHOOT = 5,
MAX_EVENT
};

enum class EventState : uint8_t {
PRESSED = 0,
RELEASED = 1,
Expand All @@ -91,11 +86,15 @@ LPL_PACKED_START
struct Event {
V_1::EventId id;
V_1::EventState state;

void print() const { std::cout << "Event: " << int(id) << " " << int(state) << std::endl; }
};

struct EventAxis {
V_1::EventAxisId id;
V_1::EventId id;
float value;

void print() const { std::cout << "EventAxis: " << int(id) << " " << value << std::endl; }
};

LPL_PACKED_END
Expand Down
2 changes: 1 addition & 1 deletion Flakkari/Protocol/Header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ LPL_PACKED_START
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Priority|Api V.| CommandId | ContentLength |
* |Priority| Api V.| CommandId | ContentLength |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | SequenceNumber |
* | |
Expand Down
2 changes: 1 addition & 1 deletion Flakkari/Protocol/Packet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ template <typename Id> struct Packet {
{
std::string str = "Packet<Id: " + Commands::command_to_string(header._commandId) +
", ContentLength: " + std::to_string(int(header._contentLength)) +
", SequenceNumber: " + std::to_string(int(header._sequenceNumber)) +
", SequenceNumber: " + std::to_string(long(header._sequenceNumber)) +
", Payload: " + std::string((const char *) payload.data(), payload.size()) + ">";
return str;
}
Expand Down
8 changes: 4 additions & 4 deletions Flakkari/Protocol/PacketFactory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,10 @@ class PacketFactory {
packet << transform->_position.vec.x;
packet << transform->_position.vec.y;
packet << transform->_position.vec.z;
packet << transform->_rotation.vec.x;
packet << transform->_rotation.vec.y;
packet << transform->_rotation.vec.z;
packet << transform->_rotation.vec.w;
packet << (float) transform->_rotation.vec.x;
packet << (float) transform->_rotation.vec.y;
packet << (float) transform->_rotation.vec.z;
packet << (float) transform->_rotation.vec.w;
packet << transform->_scale.vec.x;
packet << transform->_scale.vec.y;
packet << transform->_scale.vec.z;
Expand Down
2 changes: 1 addition & 1 deletion Flakkari/Server/Client/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Client::~Client() { _isConnected = false; }

bool Client::isConnected(float timeout)
{
if (!_isConnected)
if (!this || !_isConnected)
return false;
return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - _lastActivity).count() <
timeout;
Expand Down
12 changes: 9 additions & 3 deletions Flakkari/Server/Client/ClientManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void ClientManager::checkInactiveClients()

void ClientManager::sendPacketToClient(const std::shared_ptr<Network::Address> &client, const Network::Buffer &packet)
{
std::thread([this, client, packet] { _socket->sendTo(client, packet); }).detach();
_socket->sendTo(client, packet);
}

void ClientManager::sendPacketToAllClients(const Network::Buffer &packet)
Expand All @@ -110,7 +110,7 @@ void ClientManager::sendPacketToAllClientsExcept(const std::shared_ptr<Network::
}
}

std::optional<std::pair<const std::string &, std::shared_ptr<Client>>>
std::optional<std::pair<std::string, std::shared_ptr<Client>>>
ClientManager::receivePacketFromClient(const std::shared_ptr<Network::Address> &client, const Network::Buffer &buffer)
{
auto clientName = client->toString().value_or("");
Expand All @@ -130,6 +130,13 @@ ClientManager::receivePacketFromClient(const std::shared_ptr<Network::Address> &
if (packet.deserialize(buffer))
{
FLAKKARI_LOG_LOG("Client " + clientName + " sent a valid packet: " + packet.to_string());

if (packet.header._commandId == Protocol::CommandId::REQ_DISCONNECT)
{
FLAKKARI_LOG_LOG("Client " + clientName + " disconnected");
return std::make_pair(tmp_client->getGameName(), tmp_client);
}

tmp_client->addPacketToReceiveQueue(packet);
return std::nullopt;
}
Expand All @@ -143,7 +150,6 @@ ClientManager::receivePacketFromClient(const std::shared_ptr<Network::Address> &

_bannedClients.push_back(ip);
FLAKKARI_LOG_LOG("Client " + clientName + " banned");
_clients.erase(clientName);
return std::make_pair(tmp_client->getGameName(), tmp_client);
}

Expand Down
4 changes: 2 additions & 2 deletions Flakkari/Server/Client/ClientManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ class ClientManager : public Singleton<ClientManager> {
* @param client The client's address
* @param packet The packet received
* @return std::optional<std::pair<const std::string &, std::shared_ptr<Client>>
* The client's name and the client object
* A pair of the client's game name and the client object
*/
std::optional<std::pair<const std::string &, std::shared_ptr<Client>>>
std::optional<std::pair<std::string, std::shared_ptr<Client>>>
receivePacketFromClient(const std::shared_ptr<Network::Address> &client, const Network::Buffer &packet);

/**
Expand Down
63 changes: 42 additions & 21 deletions Flakkari/Server/Game/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void Game::loadSystems(Engine::ECS::Registry &registry, const std::string &scene
registry.add_system(
[this](Engine::ECS::Registry &r) { Engine::ECS::Systems::_3D::apply_movable(r, _deltaTime); });

else if (sysName == "spawn_enemy")
if (sysName == "spawn_enemy")
registry.add_system([this, sceneName](Engine::ECS::Registry &r) {
std::string templateName;
Engine::ECS::Entity entity;
Expand Down Expand Up @@ -182,6 +182,30 @@ void Game::sendOnSameSceneExcept(const std::string &sceneName, Protocol::Packet<
}
}

void Game::sendAllEntitiesToPlayer(std::shared_ptr<Client> player, const std::string &sceneGame)
{
auto &registry = _scenes[sceneGame];
auto &transforms = registry.getComponents<Engine::ECS::Components::_3D::Transform>();
auto &tags = registry.getComponents<Engine::ECS::Components::Common::Tag>();

for (Engine::ECS::Entity i(0); i < transforms.size(); ++i)
{
if (!transforms[i].has_value() || !tags[i].has_value() || i == player->getEntity())
continue;
if (tags[i]->tag == "Skybox")
continue;
Protocol::Packet<Protocol::CommandId> packet;
packet.header._apiVersion = player->getApiVersion();
packet.header._commandId = Protocol::CommandId::REQ_ENTITY_SPAWN;
packet << i;
packet.injectString(tags[i]->tag);

Protocol::PacketFactory::addComponentsToPacketByEntity(packet, registry, i);

player->addPacketToSendQueue(packet);
}
}

void Game::checkDisconnect()
{
for (auto &player : _players)
Expand All @@ -206,10 +230,10 @@ void Game::sendUpdatePosition(std::shared_ptr<Client> player, Engine::ECS::Compo
packet << pos._position.vec.x;
packet << pos._position.vec.y;
packet << pos._position.vec.z;
packet << pos._rotation.vec.x;
packet << pos._rotation.vec.y;
packet << pos._rotation.vec.z;
packet << pos._rotation.vec.w;
packet << (float) pos._rotation.vec.x;
packet << (float) pos._rotation.vec.y;
packet << (float) pos._rotation.vec.z;
packet << (float) pos._rotation.vec.w;
packet << pos._scale.vec.x;
packet << pos._scale.vec.y;
packet << pos._scale.vec.z;
Expand All @@ -236,7 +260,7 @@ static bool handleMoveEvent(Protocol::Event &event, Engine::ECS::Components::_3D
Engine::ECS::Components::_3D::Movable &vel, Engine::ECS::Components::_3D::Transform &pos)
{
auto setAcceleration = [&](const Engine::Math::Vector3f &acceleration) {
vel._acceleration = pos._rotation * acceleration;
vel._acceleration = pos._rotation.multiplyWithFloatVector(acceleration);
};

switch (event.id)
Expand Down Expand Up @@ -332,30 +356,22 @@ void Game::handleEvents(std::shared_ptr<Client> player, Protocol::Packet<Protoco
}

// jump to the first axis event
data += count_events * sizeof(Protocol::Event);
data += count_events * sizeof(Protocol::Event) + sizeof(uint16_t);

for (uint16_t i = 0; i < count_axis; ++i)
{
Protocol::EventAxis event = *(Protocol::EventAxis *) (data + i * sizeof(Protocol::EventAxis));

if (event.id == Protocol::EventAxisId::LOOK_RIGHT && ctrl->_look_right)
{
pos->_rotation.vec.y += event.value * 100 * _deltaTime;
continue;
}
else if (event.id == Protocol::EventAxisId::LOOK_LEFT && ctrl->_look_left)
{
pos->_rotation.vec.y -= event.value * 100 * _deltaTime;
continue;
}
else if (event.id == Protocol::EventAxisId::LOOK_UP && ctrl->_look_up)
if (event.id == Protocol::EventId::LOOK_RIGHT && ctrl->_look_right)
{
pos->_rotation.vec.x += event.value * 100 * _deltaTime;
pos->_rotation.rotate(Engine::Math::Vector3d(0, 0, 1), -event.value);
sendUpdatePosition(player, pos.value(), vel.value());
continue;
}
else if (event.id == Protocol::EventAxisId::LOOK_DOWN && ctrl->_look_down)
else if (event.id == Protocol::EventId::LOOK_UP && ctrl->_look_up)
{
pos->_rotation.vec.x -= event.value * 100 * _deltaTime;
pos->_rotation.rotate(Engine::Math::Vector3d(1, 0, 0), -event.value);
sendUpdatePosition(player, pos.value(), vel.value());
continue;
}
}
Expand Down Expand Up @@ -408,6 +424,9 @@ void Game::updateOutcomingPackets(unsigned char maxMessagePerFrame)
messageCount--;

buffer += packet.serialize();
}
if (buffer.size() > 0)
{
ClientManager::GetInstance().sendPacketToClient(player->getAddress(), buffer);
ClientManager::UnlockInstance();
}
Expand Down Expand Up @@ -487,6 +506,8 @@ bool Game::addPlayer(std::shared_ptr<Client> player)
packet2.injectString(p_Template);

sendOnSameSceneExcept(sceneGame, packet2, player);

sendAllEntitiesToPlayer(player, sceneGame);
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions Flakkari/Server/Game/Game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ class Game {
void sendOnSameSceneExcept(const std::string &sceneName, Protocol::Packet<Protocol::CommandId> &packet,
std::shared_ptr<Client> except);

void sendAllEntitiesToPlayer(std::shared_ptr<Client> player, const std::string &sceneGame);

/**
* @brief Check if a player is disconnected.
*
Expand Down
2 changes: 1 addition & 1 deletion Flakkari/Server/Game/GameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ void GameManager::removeClientFromGame(const std::string &gameName, const std::s
{
_gamesInstances[gameName].pop_back();
FLAKKARI_LOG_INFO("game \"" + gameName + "\" removed");
break;
return;
}
else if (instance->getPlayers().size() > minPlayers)
{
Expand Down
Loading