Basic network classes added: Client, Server, ClientApplication, ServerApplication.
This commit is contained in:
parent
c36481f4ef
commit
3884be8868
@ -1,18 +1,18 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Application.hpp
|
||||
* Filename: ClientApplication.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 14/12/2014 05:09:11
|
||||
* Created: 09/01/2019 19:33:30
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef APPLICATION_HPP_
|
||||
#define APPLICATION_HPP_
|
||||
#ifndef CLIENTAPPLICATION_HPP_
|
||||
#define CLIENTAPPLICATION_HPP_
|
||||
|
||||
#include <gk/core/CoreApplication.hpp>
|
||||
|
||||
@ -20,9 +20,9 @@
|
||||
#include "Registry.hpp"
|
||||
#include "ScriptEngine.hpp"
|
||||
|
||||
class Application : public gk::CoreApplication {
|
||||
class ClientApplication : public gk::CoreApplication {
|
||||
public:
|
||||
Application(int argc, char **argv) : gk::CoreApplication(argc, argv) {}
|
||||
ClientApplication(int argc, char **argv) : gk::CoreApplication(argc, argv) {}
|
||||
|
||||
void init() override;
|
||||
|
||||
@ -36,4 +36,4 @@ class Application : public gk::CoreApplication {
|
||||
Registry m_registry;
|
||||
};
|
||||
|
||||
#endif // APPLICATION_HPP_
|
||||
#endif // CLIENTAPPLICATION_HPP_
|
52
client/include/network/Client.hpp
Normal file
52
client/include/network/Client.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Client.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 25/01/2018 12:26:01
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef CLIENT_HPP_
|
||||
#define CLIENT_HPP_
|
||||
|
||||
#include <SFML/Network/TcpSocket.hpp>
|
||||
#include <SFML/Network/UdpSocket.hpp>
|
||||
|
||||
#include <gk/core/ApplicationStateStack.hpp>
|
||||
#include <gk/core/Timer.hpp>
|
||||
|
||||
class Client {
|
||||
public:
|
||||
void connect(sf::IpAddress serverAddress, u16 serverPort);
|
||||
void disconnect();
|
||||
|
||||
void sendReady();
|
||||
void sendKeyState();
|
||||
|
||||
void update(bool &hasGameStarted);
|
||||
|
||||
bool isConnected() const { return m_isConnected; }
|
||||
|
||||
u16 id() const { return m_id; }
|
||||
|
||||
private:
|
||||
bool m_isConnected = false;
|
||||
|
||||
u16 m_id;
|
||||
|
||||
sf::IpAddress m_serverAddress;
|
||||
u16 m_serverPort;
|
||||
|
||||
std::unique_ptr<sf::TcpSocket> m_tcpSocket;
|
||||
|
||||
sf::UdpSocket m_socket;
|
||||
|
||||
gk::Timer m_keyUpdateTimer;
|
||||
};
|
||||
|
||||
#endif // CLIENT_HPP_
|
@ -19,6 +19,7 @@
|
||||
#include <gk/core/ApplicationState.hpp>
|
||||
#include <gk/gl/RenderTarget.hpp>
|
||||
|
||||
#include "Client.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "HUD.hpp"
|
||||
#include "LuaCore.hpp"
|
||||
@ -52,6 +53,8 @@ class GameState : public gk::ApplicationState {
|
||||
HUD m_hud{m_player, m_world};
|
||||
|
||||
LuaCore m_luaCore;
|
||||
|
||||
Client m_client;
|
||||
};
|
||||
|
||||
#endif // GAMESTATE_HPP_
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Application.cpp
|
||||
* Filename: ClientApplication.cpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 14/12/2014 05:09:21
|
||||
* Created: 09/01/2019 19:33:52
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
@ -15,12 +15,12 @@
|
||||
#include <gk/core/Mouse.hpp>
|
||||
#include <gk/graphics/Font.hpp>
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "ClientApplication.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "GameState.hpp"
|
||||
#include "TextureLoader.hpp"
|
||||
|
||||
void Application::init() {
|
||||
void ClientApplication::init() {
|
||||
gk::CoreApplication::init();
|
||||
|
||||
gk::GamePad::init(m_keyboardHandler);
|
||||
@ -44,7 +44,7 @@ void Application::init() {
|
||||
m_stateStack.push<GameState>();
|
||||
}
|
||||
|
||||
void Application::initOpenGL() {
|
||||
void ClientApplication::initOpenGL() {
|
||||
// Enable transparency
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
@ -11,10 +11,10 @@
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "Application.hpp"
|
||||
#include "ClientApplication.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Application app(argc, argv);
|
||||
ClientApplication app(argc, argv);
|
||||
app.run();
|
||||
|
||||
return 0;
|
||||
|
112
client/source/network/Client.cpp
Normal file
112
client/source/network/Client.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Client.cpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 25/01/2018 12:26:43
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <gk/core/input/GamePad.hpp>
|
||||
#include <gk/core/input/InputHandler.hpp>
|
||||
#include <gk/core/GameClock.hpp>
|
||||
#include <gk/core/Exception.hpp>
|
||||
|
||||
#include "Client.hpp"
|
||||
#include "Network.hpp"
|
||||
|
||||
void Client::connect(sf::IpAddress serverAddress, u16 serverPort) {
|
||||
m_serverAddress = serverAddress;
|
||||
m_serverPort = serverPort;
|
||||
|
||||
m_tcpSocket.reset(new sf::TcpSocket);
|
||||
if (serverAddress.toInteger() == 0 || m_tcpSocket->connect(serverAddress, serverPort, sf::seconds(5)) != sf::Socket::Done)
|
||||
throw EXCEPTION("Network error: Unable to connect to server", serverAddress.toString() + ":" + std::to_string(serverPort));
|
||||
|
||||
if (m_socket.bind(0) != sf::Socket::Done)
|
||||
throw EXCEPTION("Network error: Bind failed");
|
||||
|
||||
sf::Packet packet;
|
||||
packet << Network::Command::ClientConnect << sf::IpAddress::getLocalAddress().toString() << m_socket.getLocalPort();
|
||||
m_tcpSocket->send(packet);
|
||||
|
||||
sf::Packet answer;
|
||||
m_tcpSocket->receive(answer);
|
||||
|
||||
Network::Command command;
|
||||
answer >> command;
|
||||
if (command == Network::Command::ClientRefused)
|
||||
throw EXCEPTION("Server error: You can't join an already started game.");
|
||||
|
||||
if (command != Network::Command::ClientOk)
|
||||
throw EXCEPTION("Network error: Expected 'ClientOk' packet.");
|
||||
answer >> m_id;
|
||||
|
||||
m_tcpSocket->setBlocking(false);
|
||||
m_socket.setBlocking(false);
|
||||
|
||||
m_isConnected = true;
|
||||
}
|
||||
|
||||
void Client::disconnect() {
|
||||
sf::Packet packet;
|
||||
packet << Network::Command::ClientDisconnect;
|
||||
m_tcpSocket->send(packet);
|
||||
}
|
||||
|
||||
void Client::sendReady() {
|
||||
sf::Packet packet;
|
||||
packet << Network::Command::ClientReady << m_id;
|
||||
m_tcpSocket->send(packet);
|
||||
}
|
||||
|
||||
void Client::sendKeyState() {
|
||||
if (!m_keyUpdateTimer.isStarted())
|
||||
m_keyUpdateTimer.start();
|
||||
|
||||
if (m_keyUpdateTimer.time() > 15) {
|
||||
gk::InputHandler *inputHandler = gk::GamePad::getInputHandler();
|
||||
if (inputHandler) {
|
||||
sf::Packet packet;
|
||||
packet << Network::Command::KeyState << gk::GameClock::getTicks() << m_id;
|
||||
for (auto &it : inputHandler->keysPressed()) {
|
||||
packet << static_cast<u8>(it.first) << it.second;
|
||||
}
|
||||
|
||||
m_socket.send(packet, m_serverAddress, m_serverPort);
|
||||
}
|
||||
|
||||
m_keyUpdateTimer.reset();
|
||||
m_keyUpdateTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::update(bool &hasGameStarted) {
|
||||
sf::Packet packet;
|
||||
sf::IpAddress senderAddress;
|
||||
u16 senderPort;
|
||||
while (m_socket.receive(packet, senderAddress, senderPort) == sf::Socket::Done) {
|
||||
Network::Command command;
|
||||
packet >> command;
|
||||
|
||||
std::cout << "UDP Message of type '" << Network::commandToString(command) << "' received from: " << senderAddress << ":" << senderPort << std::endl;
|
||||
}
|
||||
|
||||
while (m_tcpSocket->receive(packet) == sf::Socket::Done) {
|
||||
Network::Command command;
|
||||
packet >> command;
|
||||
|
||||
if (command == Network::Command::GameStart) {
|
||||
hasGameStarted = true;
|
||||
}
|
||||
else if (command == Network::Command::GameEnd) {
|
||||
disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <gk/core/ApplicationStateStack.hpp>
|
||||
#include <gk/core/input/GamePad.hpp>
|
||||
#include <gk/core/Exception.hpp>
|
||||
#include <gk/core/Mouse.hpp>
|
||||
#include <gk/gl/OpenGL.hpp>
|
||||
#include <gk/core/GameClock.hpp>
|
||||
@ -30,6 +31,13 @@
|
||||
#include "ScriptEngine.hpp"
|
||||
|
||||
GameState::GameState() {
|
||||
try {
|
||||
m_client.connect("localhost", 4242);
|
||||
}
|
||||
catch (const gk::Exception &e) {
|
||||
std::cerr << "Error " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
m_camera.setAspectRatio((float)SCREEN_WIDTH / SCREEN_HEIGHT);
|
||||
|
||||
World::setInstance(m_world);
|
42
common/include/network/Network.hpp
Normal file
42
common/include/network/Network.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Network.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 22/01/2018 14:11:41
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef NETWORK_HPP_
|
||||
#define NETWORK_HPP_
|
||||
|
||||
#include <SFML/Network/Packet.hpp>
|
||||
|
||||
namespace Network {
|
||||
enum class Command {
|
||||
// Client commands
|
||||
ClientConnect, // <TCP> [NetworkCommand][u16 udp port]
|
||||
ClientOk, // <TCP> [NetworkCommand][u16 client id]
|
||||
ClientRefused, // <TCP> [NetworkCommand]
|
||||
ClientReady, // <TCP> [NetworkCommand][u16 client id]
|
||||
ClientDisconnect, // <TCP> [NetworkCommand]
|
||||
|
||||
// Game commands
|
||||
GameStart, // <TCP> [NetworkCommand]
|
||||
GameEnd, // <TCP> [NetworkCommand]
|
||||
|
||||
// Input commands
|
||||
KeyState, // <UDP> [NetworkCommand][u32 timestamp][u16 client id][u32 keycode][bool isPressed]...
|
||||
};
|
||||
|
||||
std::string commandToString(Command command);
|
||||
}
|
||||
|
||||
sf::Packet &operator<<(sf::Packet &packet, Network::Command command);
|
||||
sf::Packet &operator>>(sf::Packet &packet, Network::Command &command);
|
||||
|
||||
#endif // NETWORK_HPP_
|
44
common/source/network/Network.cpp
Normal file
44
common/source/network/Network.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Network.cpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 22/01/2018 14:12:53
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include <map>
|
||||
|
||||
#include <gk/core/IntTypes.hpp>
|
||||
|
||||
#include "Network.hpp"
|
||||
|
||||
std::string Network::commandToString(Network::Command command) {
|
||||
std::map<Network::Command, std::string> commandNames = {
|
||||
{Network::Command::ClientConnect, "ClientConnect"},
|
||||
{Network::Command::ClientOk, "ClientOk"},
|
||||
{Network::Command::ClientRefused, "ClientRefused"},
|
||||
{Network::Command::ClientReady, "ClientReady"},
|
||||
{Network::Command::ClientDisconnect, "ClientDisconnect"},
|
||||
{Network::Command::GameStart, "GameStart"},
|
||||
{Network::Command::GameEnd, "GameEnd"},
|
||||
{Network::Command::KeyState, "KeyState"},
|
||||
};
|
||||
return commandNames[command];
|
||||
}
|
||||
|
||||
sf::Packet &operator<<(sf::Packet &packet, Network::Command command) {
|
||||
return packet << static_cast<u16>(command);
|
||||
}
|
||||
|
||||
sf::Packet &operator>>(sf::Packet &packet, Network::Command &command) {
|
||||
u16 tmp;
|
||||
packet >> tmp;
|
||||
command = static_cast<Network::Command>(tmp);
|
||||
return packet;
|
||||
}
|
||||
|
26
server/include/core/NetworkInputHandler.hpp
Normal file
26
server/include/core/NetworkInputHandler.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: NetworkInputHandler.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 21/01/2018 10:54:01
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef NETWORKINPUTHANDLER_HPP_
|
||||
#define NETWORKINPUTHANDLER_HPP_
|
||||
|
||||
#include <gk/core/input/InputHandler.hpp>
|
||||
|
||||
class NetworkInputHandler : public gk::InputHandler {
|
||||
public:
|
||||
void setKeyPressed(gk::GameKey key, bool isPressed) {
|
||||
m_keysPressed[key] = isPressed;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // NETWORKINPUTHANDLER_HPP_
|
37
server/include/core/ServerApplication.hpp
Normal file
37
server/include/core/ServerApplication.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: ServerApplication.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 09/01/2019 19:37:20
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef SERVERAPPLICATION_HPP_
|
||||
#define SERVERAPPLICATION_HPP_
|
||||
|
||||
#include <gk/core/CoreApplication.hpp>
|
||||
|
||||
#include "NetworkInputHandler.hpp"
|
||||
#include "Registry.hpp"
|
||||
#include "Server.hpp"
|
||||
|
||||
class ServerApplication : public gk::CoreApplication {
|
||||
public:
|
||||
ServerApplication(int argc, char **argv) : gk::CoreApplication(argc, argv) {}
|
||||
|
||||
void init() override;
|
||||
|
||||
private:
|
||||
void mainLoop() override;
|
||||
|
||||
Server m_server;
|
||||
|
||||
Registry m_registry;
|
||||
};
|
||||
|
||||
#endif // SERVERAPPLICATION_HPP_
|
56
server/include/network/Server.hpp
Normal file
56
server/include/network/Server.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Server.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 23/01/2018 14:47:14
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef SERVER_HPP_
|
||||
#define SERVER_HPP_
|
||||
|
||||
#include <SFML/Network/SocketSelector.hpp>
|
||||
#include <SFML/Network/TcpListener.hpp>
|
||||
#include <SFML/Network/UdpSocket.hpp>
|
||||
|
||||
#include "ServerInfo.hpp"
|
||||
|
||||
class Server {
|
||||
public:
|
||||
void init();
|
||||
|
||||
void handleKeyState();
|
||||
|
||||
void handleGameEvents();
|
||||
|
||||
bool isRunning() const { return m_isRunning; }
|
||||
bool hasGameStarted() const { return m_hasGameStarted; }
|
||||
|
||||
ServerInfo &info() { return m_info; }
|
||||
|
||||
sf::UdpSocket &udpSocket() { return m_udpSocket; }
|
||||
|
||||
void setRunning(bool isRunning) { m_isRunning = isRunning; }
|
||||
void setGameStarted(bool hasGameStarted) { m_hasGameStarted = hasGameStarted; }
|
||||
|
||||
private:
|
||||
void handleNewConnections();
|
||||
void handleClientMessages();
|
||||
|
||||
bool m_isRunning = true;
|
||||
bool m_hasGameStarted = false;
|
||||
|
||||
ServerInfo m_info;
|
||||
|
||||
sf::UdpSocket m_udpSocket;
|
||||
|
||||
sf::TcpListener m_tcpListener;
|
||||
sf::SocketSelector m_selector;
|
||||
};
|
||||
|
||||
#endif // SERVER_HPP_
|
57
server/include/network/ServerInfo.hpp
Normal file
57
server/include/network/ServerInfo.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: ServerInfo.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 22/01/2018 19:03:23
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef SERVERINFO_HPP_
|
||||
#define SERVERINFO_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
|
||||
#include <gk/core/Exception.hpp>
|
||||
|
||||
#include "NetworkInputHandler.hpp"
|
||||
|
||||
struct Client {
|
||||
Client(u16 _id, sf::IpAddress _address, u16 _port, const std::shared_ptr<sf::TcpSocket> &socket)
|
||||
: id(_id), address(_address), port(_port), tcpSocket(socket) {}
|
||||
|
||||
u16 id;
|
||||
bool isReady = false;
|
||||
|
||||
sf::IpAddress address;
|
||||
u16 port;
|
||||
|
||||
u32 previousKeyTimestamp = 0;
|
||||
|
||||
std::shared_ptr<sf::TcpSocket> tcpSocket;
|
||||
|
||||
NetworkInputHandler inputHandler;
|
||||
};
|
||||
|
||||
class ServerInfo {
|
||||
public:
|
||||
Client &addClient(sf::IpAddress address, u16 port, const std::shared_ptr<sf::TcpSocket> &socket);
|
||||
Client *getClient(u16 id);
|
||||
void removeClient(u16 id);
|
||||
|
||||
std::vector<Client> &clients() { return m_clients; }
|
||||
const std::vector<Client> &clients() const { return m_clients; }
|
||||
|
||||
private:
|
||||
std::vector<Client> m_clients;
|
||||
};
|
||||
|
||||
#endif // SERVERINFO_HPP_
|
44
server/source/core/ServerApplication.cpp
Normal file
44
server/source/core/ServerApplication.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: ServerApplication.cpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 09/01/2019 19:41:15
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "ServerApplication.hpp"
|
||||
|
||||
void ServerApplication::init() {
|
||||
m_server.init();
|
||||
m_server.setRunning(true);
|
||||
m_server.setGameStarted(false);
|
||||
|
||||
gk::CoreApplication::init();
|
||||
|
||||
Registry::setInstance(m_registry);
|
||||
|
||||
// m_scriptEngine.init();
|
||||
}
|
||||
|
||||
void ServerApplication::mainLoop() {
|
||||
while (m_server.isRunning()) {
|
||||
handleEvents();
|
||||
|
||||
m_server.handleGameEvents();
|
||||
|
||||
if (m_server.hasGameStarted()) {
|
||||
m_server.handleKeyState();
|
||||
|
||||
m_clock.updateGame([&] {
|
||||
});
|
||||
|
||||
m_clock.waitForNextFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,10 @@
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "Application.hpp"
|
||||
#include "ServerApplication.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Application app(argc, argv);
|
||||
ServerApplication app(argc, argv);
|
||||
app.run();
|
||||
|
||||
return 0;
|
||||
|
157
server/source/network/Server.cpp
Normal file
157
server/source/network/Server.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Server.cpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 23/01/2018 14:48:07
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "Network.hpp"
|
||||
#include "Server.hpp"
|
||||
|
||||
void Server::init() {
|
||||
if (m_udpSocket.bind(4242) != sf::Socket::Done)
|
||||
throw EXCEPTION("Network error: Bind failed");
|
||||
|
||||
m_udpSocket.setBlocking(false);
|
||||
|
||||
if (m_tcpListener.listen(4242) != sf::Socket::Done)
|
||||
throw EXCEPTION("Network error: Listen failed");
|
||||
|
||||
m_tcpListener.setBlocking(false);
|
||||
|
||||
m_selector.add(m_tcpListener);
|
||||
}
|
||||
|
||||
void Server::handleKeyState() {
|
||||
sf::Packet packet;
|
||||
sf::IpAddress senderAddress;
|
||||
u16 senderPort;
|
||||
while (m_udpSocket.receive(packet, senderAddress, senderPort) == sf::Socket::Status::Done) {
|
||||
Network::Command command;
|
||||
u32 timestamp;
|
||||
u16 clientId;
|
||||
packet >> command >> timestamp >> clientId;
|
||||
|
||||
std::cout << "UDP Message of type '" << Network::commandToString(command) << "' received from: " << senderAddress << ":" << senderPort << std::endl;
|
||||
|
||||
if (command == Network::Command::KeyState) {
|
||||
Client *client = m_info.getClient(clientId);
|
||||
if (client && client->previousKeyTimestamp < timestamp) {
|
||||
client->previousKeyTimestamp = timestamp;
|
||||
|
||||
while (!packet.endOfPacket()) {
|
||||
u8 key;
|
||||
bool isPressed;
|
||||
packet >> key >> isPressed;
|
||||
|
||||
client->inputHandler.setKeyPressed(key, isPressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleGameEvents() {
|
||||
if (m_selector.wait(sf::milliseconds(10))) {
|
||||
if (m_selector.isReady(m_tcpListener)) {
|
||||
handleNewConnections();
|
||||
}
|
||||
else {
|
||||
handleClientMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleNewConnections() {
|
||||
std::shared_ptr<sf::TcpSocket> clientSocket = std::make_shared<sf::TcpSocket>();
|
||||
if (m_tcpListener.accept(*clientSocket) == sf::Socket::Done) {
|
||||
sf::Packet packet;
|
||||
clientSocket->receive(packet);
|
||||
|
||||
Network::Command command;
|
||||
packet >> command;
|
||||
if (command != Network::Command::ClientConnect)
|
||||
throw EXCEPTION("Network error: Expected 'ClientConnect' packet.");
|
||||
|
||||
if (!m_hasGameStarted && m_info.clients().size() < 5) {
|
||||
std::string address;
|
||||
u16 port;
|
||||
packet >> address >> port;
|
||||
|
||||
Client &client = m_info.addClient(address, port, clientSocket);
|
||||
// FIXME
|
||||
// scene.addObject(PlayerFactory::create(20, 50 + 100 * client.id, client.id));
|
||||
m_selector.add(*client.tcpSocket);
|
||||
|
||||
sf::Packet outPacket;
|
||||
outPacket << Network::Command::ClientOk << client.id;
|
||||
client.tcpSocket->send(outPacket);
|
||||
client.tcpSocket->setBlocking(false);
|
||||
}
|
||||
else {
|
||||
sf::Packet outPacket;
|
||||
outPacket << Network::Command::ClientRefused;
|
||||
clientSocket->send(outPacket);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cerr << "Warning: Connection accept failed." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Refactor this function
|
||||
void Server::handleClientMessages() {
|
||||
bool areAllClientsReady = true;
|
||||
for (size_t i = 0 ; i < m_info.clients().size() ; ++i) {
|
||||
Client &client = m_info.clients()[i];
|
||||
if (m_selector.isReady(*client.tcpSocket)) {
|
||||
sf::Packet packet;
|
||||
if (client.tcpSocket->receive(packet) == sf::Socket::Done) {
|
||||
Network::Command command;
|
||||
packet >> command;
|
||||
|
||||
if (command == Network::Command::ClientDisconnect) {
|
||||
// FIXME
|
||||
// sf::Packet packet;
|
||||
// packet << Network::Command::EntityDie << "Player" + std::to_string(client.id);
|
||||
// for (Client &client : m_info.clients()) {
|
||||
// client.tcpSocket->send(packet);
|
||||
// }
|
||||
|
||||
--i;
|
||||
m_selector.remove(*client.tcpSocket);
|
||||
m_info.removeClient(client.id);
|
||||
|
||||
if (m_info.clients().size() == 0) {
|
||||
// m_tcpListener.close();
|
||||
m_isRunning = false;
|
||||
m_hasGameStarted = false;
|
||||
}
|
||||
}
|
||||
else if (command == Network::Command::ClientReady) {
|
||||
client.isReady = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!client.isReady)
|
||||
areAllClientsReady = false;
|
||||
}
|
||||
|
||||
if (areAllClientsReady) {
|
||||
sf::Packet packet;
|
||||
packet << Network::Command::GameStart;
|
||||
for (Client &client : m_info.clients()) {
|
||||
client.tcpSocket->send(packet);
|
||||
}
|
||||
|
||||
m_hasGameStarted = true;
|
||||
}
|
||||
}
|
||||
|
34
server/source/network/ServerInfo.cpp
Normal file
34
server/source/network/ServerInfo.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: ServerInfo.cpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 26/01/2018 22:41:02
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "ServerInfo.hpp"
|
||||
|
||||
Client &ServerInfo::addClient(sf::IpAddress address, u16 port, const std::shared_ptr<sf::TcpSocket> &socket) {
|
||||
m_clients.emplace_back(m_clients.size(), address, port, socket);
|
||||
return m_clients.back();
|
||||
}
|
||||
|
||||
Client *ServerInfo::getClient(u16 id) {
|
||||
auto it = std::find_if(m_clients.begin(), m_clients.end(), [id] (Client &client) { return client.id == id; });
|
||||
if (it == m_clients.end())
|
||||
return nullptr;
|
||||
|
||||
return &*it;
|
||||
}
|
||||
|
||||
void ServerInfo::removeClient(u16 id) {
|
||||
auto it = std::find_if(m_clients.begin(), m_clients.end(), [id] (Client &client) { return client.id == id; });
|
||||
if (it != m_clients.end())
|
||||
m_clients.erase(it);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user