28 Commits

Author SHA1 Message Date
5cfdd63cb6 entitities 2024-03-09 14:53:48 +01:00
2cb5074140 better server logs 2024-03-09 11:01:30 +01:00
269ac16d28 more precise logging 2024-03-08 22:59:50 +01:00
b7926d7a98 pretty log 2024-03-08 22:57:38 +01:00
52da1cf19b explicit server in logs 2024-03-07 23:10:37 +01:00
2da89c8dab xmake: remove global include 2024-03-07 21:12:41 +01:00
88cb433ecf xmake: relative paths 2024-03-07 21:03:23 +01:00
d96b01074e split xmake targets 2024-03-07 20:50:14 +01:00
a1effa05cd remove github ci 2024-03-07 20:14:12 +01:00
7b58117f36 fix warnings 2024-03-07 20:13:05 +01:00
bf8a6458a0 valgrind full info 2024-03-05 12:30:09 +01:00
18ddede8c0 add shoot 2024-03-05 12:29:39 +01:00
d3467418c7 Merge branch 'main' of github.com:Persson-dev/Blitz 2024-03-05 09:01:15 +01:00
d98939cb31 remove useless add_requires 2024-03-05 08:39:24 +01:00
0d039caa0e Merge branch 'weirdshoot' 2024-03-05 08:38:34 +01:00
848f12e58b Vecxuc wrong type 2024-02-27 12:15:35 +01:00
ce249359c6 non copyable classes 2024-02-26 11:27:16 +01:00
9591836074 add valgrind test 2024-01-30 09:14:07 +01:00
7305051062 fix memory warnings 2024-01-30 08:53:26 +01:00
617e1fa95e branchless 2024-01-28 19:09:30 +01:00
73b4539e8d add gun animation 2024-01-28 18:30:16 +01:00
de3ff4326a CooldownTimer to template 2024-01-28 18:29:55 +01:00
51f046f44e fix compile error 2024-01-27 20:12:14 +01:00
3b5208aeba clamp horizonal movement vector norm to 1 (fix diagonal movement speed increase) 2024-01-27 20:10:10 +01:00
a40cd1cd61 change smoothing time const names 2024-01-27 19:11:04 +01:00
1ccf525dd6 fix wrong filter equation 2024-01-27 19:08:56 +01:00
b345d6eb49 fixed-alpha movement smoothing 2024-01-27 17:54:26 +01:00
a7dbf69a4a oooo? 2024-01-27 17:48:37 +01:00
72 changed files with 642 additions and 345 deletions

View File

@@ -1,32 +0,0 @@
name: macOS
on:
pull_request:
push:
branches: main
jobs:
build:
strategy:
fail-fast: false
runs-on: macos-latest
concurrency:
group: ${{ github.ref }}-${{ github.base_ref }}-${{ github.head_ref }}-macOS
cancel-in-progress: true
steps:
- uses: actions/checkout@v1
- uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: branch@master
- name: Prepare XMake
run: xmake f -p macosx -y
- name: Build
run: xmake
- name: Test
run: xmake test

View File

@@ -1,42 +0,0 @@
name: Windows
on:
pull_request:
push:
branches: main
jobs:
build:
strategy:
fail-fast: false
matrix:
arch: [x64, x86]
vs_runtime: [MT, MD]
runs-on: windows-latest
concurrency:
group: ${{ github.ref }}-${{ github.base_ref }}-${{ github.head_ref }}-Windows-${{ matrix.arch }}-${{ matrix.vs_runtime }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v1
- uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: branch@master
- name: Configure Pagefile
uses: al-cheb/configure-pagefile-action@v1.2
with:
minimum-size: 8GB
maximum-size: 32GB
disk-root: "D:"
- name: Prepare XMake
run: xmake f -p windows -a ${{ matrix.arch }} --vs_runtime=${{ matrix.vs_runtime }} -y
- name: Build
run: xmake
- name: Test
run: xmake test

View File

@@ -10,11 +10,17 @@
namespace blitz {
namespace game {
/**
* \typedef EntityID
* \brief Represents the identifier of an Entity
*/
typedef std::uint32_t EntityID;
/**
* \typedef PlayerID
* \brief Represents the identifier of a Player
*/
typedef std::uint8_t PlayerID;
typedef EntityID PlayerID;
} // namespace game
} // namespace blitz

View File

@@ -0,0 +1,15 @@
#pragma once
namespace blitz {
class NonCopyable {
public:
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
protected:
NonCopyable() {}
~NonCopyable() {}
};
} // namespace blitz

View File

@@ -81,19 +81,19 @@ struct Vec4 {
using Vec2uc = Vec2<unsigned int>;
using Vec2uc = Vec2<unsigned char>;
using Vec2i = Vec2<int>;
using Vec2u = Vec2<unsigned int>;
using Vec2f = Vec2<float>;
using Vec2d = Vec2<double>;
using Vec3uc = Vec3<unsigned int>;
using Vec3uc = Vec3<unsigned char>;
using Vec3i = Vec3<int>;
using Vec3u = Vec3<unsigned int>;
using Vec3f = Vec3<float>;
using Vec3d = Vec3<double>;
using Vec4uc = Vec4<unsigned int>;
using Vec4uc = Vec4<unsigned char>;
using Vec4i = Vec4<int>;
using Vec4u = Vec4<unsigned int>;
using Vec4f = Vec4<float>;

View File

@@ -1,19 +1,22 @@
#pragma once
#include "Player.h"
#include "World.h"
#include <map>
namespace blitz {
namespace game {
typedef std::map<PlayerID, Player> PlayerMap;
class Player;
typedef std::map<PlayerID, Player*> PlayerMap;
class Game {
private:
PlayerMap m_Players;
World* m_World;
public:
Game() {}
Game(World* world) : m_World(world) {}
virtual void Tick(std::uint64_t delta) = 0;
@@ -28,7 +31,7 @@ class Game {
return m_Players;
}
void AddPlayer(PlayerID player, const std::string& name);
Player* AddPlayer(PlayerID player, const std::string& name);
void RemovePlayer(PlayerID player);
};

View File

@@ -0,0 +1,15 @@
#pragma once
#include "blitz/common/Vector.h"
namespace blitz {
namespace game {
class PlayerInputListener {
public:
virtual void OnPlayerJump() {}
virtual void OnPlayerShoot(const Vec3f& position, float yaw, float pitch) {}
};
} // namespace game
} // namespace blitz

View File

@@ -0,0 +1,29 @@
#pragma once
#include "blitz/game/entity/Entity.h"
#include <memory>
#include <vector>
namespace blitz {
namespace game {
class Player;
typedef std::unique_ptr<Entity> EntityPtr;
typedef std::vector<EntityPtr> EntityList;
class World {
protected:
EntityList m_Entities;
public:
World() {}
game::Player* CreatePlayer(PlayerID id);
Entity* GetEntityByID(EntityID id);
const Entity* GetEntityByID(EntityID id) const;
};
} // namespace game
} // namespace blitz

View File

@@ -0,0 +1,46 @@
#pragma once
#include "blitz/common/Defines.h"
#include "blitz/common/Vector.h"
namespace blitz {
namespace game {
class Entity {
protected:
EntityID m_ID;
Vec3f m_Position{};
Vec3f m_Velocity{};
Entity(EntityID id) : m_ID(id) {}
public:
virtual ~Entity() {}
EntityID GetID() const {
return m_ID;
}
const Vec3f& GetPosition() const {
return m_Position;
}
void SetPosition(const Vec3f& newPos) {
m_Position = newPos;
}
void AddPosition(const Vec3f& dPos) {
m_Position += dPos;
}
const Vec3f& GetVelocity() const {
return m_Velocity;
}
void SetVelocity(const Vec3f& newVelocity) {
m_Velocity = newVelocity;
}
};
} // namespace game
} // namespace blitz

View File

@@ -0,0 +1,21 @@
#pragma once
#include "Entity.h"
namespace blitz {
namespace game {
class HitScanBullet : public Entity {
private:
PlayerID m_Shooter;
public:
HitScanBullet(EntityID id, PlayerID shooter) : Entity(id), m_Shooter(shooter) {}
PlayerID GetShooter() const {
return m_Shooter;
}
};
} // namespace game
} // namespace blitz

View File

@@ -1,28 +1,20 @@
#pragma once
#include "blitz/common/Defines.h"
#include "blitz/common/Vector.h"
#include "blitz/game/entity/Entity.h"
#include <cstdint>
#include <string>
namespace blitz {
namespace game {
class Player {
class Player : public Entity {
private:
PlayerID m_ID;
std::string m_Name;
Vec3f m_Position;
Vec3f m_Velocity;
float m_Yaw;
float m_Pitch;
public:
Player(PlayerID id) : m_ID(id), m_Yaw(0), m_Pitch(0) {}
PlayerID GetID() const {
return m_ID;
}
Player(PlayerID id) : Entity(id), m_Yaw(0), m_Pitch(0) {}
const std::string& GetName() const {
return m_Name;
@@ -32,26 +24,6 @@ class Player {
m_Name = name;
}
const Vec3f& GetPosition() const {
return m_Position;
}
void SetPosition(const Vec3f& newPos) {
m_Position = newPos;
}
void AddPosition(const Vec3f& dPos) {
m_Position += dPos;
}
const Vec3f& GetVelocity() const {
return m_Velocity;
}
void SetVelocity(const Vec3f& newVelocity) {
m_Velocity = newVelocity;
}
float GetYaw() const {
return m_Yaw;
}

View File

@@ -1,5 +0,0 @@
#pragma once
#define REMOVE_COPY(className) \
className(const className&) = delete; \
className& operator=(const className&) = delete

View File

@@ -0,0 +1,25 @@
#pragma once
#include "blitz/common/Vector.h"
#include <string>
namespace blitz {
namespace utils {
namespace TextColor {
const static Vec3uc AQUA = {0, 255, 255};
const static Vec3uc BLUE = {0, 0, 255};
const static Vec3uc GREEN = {0, 255, 0};
const static Vec3uc PURPLE = {255, 0, 255};
const static Vec3uc RED = {255, 0, 0};
const static Vec3uc WHITE = {255, 255, 255};
const static Vec3uc YELLOW = {255, 255, 0};
} // namespace TextColor
std::string GetTextColor(Vec3uc color);
std::string GetTextColorReset();
} // namespace utils
} // namespace blitz

View File

@@ -70,26 +70,36 @@ class Timer {
};
// utililty class to trigger update at regular period of time with a cooldown
template <typename T>
class CooldownTimer {
private:
std::uint64_t m_Cooldown; // in millis
std::uint64_t m_CooldownTime;
T m_Cooldown;
T m_CooldownTime;
public:
CooldownTimer() : m_Cooldown(0), m_CooldownTime(0) {}
CooldownTimer(std::uint64_t cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
CooldownTimer(T cooldown) : m_Cooldown(0), m_CooldownTime(cooldown) {}
bool Update(std::uint64_t delta);
bool Update(T delta) {
if (m_Cooldown > 0) {
m_Cooldown = std::max<T>(static_cast<T>(0), static_cast<T>(m_Cooldown - delta));
}
return m_Cooldown == 0;
}
void ApplyCooldown();
void ApplyCooldown() {
m_Cooldown = m_CooldownTime;
}
void Reset();
void Reset() {
m_Cooldown = 0;
}
void SetCooldown(std::uint64_t newCooldown) {
void SetCooldown(T newCooldown) {
m_CooldownTime = newCooldown;
}
std::uint64_t GetCooldown() const {
T GetCooldown() const {
return m_CooldownTime;
}
};

View File

@@ -16,7 +16,7 @@ namespace network {
* \class Connexion
* \brief Represents a network connexion
*/
class Connexion : public protocol::PacketHandler {
class Connexion : public protocol::PacketHandler, private NonCopyable {
protected:
protocol::PacketDispatcher m_Dispatcher;
@@ -72,11 +72,6 @@ class Connexion : public protocol::PacketHandler {
* \param packet The protocol::Packet to send
*/
void SendPacket(const protocol::Packet* packet);
/**
* \brief Disables Connexion copy
*/
REMOVE_COPY(Connexion);
};
} // namespace network

View File

@@ -21,7 +21,7 @@ namespace network {
* \note This class is meant to be created only once in your program. \n
* The easiest thing to do is to create an instance of this class at the top of your **main.cpp**.
*/
class NetworkInitializer {
class NetworkInitializer : private NonCopyable {
public:
/**
* \brief Creates the networking context
@@ -31,8 +31,6 @@ class NetworkInitializer {
* \brief Destroys the networking context
*/
~NetworkInitializer();
REMOVE_COPY(NetworkInitializer);
};
} // namespace network

View File

@@ -14,7 +14,7 @@ namespace network {
* \class TCPListener
* \brief Cross platform abstraction of a TCP socket server
*/
class TCPListener {
class TCPListener : private NonCopyable {
private:
SocketHandle m_Handle;
std::uint16_t m_Port;
@@ -79,11 +79,6 @@ class TCPListener {
int GetMaximumConnections() const {
return m_MaxConnections;
}
/**
* \brief Disables TCPListener copy
*/
REMOVE_COPY(TCPListener);
};
} // namespace network

View File

@@ -1,7 +1,7 @@
#pragma once
#include "blitz/common/DataBuffer.h"
#include "blitz/misc/ClassEntity.h"
#include "blitz/common/NonCopyable.h"
#ifdef _WIN32
#include <winsock2.h>
@@ -40,7 +40,7 @@ typedef int SocketHandle;
* \class TCPSocket
* \brief Cross platform abstraction of a TCP socket
*/
class TCPSocket {
class TCPSocket : private NonCopyable {
public:
/**
* \enum Status
@@ -153,11 +153,6 @@ class TCPSocket {
*/
std::size_t Receive(DataBuffer& buffer, std::size_t amount);
/**
* \brief Disable TCPSocket copy, as it disconnects when destroyed
*/
REMOVE_COPY(TCPSocket);
friend class TCPListener;
};

View File

@@ -29,6 +29,7 @@ class PacketHandler {
virtual void HandlePacket(const PlayerListPacket* packet) {}
virtual void HandlePacket(const PlayerLoginPacket* packet) {}
virtual void HandlePacket(const PlayerPositionAndRotationPacket* packet) {}
virtual void HandlePacket(const PlayerShootPacket* packet) {}
virtual void HandlePacket(const ServerTpsPacket* packet) {}
};

View File

@@ -7,4 +7,5 @@
#include "packets/PlayerListPacket.h"
#include "packets/PlayerLoginPacket.h"
#include "packets/PlayerPositionAndRotationPacket.h"
#include "packets/PlayerShootPacket.h"
#include "packets/ServerTpsPacket.h"

View File

@@ -12,6 +12,7 @@ class PlayerLeavePacket;
class PlayerListPacket;
class PlayerLoginPacket;
class PlayerPositionAndRotationPacket;
class PlayerShootPacket;
class ServerTpsPacket;
} // namespace protocol

View File

@@ -35,6 +35,7 @@ enum class PacketType : std::uint8_t {
Disconnect, /**< Corresponds to DisconnectPacket */
Chat, /**< Corresponds to ChatPacket */
PlayerPositionAndRotation, /**< Corresponds to PlayerPositionAndRotationPacket */
PlayerShoot, /**< Corresponds to PlayerShootPacket */
PACKET_COUNT
};

View File

@@ -2,6 +2,7 @@
#include <map>
#include "blitz/common/Defines.h"
#include "blitz/protocol/Protocol.h"
namespace blitz {
@@ -11,7 +12,7 @@ struct PlayerInfo {
std::string name;
};
typedef std::map<std::uint8_t, PlayerInfo> PlayerList;
typedef std::map<game::PlayerID, PlayerInfo> PlayerList;
class PlayerListPacket : public Packet {
private:

View File

@@ -0,0 +1,31 @@
#pragma once
#include "blitz/game/entity/Player.h"
#include "blitz/protocol/Protocol.h"
namespace blitz {
namespace protocol {
class PlayerShootPacket : public Packet {
private:
game::PlayerID m_Player; // only used when sent to client
Vec3f m_Position;
float m_Yaw, m_Pitch;
public:
PlayerShootPacket() {}
PlayerShootPacket(Vec3f position, float yaw, float pitch, game::PlayerID player = 0) :
m_Position(position), m_Yaw(yaw), m_Pitch(pitch), m_Player(player) {}
virtual ~PlayerShootPacket() {}
virtual DataBuffer Serialize(bool packetID = true) const;
virtual void Deserialize(DataBuffer& data);
virtual void Dispatch(PacketHandler* handler) const;
virtual PacketType GetType() const {
return PacketType::PlayerShoot;
}
};
} // namespace protocol
} // namespace blitz

View File

@@ -1,6 +1,7 @@
#pragma once
#include "blitz/common/Defines.h"
#include "blitz/game/Listeners.h"
#include "blitz/misc/ObjectNotifier.h"
#include "blitz/misc/Time.h"
#include "blitz/protocol/packets/ChatPacket.h"
@@ -29,7 +30,7 @@ class GuiListener {
};
// Singleton
class Client : public utils::ObjectNotifier<GuiListener> {
class Client : public utils::ObjectNotifier<GuiListener>, public game::PlayerInputListener {
private:
std::unique_ptr<server::Server> m_Server;
std::unique_ptr<client::ClientConnexion> m_Connexion;
@@ -55,6 +56,8 @@ class Client : public utils::ObjectNotifier<GuiListener> {
void SendPlayerPosAndLook(const Vec3f& position, float yaw, float pitch);
virtual void OnPlayerShoot(const Vec3f& position, float yaw, float pitch) override;
game::PlayerID GetPlayerID() const;
client::ClientGame* GetGame() {

View File

@@ -1,5 +1,9 @@
#pragma once
#include "blitz/common/Smoothing.h"
#include "blitz/game/Listeners.h"
#include "blitz/misc/ObjectNotifier.h"
#include "blitz/misc/Time.h"
namespace blitz {
namespace game {
@@ -10,9 +14,10 @@ class Player;
namespace input {
class PlayerController {
class PlayerController : public utils::ObjectNotifier<game::PlayerInputListener> {
private:
game::Player* m_Player;
game::Player* m_Player;
utils::CooldownTimer<float> m_ShootTimer{1.0f};
EMASmoother m_DxSmoother;
/// maximum x-axis velocity
float m_MaxDx;

View File

@@ -2,6 +2,7 @@
#include "blitz/game/Game.h"
#include "blitz/protocol/PacketHandler.h"
#include "client/game/ClientWorld.h"
namespace blitz {
@@ -12,6 +13,7 @@ namespace client {
class ClientGame : public game::Game, public protocol::PacketHandler {
private:
Client* m_Client;
ClientWorld m_World;
public:
ClientGame(Client* client, protocol::PacketDispatcher* dispatcher);

View File

@@ -0,0 +1,24 @@
#pragma once
#include "blitz/game/Listeners.h"
#include "blitz/game/World.h"
namespace blitz {
namespace game {
class Player;
class HitScanBullet;
} // namespace game
namespace client {
class ClientWorld : public game::World {
public:
ClientWorld() {}
// game::Player& CreatePlayer();
// game::HitScanBullet& CreateHitScanBullet();
};
} // namespace client
} // namespace blitz

View File

@@ -1,7 +1,7 @@
#pragma once
#include "blitz/common/Vector.h"
#include "blitz/game/Player.h"
#include "blitz/game/entity/Player.h"
#include <cstdint>
namespace blitz {

View File

@@ -19,7 +19,7 @@ class GunShader;
namespace render {
class MainRenderer : public GuiListener {
class MainRenderer : public GuiListener, public game::PlayerInputListener {
private:
Client* m_Client;
ModelLoader::Model m_PlayerModel;
@@ -30,6 +30,7 @@ class MainRenderer : public GuiListener {
std::unique_ptr<shader::GunShader> m_GunShader;
input::PlayerController m_PlayerController;
unsigned int m_Texture;
float m_ShootTime;
Camera m_Camera;
public:
@@ -38,6 +39,8 @@ class MainRenderer : public GuiListener {
virtual void OnSpectatorChange(const game::PlayerID player) override;
virtual void OnPlayerShoot(const Vec3f& position, float yaw, float pitch) override;
void Update();
void Render();
void RenderEntity(const GL::VertexArray& vao, const Vec3f& position, float yaw);

View File

@@ -1,6 +1,6 @@
#pragma once
#include "blitz/misc/ClassEntity.h"
#include "blitz/common/NonCopyable.h"
#include <vector>
@@ -13,7 +13,7 @@ struct VertexAttribPointer {
unsigned int m_Offset;
};
class ElementBuffer {
class ElementBuffer : private NonCopyable {
private:
unsigned int m_ID = 0;
std::size_t m_TriangleCount;
@@ -33,11 +33,9 @@ class ElementBuffer {
std::size_t GetTriangleCount() const {
return m_TriangleCount;
}
REMOVE_COPY(ElementBuffer);
};
class VertexBuffer {
class VertexBuffer : private NonCopyable {
private:
unsigned int m_ID = 0, m_DataStride;
std::vector<VertexAttribPointer> m_VertexAttribs;
@@ -56,11 +54,9 @@ class VertexBuffer {
void Unbind() const;
void AddVertexAttribPointer(unsigned int index, unsigned int coordinateSize, unsigned int offset);
void BindVertexAttribs() const;
REMOVE_COPY(VertexBuffer);
};
class VertexArray {
class VertexArray : private NonCopyable {
private:
unsigned int m_ID = 0;
ElementBuffer m_ElementBuffer;
@@ -82,8 +78,6 @@ class VertexArray {
void Bind() const;
void Unbind() const;
REMOVE_COPY(VertexArray);
private:
void BindElementArrayBuffer();
};

View File

@@ -42,6 +42,7 @@ class ServerConnexion : public network::Connexion {
virtual void HandlePacket(const protocol::DisconnectPacket* packet) override;
virtual void HandlePacket(const protocol::ChatPacket* packet) override;
virtual void HandlePacket(const protocol::PlayerPositionAndRotationPacket* packet) override;
virtual void HandlePacket(const protocol::PlayerShootPacket* packet) override;
std::uint8_t GetID() const {
return m_ID;
@@ -49,8 +50,6 @@ class ServerConnexion : public network::Connexion {
virtual bool UpdateSocket();
REMOVE_COPY(ServerConnexion);
private:
void RegisterHandlers();
void CheckKeepAlive();

View File

@@ -2,6 +2,7 @@
#include "blitz/game/Game.h"
#include "blitz/misc/Time.h"
#include "server/game/ServerWorld.h"
namespace blitz {
namespace server {
@@ -12,11 +13,16 @@ class ServerGame : public game::Game {
private:
Server* m_Server;
utils::Timer m_PositionTimer;
ServerWorld m_World;
public:
ServerGame(Server* server);
virtual ~ServerGame();
game::PlayerID GetNextPlayerID() {
return m_World.GetNextEntityID();
}
void Tick(std::uint64_t delta) override;
private:

View File

@@ -0,0 +1,30 @@
#pragma once
#include "blitz/game/Listeners.h"
#include "blitz/game/World.h"
namespace blitz {
namespace game {
class Player;
class HitScanBullet;
} // namespace game
namespace server {
class ServerWorld : public game::World {
private:
game::EntityID m_CurrentID;
public:
ServerWorld() : m_CurrentID(0) {}
game::EntityID GetNextEntityID() {
return m_CurrentID++;
}
game::Player* CreateEmptyPlayer();
game::HitScanBullet* CreateEmptyHitScanBullet(game::PlayerID shooter);
};
} // namespace server
} // namespace blitz

View File

@@ -79,7 +79,7 @@ bool DataBuffer::ReadFile(const std::string& fileName) {
m_Buffer = DataBuffer::Data(s.begin(), s.end());
m_ReadOffset = 0;
} catch (std::exception& e) {
utils::LOGE(utils::Format("Failed to read file %s ! reason : %s", fileName.c_str(), e.what()));
utils::LOGE(utils::Format("[IO] Failed to read file %s ! reason : %s", fileName.c_str(), e.what()));
return false;
}
return m_Buffer.size() > 0;
@@ -91,7 +91,7 @@ bool DataBuffer::WriteFile(const std::string& fileName) {
file.write(reinterpret_cast<const char*>(m_Buffer.data()), static_cast<std::streamsize>(m_Buffer.size()));
file.flush();
} catch (std::exception& e) {
utils::LOGE(utils::Format("Failed to read file %s ! reason : %s", fileName.c_str(), e.what()));
utils::LOGE(utils::Format("[IO] Failed to read file %s ! reason : %s", fileName.c_str(), e.what()));
return false;
}
return true;

View File

@@ -7,11 +7,11 @@ namespace blitz {
EMASmoother::EMASmoother() : Alpha(1.0f), Current(0.0f) {}
void EMASmoother::TickUnitT(float target) {
Current += Alpha * (target - Current);
Current = target + Alpha * (Current - target);
}
void EMASmoother::Tick(float target, float delta) {
Current += std::pow(Alpha, delta) * (target - Current);
Current = target + std::pow(Alpha, delta) * (Current - target);
}
float EMASmoother::GetAlpha() {
@@ -24,7 +24,7 @@ void EMASmoother::SetAlpha(float alpha) {
}
void EMASmoother::SetSmoothingTime(float t) {
Alpha = 0.99f;
SetAlpha(std::pow(1.0f - 0.999f, 1.0f / t));
};
} // namespace blitz

View File

@@ -1,5 +1,7 @@
#include "blitz/game/Game.h"
#include "blitz/game/entity/Player.h"
namespace blitz {
namespace game {
@@ -9,7 +11,7 @@ Player* Game::GetPlayerById(PlayerID id) {
if (it == m_Players.end())
return nullptr;
return &it->second;
return it->second;
}
const Player* Game::GetPlayerById(PlayerID id) const {
@@ -18,14 +20,16 @@ const Player* Game::GetPlayerById(PlayerID id) const {
if (it == m_Players.end())
return nullptr;
return &it->second;
return it->second;
}
void Game::AddPlayer(PlayerID player, const std::string& name) {
game::Player newPlayer{player};
newPlayer.SetName(name);
Player* Game::AddPlayer(PlayerID playerID, const std::string& name) {
game::Player* player = m_World->CreatePlayer(playerID);
player->SetName(name);
GetPlayers().insert({player, newPlayer});
GetPlayers().insert({playerID, player});
return player;
}
void Game::RemovePlayer(PlayerID player) {

37
src/blitz/game/World.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include "blitz/game/World.h"
#include "blitz/game/entity/Player.h"
#include <algorithm>
namespace blitz {
namespace game {
Player* World::CreatePlayer(PlayerID id) {
m_Entities.push_back(std::make_unique<Player>(id));
return dynamic_cast<game::Player*>(m_Entities.back().get());
}
Entity* World::GetEntityByID(EntityID id) {
auto it = std::find_if(m_Entities.begin(), m_Entities.end(), [id](const EntityPtr& ptr) {
return ptr->GetID() == id;
});
if (it == m_Entities.end())
return nullptr;
return it->get();
}
const Entity* World::GetEntityByID(EntityID id) const {
auto it = std::find_if(m_Entities.begin(), m_Entities.end(), [id](const EntityPtr& ptr) {
return ptr->GetID() == id;
});
if (it == m_Entities.end())
return nullptr;
return it->get();
}
} // namespace game
} // namespace blitz

View File

@@ -0,0 +1,15 @@
#include "blitz/misc/PrettyLog.h"
namespace blitz {
namespace utils {
std::string GetTextColor(Vec3uc color) {
return "\033[38;2;" + std::to_string(+color.r) + ";" + std::to_string(color.g) + ";" + std::to_string(color.b) + "m";
}
std::string GetTextColorReset() {
return "\033[0m";
}
} // namespace utils
} // namespace blitz

View File

@@ -44,21 +44,6 @@ void Timer::Reset() {
m_InternalTime = 0; // let the timer active once at the beginning
}
bool CooldownTimer::Update(std::uint64_t delta) {
if (m_Cooldown > 0) {
m_Cooldown = static_cast<std::uint64_t>(std::max(static_cast<std::int64_t>(0), static_cast<std::int64_t>(m_Cooldown - delta)));
}
return m_Cooldown == 0;
}
void CooldownTimer::Reset() {
m_Cooldown = 0; // let the timer active once at the beginning
}
void CooldownTimer::ApplyCooldown() {
m_Cooldown = m_CooldownTime;
}
std::uint64_t GetTime() {
return static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count());

View File

@@ -9,9 +9,9 @@ namespace network {
NetworkInitializer::NetworkInitializer() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) < 0) {
utils::LOGE("Failed to initialize network !");
utils::LOGE("[Network] Failed to initialize network !");
} else {
utils::LOG("Network initialized !");
utils::LOG("[Network] Network initialized !");
}
}
NetworkInitializer::~NetworkInitializer() {

View File

@@ -11,7 +11,7 @@
namespace blitz {
namespace network {
TCPListener::TCPListener() {}
TCPListener::TCPListener() : m_Handle(INVALID_SOCKET), m_Port(0), m_MaxConnections(0) {}
TCPListener::~TCPListener() {
Destroy();
@@ -19,7 +19,7 @@ TCPListener::~TCPListener() {
bool TCPListener::Listen(std::uint16_t port, int maxConnections) {
if ((m_Handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
utils::LOGE("Failed to create server socket !");
utils::LOGE("[TCPListener] Failed to create server socket !");
return false;
}
@@ -59,7 +59,7 @@ bool TCPListener::Accept(TCPSocket& newSocket) {
}
void TCPListener::Destroy() {
if (m_Handle < 0)
if (m_Handle > 0)
closesocket(m_Handle);
}

View File

@@ -61,7 +61,7 @@ std::size_t TCPSocket::Send(DataBuffer& buffer) {
}
void TCPSocket::Disconnect() {
if (m_Handle < 0)
if (m_Handle > 0)
closesocket(m_Handle);
m_Status = Status::Disconnected;
}
@@ -79,13 +79,13 @@ bool TCPSocket::Connect(const std::string& host, unsigned short port) {
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(host.c_str(), std::to_string(static_cast<int>(port)).c_str(), &hints, &result) != 0) {
utils::LOGE("Failed to get address info !");
utils::LOGE("[TCPSocket] Failed to get address info !");
return false;
}
m_Handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_Handle < 0) {
utils::LOGE("Failed to create socket !");
utils::LOGE("[TCPSocket] Failed to create socket !");
return false;
}
@@ -93,7 +93,7 @@ bool TCPSocket::Connect(const std::string& host, unsigned short port) {
for (ptr = result; ptr != nullptr; ptr = ptr->ai_next) {
struct sockaddr* sockaddr = ptr->ai_addr;
if (connect(m_Handle, sockaddr, sizeof(sockaddr_in)) != 0) {
utils::LOGE("Failed to connect with this address !");
utils::LOGE("[TCPSocket] Failed to connect with this address !");
continue;
}
m_RemoteAddr = *sockaddr;
@@ -103,7 +103,7 @@ bool TCPSocket::Connect(const std::string& host, unsigned short port) {
freeaddrinfo(result);
if (!ptr) {
utils::LOGE("Could not find a suitable interface for connecting !");
utils::LOGE("[TCPSocket] Could not find a suitable interface for connecting !");
return false;
}

View File

@@ -23,6 +23,7 @@ static std::array<PacketPtr, static_cast<std::size_t>(PacketType::PACKET_COUNT)>
std::make_unique<DisconnectPacket>(),
std::make_unique<ChatPacket>(),
std::make_unique<PlayerPositionAndRotationPacket>(),
std::make_unique<PlayerShootPacket>(),
};
const Packet* CreatePacket(PacketType type, DataBuffer& buffer) {

View File

@@ -2,7 +2,9 @@
#include "blitz/protocol/Packets.h"
#define REGISTER_DISPATCH_CLASS(className) \
void className::Dispatch(PacketHandler* handler) const { handler->HandlePacket(this); }
void className::Dispatch(PacketHandler* handler) const { \
handler->HandlePacket(this); \
}
namespace blitz {
namespace protocol {
@@ -22,6 +24,7 @@ REGISTER_DISPATCH_CLASS(DisconnectPacket)
REGISTER_DISPATCH_CLASS(ServerTpsPacket)
REGISTER_DISPATCH_CLASS(ChatPacket)
REGISTER_DISPATCH_CLASS(PlayerPositionAndRotationPacket)
REGISTER_DISPATCH_CLASS(PlayerShootPacket);
} // namespace protocol
} // namespace blitz

View File

@@ -46,13 +46,13 @@ std::string ChatPacket::GetTextColor(Vec3uc color) {
ss << std::hex << "\\u";
if (color.r <= 0xF)
ss << 0;
ss << color.r;
ss << +color.r;
if (color.g <= 0xF)
ss << 0;
ss << color.g;
ss << +color.g;
if (color.b <= 0xF)
ss << 0;
ss << color.b;
ss << +color.b;
return ss.str();
}
@@ -84,7 +84,7 @@ ColoredText ChatPacket::ColorizeText(const std::string& text) {
static_cast<float>(std::stoul(blue, nullptr, 16)) / 255.0f, 1.0f};
cursor += 6;
} catch (std::exception& e) {
utils::LOG("warning ! wrong color providen !");
utils::LOG("[ChatPacket] warning ! wrong color providen !");
}
break;
}

View File

@@ -0,0 +1,19 @@
#include "blitz/protocol/packets/PlayerShootPacket.h"
namespace blitz {
namespace protocol {
DataBuffer PlayerShootPacket::Serialize(bool packetID) const {
DataBuffer data;
WritePacketID(data, packetID);
data << m_Player << m_Position << m_Yaw << m_Pitch;
return data;
}
void PlayerShootPacket::Deserialize(DataBuffer& data) {
data >> m_Player >> m_Position >> m_Yaw >> m_Pitch;
}
} // namespace protocol
} // namespace blitz

View File

@@ -9,7 +9,7 @@ namespace utils {
namespace AssetsManager {
DataBuffer GetAsset(const std::string& fileName) {
utils::LOGD(utils::Format("Opening file %s...", fileName.c_str()));
utils::LOGD(utils::Format("[AssetsManager] Opening file %s...", fileName.c_str()));
SDL_RWops* io = SDL_RWFromFile(fileName.c_str(), "rb");

View File

@@ -3,6 +3,7 @@
#include "blitz/protocol/packets/ChatPacket.h"
#include "blitz/protocol/packets/DisconnectPacket.h"
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
#include "blitz/protocol/packets/PlayerShootPacket.h"
#include "client/ClientConnexion.h"
#include "client/game/ClientGame.h"
#include "server/Server.h"
@@ -78,6 +79,13 @@ void Client::SendPlayerPosAndLook(const Vec3f& position, float yaw, float pitch)
m_Connexion->SendPacket(&packet);
}
void Client::OnPlayerShoot(const Vec3f& position, float yaw, float pitch) {
protocol::PlayerShootPacket packet(position, yaw, pitch);
m_Connexion->SendPacket(&packet);
}
game::PlayerID Client::GetPlayerID() const {
return m_Connexion->GetPlayerID();
}

View File

@@ -2,6 +2,7 @@
#include "blitz/misc/Format.h"
#include "blitz/misc/Log.h"
#include "blitz/misc/PrettyLog.h"
#include "blitz/protocol/packets/ChatPacket.h"
#include "blitz/protocol/packets/ConnexionInfoPacket.h"
#include "blitz/protocol/packets/KeepAlivePacket.h"
@@ -11,6 +12,17 @@
namespace blitz {
namespace client {
static std::string PrintColoredText(const protocol::ColoredText& coloredText) {
std::string text;
for (const auto& part : coloredText) {
text += utils::GetTextColor({static_cast<std::uint8_t>(part.color.r * 255), static_cast<std::uint8_t>(part.color.g * 255),
static_cast<std::uint8_t>(part.color.b * 255)}) +
part.text;
}
text += utils::GetTextColorReset();
return text;
}
ClientConnexion::ClientConnexion(Client* client) : network::Connexion(&m_Dispatcher), m_Client(client) {
RegisterHandlers();
}
@@ -35,7 +47,7 @@ bool ClientConnexion::Connect(const std::string& pseudo, const std::string& addr
}
void ClientConnexion::HandlePacket(const protocol::ChatPacket* packet) {
utils::LOG(utils::Format("Chat : %s", protocol::ChatPacket::GetColoredTextString(packet->GetMessage()).c_str()));
utils::LOG("[Chat] " + PrintColoredText(packet->GetMessage()));
m_Client->ChatTextReceived(packet->GetMessage());
}

View File

@@ -22,7 +22,7 @@ void BlitzConfig::LoadConfig() {
LoadDefaultConfig();
if (!file) {
utils::LOG("Could not load config !");
utils::LOG("[BlitzConfig] Could not load config !");
return;
}
@@ -36,8 +36,10 @@ void BlitzConfig::LoadConfig() {
std::memcpy(m_Pseudo.data(), pseudo.data(), pseudo.size() + 1);
jsonInput.at("vsync").get_to<bool>(m_VSync);
jsonInput.at("fps").get_to<bool>(m_DisplayFps);
utils::LOG("[BlitzConfig] Restored config !");
} catch (std::exception& e) {
utils::LOGE("Failed to load config !");
utils::LOGE("[BlitzConfig] Failed to load config !");
}
}
@@ -52,7 +54,7 @@ void BlitzConfig::SaveConfig() {
std::ofstream file{"settings.json"};
if (!file) {
utils::LOGE("Could not save config !");
utils::LOGE("[BlitzConfig] Could not save config !");
}
json jsonOutput = {

View File

@@ -52,7 +52,7 @@ bool Display::Create() {
m_GL_Context = SDL_GL_CreateContext(m_Window);
if (!m_GL_Context) {
utils::LOGE(utils::Format("Could not create context ! SDL error : %s", SDL_GetError()));
utils::LOGE(utils::Format("[Display] Could not create context ! SDL error : %s", SDL_GetError()));
return false;
}
@@ -86,10 +86,10 @@ bool Display::Create() {
}
utils::LOG(utils::Format(
"GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth));
utils::LOG(
utils::Format("Antialiasing : %s, Number of samples per pixel : %i", multisamples ? "true" : "false", multisamplescount));
utils::LOG(utils::Format("Screen keyboard supported : %s", SDL_HasScreenKeyboardSupport() ? "true" : "false"));
"[Display] GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth));
utils::LOG(utils::Format(
"[Display] Antialiasing : %s, Number of samples per pixel : %i", multisamples ? "true" : "false", multisamplescount));
utils::LOG(utils::Format("[Display] Screen keyboard supported : %s", SDL_HasScreenKeyboardSupport() ? "true" : "false"));
SDL_GL_MakeCurrent(m_Window, m_GL_Context);
SDL_GL_SetSwapInterval(1);

View File

@@ -1,11 +1,12 @@
#include "client/display/PlayerController.h"
#include "blitz/game/Player.h"
#include "blitz/game/entity/Player.h"
#include "blitz/misc/Log.h"
#include "blitz/misc/Maths.h"
#include "client/display/InputManager.h"
#include "imgui.h"
#include <algorithm>
#include <iostream>
namespace blitz {
namespace input {
@@ -14,8 +15,8 @@ static constexpr float DEFAULT_JUMP_VEL = 7.5;
static constexpr float DEFAULT_GRAVITY = 20.0;
static constexpr float DEFAULT_MAX_LR_SPEED = 10.;
static constexpr float DEFAULT_MAX_FB_SPEED = 10.;
static constexpr float DEFAULT_LR_TOP_SPEED_REACH_TIME = 0.1;
static constexpr float DEFAULT_FB_TOP_SPEED_REACH_TIME = 0.1;
static constexpr float DEFAULT_LR_SPEED_SMOOTHING_TIME = 1.0;
static constexpr float DEFAULT_FB_SPEED_SMOOTHING_TIME = 1.0;
PlayerController::PlayerController() :
m_Player(nullptr),
@@ -26,12 +27,11 @@ PlayerController::PlayerController() :
m_MaxDz(DEFAULT_JUMP_VEL),
m_Dz(0.0),
m_G(DEFAULT_GRAVITY),
m_OnGround(true)
{
m_OnGround(true) {
m_DxSmoother.Current = 0.0f;
m_DySmoother.Current = 0.0f;
m_DxSmoother.SetSmoothingTime(DEFAULT_LR_TOP_SPEED_REACH_TIME);
m_DySmoother.SetSmoothingTime(DEFAULT_FB_TOP_SPEED_REACH_TIME);
m_DxSmoother.SetSmoothingTime(DEFAULT_LR_SPEED_SMOOTHING_TIME);
m_DySmoother.SetSmoothingTime(DEFAULT_FB_SPEED_SMOOTHING_TIME);
InputManager::BindMouseMoveCallback(
std::bind(&PlayerController::MouseMotionEvent, this, std::placeholders::_1, std::placeholders::_2));
}
@@ -55,11 +55,22 @@ void PlayerController::Update(float delta) {
float lr = static_cast<float>(ImGui::IsKeyDown(ImGuiKey_Z)) - static_cast<float>(ImGui::IsKeyDown(ImGuiKey_S));
float fb = static_cast<float>(ImGui::IsKeyDown(ImGuiKey_Q)) - static_cast<float>(ImGui::IsKeyDown(ImGuiKey_D));
m_Dx = lr * m_MaxDx;
m_Dy = fb * m_MaxDy;
// scale values in such a way that clamps ||(lr, fb)|| to 1.0
float scale = 1.0f / std::max(sqrt(lr * lr + fb * fb), 1.0f);
m_Dx = lr * m_MaxDx * scale;
m_Dy = fb * m_MaxDy * scale;
if (ImGui::IsKeyDown(ImGuiKey::ImGuiKey_Space) && m_OnGround) {
m_Dz = m_MaxDz;
NotifyListeners(&game::PlayerInputListener::OnPlayerJump);
}
bool canShoot = m_ShootTimer.Update(delta);
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && canShoot) {
NotifyListeners(
&game::PlayerInputListener::OnPlayerShoot, m_Player->GetPosition(), m_Player->GetYaw(), m_Player->GetPitch());
m_ShootTimer.ApplyCooldown();
}
}

View File

@@ -1,5 +1,6 @@
#include "client/game/ClientGame.h"
#include "blitz/game/entity/Player.h"
#include "blitz/misc/Log.h"
#include "blitz/protocol/PacketDispatcher.h"
#include "blitz/protocol/packets/PlayerJoinPacket.h"
@@ -12,7 +13,7 @@ namespace blitz {
namespace client {
ClientGame::ClientGame(Client* client, protocol::PacketDispatcher* dispatcher) :
protocol::PacketHandler(dispatcher), m_Client(client) {
protocol::PacketHandler(dispatcher), game::Game(&m_World), m_Client(client) {
RegisterHandlers();
}
@@ -63,7 +64,7 @@ void ClientGame::HandlePacket(const protocol::PlayerPositionAndRotationPacket* p
void ClientGame::Tick(std::uint64_t delta) {
float deltaTime = static_cast<float>(delta) / 1000.0f;
for (auto& [playerId, player] : GetPlayers()) {
player.SetPosition(player.GetPosition() + player.GetVelocity() * (static_cast<float>(delta) / 100.0f));
player->SetPosition(player->GetPosition() + player->GetVelocity() * (static_cast<float>(delta) / 100.0f));
}
}

View File

@@ -0,0 +1,8 @@
#include "client/game/ClientWorld.h"
#include "blitz/game/entity/HitScanBullet.h"
#include "blitz/game/entity/Player.h"
namespace blitz {
namespace client {} // namespace client
} // namespace blitz

View File

@@ -7,7 +7,7 @@ namespace gui {
void RenderColorfulText(const protocol::ColoredText& parts, float alpha) {
for (auto& part : parts) {
ImGui::TextColored({part.color.r, part.color.g, part.color.b, alpha}, part.text.c_str());
ImGui::TextColored({part.color.r, part.color.g, part.color.b, alpha}, "%s", part.text.c_str());
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - ImGui::CalcTextSize(".").x);
}

View File

@@ -32,7 +32,7 @@ void CreateGameMenu::Render() {
ImGui::Text("Port saisi : %d", InputPort);
if (ImGui::Button("Creer")) {
utils::LOGD(utils::Format("Port saisi : %i", InputPort));
utils::LOGD(utils::Format("[CreateGameMenu] Port saisi : %i", InputPort));
if (m_Client->CreateGame(InputPort, m_Client->GetConfig()->GetPseudo().data())) {
InputManager::GrabMouse(true);

View File

@@ -36,7 +36,7 @@ void JoinGameMenu::Render() {
ImGui::Text("Port saisi : %d", InputPort);
if (ImGui::Button("Rejoindre")) {
utils::LOGD(utils::Format("Adresse saisie : %s, Port saisi : %i", InputAddress, InputPort));
utils::LOGD(utils::Format("[JoinGameMenu] Adresse saisie : %s, Port saisi : %i", InputAddress, InputPort));
if (m_Client->JoinGame(m_Client->GetConfig()->GetPseudo().data(), InputAddress, InputPort)) {
InputManager::GrabMouse(true);

View File

@@ -1,6 +1,6 @@
#include "client/render/Camera.h"
#include "blitz/game/Player.h"
#include "blitz/game/entity/Player.h"
#include "blitz/misc/Maths.h"
#include "imgui.h"

View File

@@ -1,5 +1,6 @@
#include "client/render/MainRenderer.h"
#include "blitz/misc/Easing.h"
#include "blitz/misc/Format.h"
#include "blitz/misc/Log.h"
#include "blitz/misc/Maths.h"
@@ -24,11 +25,13 @@ namespace render {
static const Vec4f SkyColor = {0.6, 0.8, 1, 1};
static const Vec4f MenuColor = {0, 0, 0, 0};
MainRenderer::MainRenderer(Client* client) : m_Client(client) {
MainRenderer::MainRenderer(Client* client) : m_Client(client), m_ShootTime(0) {
LoadModels();
client->BindListener(this);
m_PlayerController.BindListener(this);
m_PlayerController.BindListener(client);
m_EntityShader = std::make_unique<shader::EntityShader>();
blitz_debug_assert(m_EntityShader->LoadShader());
@@ -92,19 +95,28 @@ void MainRenderer::RenderPlayers() {
for (const auto& [playerId, player] : m_Client->GetGame()->GetPlayers()) {
if (playerId != m_Client->GetPlayerID()) {
for (auto& Vao : m_PlayerModel.mVaos) {
RenderEntity(*Vao.get(), player.GetPosition(), player.GetYaw());
RenderEntity(*Vao.get(), player->GetPosition(), player->GetYaw());
}
}
}
}
void MainRenderer::OnPlayerShoot(const Vec3f& position, float yaw, float pitch) {
m_ShootTime = 1.0f;
}
void MainRenderer::RenderGun() {
if (!m_Camera.GetAttachedPlayer())
return;
m_GunShader->Start();
m_GunShader->SetModelTransform(maths::Identity<float>());
float progression = 1.0f - m_ShootTime;
float angle = progression * progression * progression * 7 - progression * progression * 11 + progression * 4;
Mat4f transform = maths::RotateX(-angle);
m_GunShader->SetModelTransform(transform);
for (auto& Vao : m_GunModel.mVaos) {
Vao->Bind();
@@ -144,6 +156,8 @@ void MainRenderer::Update() {
m_GunShader->Start();
m_GunShader->SetProjectionMatrix(m_Camera.GetPerspectiveMatrix());
m_ShootTime = std::max(0.0f, m_ShootTime - delta);
}
void MainRenderer::OnSpectatorChange(const game::PlayerID player) {

View File

@@ -104,11 +104,11 @@ Model LoadModel(const std::string& fileName) {
aiProcess_OptimizeMeshes);
if (nullptr == scene) {
utils::LOGE("Failed to load model !");
utils::LOGE("[ModelLoader] Failed to load model !");
return {};
}
utils::LOGD(utils::Format("\tModel nodes : %i", scene->mRootNode->mNumMeshes));
utils::LOGD(utils::Format("[ModelLoader]\tModel nodes : %i", scene->mRootNode->mNumMeshes));
Model model;
ProcessNode(scene->mRootNode, scene, model.mVaos, {});

View File

@@ -21,7 +21,7 @@ unsigned int LoadGLTexture(const std::string& fileName) {
const unsigned char* image = stbi_load_from_memory(buffer.data(), buffer.GetSize(), &width, &height, &comp, STBI_default);
if (image == nullptr) {
utils::LOGE("Erreur lors du chargement de la texture !");
utils::LOGE("[TextureLoader] Erreur lors du chargement de la texture !");
throw(std::runtime_error("Failed to load texture"));
}

View File

@@ -30,7 +30,7 @@ void ShaderProgram::Stop() const {
int ShaderProgram::GetUniformLocation(const std::string& uniformName) const {
const int location = glGetUniformLocation(m_ProgramID, uniformName.c_str());
if (location == -1) {
utils::LOGD(utils::Format("Warning ! Uniform variable %s not found !", uniformName.c_str()));
utils::LOGD(utils::Format("[ShaderProgram] Warning ! Uniform variable %s not found !", uniformName.c_str()));
}
return location;
}
@@ -104,7 +104,7 @@ int ShaderProgram::LoadShader(const std::string& source, GLenum type) {
std::vector<char> shaderError(static_cast<std::size_t>(size));
glGetShaderInfoLog(shaderID, size, &size, shaderError.data());
utils::LOGE("Could not compile shader !");
utils::LOGE("[ShaderProgram] Could not compile shader !");
utils::LOGE(shaderError.data());

View File

@@ -52,14 +52,14 @@ void Server::StopThread() {
bool Server::Start(std::uint16_t port, bool blocking) {
if (!m_Listener.Listen(port, 10)) {
utils::LOGE(utils::Format("Failed to bind port %u !", port));
utils::LOGE(utils::Format("[Server] Failed to bind port %u !", port));
return false;
}
if (!m_Listener.SetBlocking(false)) {
utils::LOGE("Failed to block server socket !");
utils::LOGE("[Server] Failed to block server socket !");
return false;
}
utils::LOG(utils::Format("Server started at port %u !", m_Listener.GetListeningPort()));
utils::LOG(utils::Format("[Server] Server started at port %u !", m_Listener.GetListeningPort()));
m_TickCounter.Reset();
m_ServerRunning = true;
if (blocking) {
@@ -76,7 +76,7 @@ void Server::Clean() {
m_Connections.clear();
utils::LOG("Server successfully stopped !");
utils::LOG("[Server] Server successfully stopped !");
}
void Server::Stop() {
@@ -103,6 +103,7 @@ void Server::Accept() {
static std::uint8_t newPlayerID = 0;
network::TCPSocket newSocket;
if (m_Listener.Accept(newSocket)) {
game::PlayerID newPlayerID = m_Game.GetNextPlayerID();
auto con = std::make_unique<ServerConnexion>(this, newSocket, newPlayerID);
m_Connections.insert(std::move(ConnexionMap::value_type{newPlayerID, std::move(con)}));
m_Connections[newPlayerID]->Start();

View File

@@ -1,6 +1,7 @@
#include "server/ServerConnexion.h"
#include "blitz/game/Game.h"
#include "blitz/game/entity/Player.h"
#include "blitz/misc/Format.h"
#include "blitz/misc/Log.h"
#include "blitz/misc/Random.h"
@@ -46,6 +47,7 @@ void ServerConnexion::RegisterHandlers() {
GetDispatcher()->RegisterHandler(protocol::PacketType::KeepAlive, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerLogin, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::Chat, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerShoot, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerPositionAndRotation, this);
}
@@ -82,31 +84,26 @@ void ServerConnexion::InitPlayerChatColor() {
const std::string& playerName = m_Player->GetName();
std::size_t hash = std::hash<std::string>()(playerName);
unsigned int red = hash >> 16 & 0xFF;
unsigned int green = hash >> 8 & 0xFF;
unsigned int blue = hash & 0xFF;
std::uint8_t red = hash >> 16 & 0xFF;
std::uint8_t green = hash >> 8 & 0xFF;
std::uint8_t blue = hash & 0xFF;
m_ChatColor = protocol::ChatPacket::GetTextColor({red, green, blue});
}
void ServerConnexion::HandlePacket(const protocol::PlayerLoginPacket* packet) {
game::Player newPlayer{m_ID};
newPlayer.SetName(packet->GetPlayerName());
m_Player = m_Server->GetGame().AddPlayer(m_ID, packet->GetPlayerName());
SendPlayers();
m_Server->GetGame().GetPlayers().insert({m_ID, newPlayer});
m_Player = m_Server->GetGame().GetPlayerById(m_ID);
protocol::PlayerJoinPacket joinPacket(m_ID, m_Player->GetName());
protocol::PlayerJoinPacket joinPacket(m_Player->GetID(), m_Player->GetName());
m_Server->BroadcastPacket(&joinPacket);
InitPlayerChatColor();
std::string joinMessage = utils::Format("%s a rejoint la partie !", packet->GetPlayerName().c_str());
utils::LOG(joinMessage);
utils::LOG("[Server] " + joinMessage);
m_Server->BroadcastChatMessage(protocol::ChatPacket::GetTextColor(protocol::YELLOW) + joinMessage);
}
@@ -139,6 +136,10 @@ void ServerConnexion::HandlePacket(const protocol::PlayerPositionAndRotationPack
m_Player->SetPitch(packet->GetPitch());
}
void ServerConnexion::HandlePacket(const protocol::PlayerShootPacket* packet) {
utils::LOGD(utils::Format("[Server] Le joueur %s a essayé de tirer", m_Player->GetName().c_str()));
}
void ServerConnexion::Start() {
InitConnection();
SendKeepAlive();
@@ -148,7 +149,7 @@ void ServerConnexion::SendPlayers() {
protocol::PlayerList list;
for (const auto& [playerID, player] : m_Server->GetGame().GetPlayers()) {
list.insert({playerID, {player.GetName()}});
list.insert({playerID, {player->GetName()}});
}
protocol::PlayerListPacket packet(list);
@@ -169,7 +170,7 @@ ServerConnexion::~ServerConnexion() {
if (m_Player) {
std::string leaveMessage = utils::Format("%s a quitte la partie !", m_Player->GetName().c_str());
utils::LOG(leaveMessage);
utils::LOG("[Server] " + leaveMessage);
m_Server->BroadcastChatMessage(protocol::ChatPacket::GetTextColor(protocol::YELLOW) + leaveMessage);
}
}

View File

@@ -1,12 +1,13 @@
#include "server/game/ServerGame.h"
#include "blitz/game/entity/Player.h"
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
#include "server/Server.h"
namespace blitz {
namespace server {
ServerGame::ServerGame(Server* server) : m_Server(server), m_PositionTimer(SERVER_TPS) {}
ServerGame::ServerGame(Server* server) : game::Game(&m_World), m_Server(server), m_PositionTimer(SERVER_TPS) {}
ServerGame::~ServerGame() {}
@@ -18,7 +19,7 @@ void ServerGame::Tick(std::uint64_t delta) {
void ServerGame::SendPlayerPositions() {
for (const auto& [playerID, player] : GetPlayers()) {
protocol::PlayerPositionAndRotationPacket packet(player.GetPosition(), player.GetYaw(), player.GetPitch(), playerID);
protocol::PlayerPositionAndRotationPacket packet(player->GetPosition(), player->GetYaw(), player->GetPitch(), playerID);
m_Server->BroadcastPacket(&packet);
}
}

View File

@@ -0,0 +1,20 @@
#include "server/game/ServerWorld.h"
#include "blitz/game/entity/HitScanBullet.h"
#include "blitz/game/entity/Player.h"
namespace blitz {
namespace server {
game::Player* ServerWorld::CreateEmptyPlayer() {
return CreatePlayer(m_CurrentID++);
}
game::HitScanBullet* ServerWorld::CreateEmptyHitScanBullet(game::PlayerID shooter) {
m_Entities.push_back(std::make_unique<game::HitScanBullet>(m_CurrentID, shooter));
m_CurrentID++;
return dynamic_cast<game::HitScanBullet*>(m_Entities.back().get());
}
} // namespace server
} // namespace blitz

View File

@@ -1,89 +1,7 @@
-- We need that for the tests
set_xmakever("2.8.5")
set_policy("package.install_locally", true)
add_rules("mode.debug", "mode.release")
add_requires("libsdl 2.28.3", {configs = {sdlmain = false}})
add_requires("glbinding >= 3", "zlib", "assimp", "nlohmann_json")
add_rules("mode.debug", "mode.release", "mode.valgrind")
set_languages("c++17")
add_includedirs("include")
-- Game files (with server)
target("Blitz")
if is_os("windows") then
set_kind("static")
add_links("ws2_32") -- link network stuff
else
set_kind("shared")
end
add_files("src/blitz/**.cpp", "src/server/**.cpp")
add_packages("zlib")
-- Server binary (headless)
target("BlitzServer")
set_kind("binary")
set_default(false)
add_files("src/ServerMain.cpp")
-- Libraries
add_deps("Blitz")
-- Client binary (default)
target("BlitzClient")
if is_plat("android") then
set_kind("shared")
else
set_kind("binary")
end
set_default(true)
add_files("src/client/**.cpp", "src/ClientMain.cpp")
-- Libraries
add_deps("Blitz")
add_packages("libsdl", "glbinding", "assimp", "nlohmann_json")
add_includedirs("libs", "libs/imgui")
add_files("libs/imgui/**.cpp")
if is_plat("macosx") then
add_frameworks("OpenGL")
elseif is_plat("windows") then
add_ldflags("/LTCG") -- fix compiltation of glbinding
end
-- Assets
set_rundir("$(projectdir)/assets")
-- Tests
for _, file in ipairs(os.files("test/test_*.cpp")) do
local name = path.basename(file)
target(name)
set_kind("binary")
add_files("test/" .. name .. ".cpp")
set_default(false)
add_deps("Blitz")
add_tests("compile_and_run")
end
includes("xmake/BlitzClient.lua")
includes("xmake/BlitzServer.lua")
includes("xmake/BlitzTest.lua")

15
xmake/Blitz.lua Normal file
View File

@@ -0,0 +1,15 @@
add_requires("zlib")
-- Game files (with server)
target("Blitz")
if is_os("windows") then
set_kind("static")
add_links("ws2_32") -- link network stuff
else
set_kind("shared")
end
add_includedirs("../include")
add_files("../src/blitz/**.cpp", "../src/server/**.cpp")
add_packages("zlib")

41
xmake/BlitzClient.lua Normal file
View File

@@ -0,0 +1,41 @@
includes("Blitz.lua")
add_requires("libsdl 2.28.3", {configs = {sdlmain = false}})
add_requires("glbinding >= 3", "assimp", "nlohmann_json")
-- Client binary (default)
target("BlitzClient")
if is_plat("android") then
set_kind("shared")
else
set_kind("binary")
end
set_default(true)
add_includedirs("../include")
add_files("../src/client/**.cpp", "../src/ClientMain.cpp")
-- Libraries
add_deps("Blitz")
add_packages("libsdl", "glbinding", "assimp", "nlohmann_json")
add_includedirs("../libs", "../libs/imgui")
add_files("../libs/imgui/**.cpp")
if is_plat("macosx") then
add_frameworks("OpenGL")
elseif is_plat("windows") then
add_ldflags("/LTCG") -- fix compiltation of glbinding
end
-- Assets
set_rundir("../assets")
-- Valgrind test
if is_mode("valgrind") then
on_run(function (target)
os.cd("../assets")
os.execv("valgrind", {"-s", "--leak-check=full", target:targetfile()})
end)
end

12
xmake/BlitzServer.lua Normal file
View File

@@ -0,0 +1,12 @@
includes("Blitz.lua")
-- Server binary (headless)
target("BlitzServer")
set_kind("binary")
set_default(false)
add_includedirs("../include")
add_files("../src/ServerMain.cpp")
-- Libraries
add_deps("Blitz")

20
xmake/BlitzTest.lua Normal file
View File

@@ -0,0 +1,20 @@
includes("Blitz.lua")
-- Tests were introduced in that version
set_xmakever("2.8.5")
-- Tests
for _, file in ipairs(os.files("../test/test_*.cpp")) do
local name = path.basename(file)
target(name)
set_kind("binary")
add_includedirs("../include")
add_files("../test/" .. name .. ".cpp")
set_default(false)
add_deps("Blitz")
add_tests("compile_and_run")
end