Compare commits
10 Commits
e43d142f6a
...
90c43b6d75
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90c43b6d75 | ||
|
|
c5f9dfd628 | ||
|
|
72129de8f0 | ||
|
|
342162ba80 | ||
|
|
e6d262cfc0 | ||
|
|
6258ee9193 | ||
|
|
a83b544a3a | ||
|
|
473432d9bb | ||
|
|
84beaf7fd6 | ||
|
|
8ad1c7219d |
@@ -3,12 +3,6 @@ project(DarkRP2D_DEDICATED_SERVER)
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
include(ExternalProject)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
add_definitions(-DNDEBUG)
|
||||
endif(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
MESSAGE( "64-Bit Compiler erkannt" )
|
||||
SET( EX_PLATFORM 64 )
|
||||
@@ -19,11 +13,10 @@ else( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
SET( EX_PLATFORM_NAME "x86" )
|
||||
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
|
||||
|
||||
# Download automatically, you can also just copy the conan.cmake file
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
|
||||
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.13/conan.cmake"
|
||||
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.15/conan.cmake"
|
||||
"${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
endif()
|
||||
include(${CMAKE_BINARY_DIR}/conan.cmake)
|
||||
@@ -31,13 +24,14 @@ include(${CMAKE_BINARY_DIR}/conan.cmake)
|
||||
# Launch Conan Install
|
||||
conan_cmake_run(CONANFILE conanfile.txt
|
||||
BASIC_SETUP CMAKE_TARGETS
|
||||
BUILD missing)
|
||||
BUILD missing
|
||||
CONFIGURATION_TYPES "Release;Debug")
|
||||
|
||||
MESSAGE( STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR} )
|
||||
MESSAGE( STATUS "DarkRP2D_DEDICATED_SERVER_SOURCE_DIR: " ${DarkRP2D_DEDICATED_SERVER_SOURCE_DIR} )
|
||||
|
||||
#Libs
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake)
|
||||
conan_basic_setup()
|
||||
|
||||
file(GLOB_RECURSE DarkRP2D_DEDICATED_SERVER_SOURCE_FILES ${DarkRP2D_DEDICATED_SERVER_SOURCE_DIR}/src/*.cpp)
|
||||
@@ -48,7 +42,12 @@ MESSAGE( STATUS "Conan search Dirs: " "${CONAN_LIB_DIRS}")
|
||||
MESSAGE( STATUS "Conan Libs: " "${CONAN_LIBS}")
|
||||
MESSAGE( STATUS "Conan Includes: " "${CONAN_INCLUDE_DIRS}")
|
||||
|
||||
target_link_libraries(DarkRP2DDServer ${CONAN_LIBS})
|
||||
foreach(_LIB ${CONAN_LIBS_RELEASE})
|
||||
target_link_libraries(DarkRP2DDServer optimized ${_LIB})
|
||||
endforeach()
|
||||
foreach(_LIB ${CONAN_LIBS_DEBUG})
|
||||
target_link_libraries(DarkRP2DDServer debug ${_LIB})
|
||||
endforeach()
|
||||
|
||||
#add_custom_target(CopyBinaries
|
||||
#COMMAND ${CMAKE_COMMAND} -E copy ${SDL2_DLL} ${CMAKE_BINARY_DIR}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
[requires]
|
||||
box2d/2.3.1@conan/stable
|
||||
glm/0.9.9.1@g-truc/stable
|
||||
EntityX/1.1.2@gulum/stable
|
||||
EntityX/1.3.0@gulum/stable
|
||||
Yojimbo/1.2.1@gulum/stable
|
||||
vscodepropertiesgen/0.1@mkovalchik/stable
|
||||
|
||||
[options]
|
||||
Entityx:shared=False
|
||||
|
||||
[generators]
|
||||
cmake
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// #pragma once
|
||||
|
||||
// namespace constants {
|
||||
|
||||
// const int CLIENT_PORT = 9999;
|
||||
// const int MAX_CLIENTS = 128;
|
||||
|
||||
// }
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
// #pragma once
|
||||
|
||||
// #define CONNECTION_REQUEST 0x01
|
||||
// #define CONNECTION_ACCEPTED 0x02
|
||||
// #define CONNECTION_DENIED 0x03
|
||||
|
||||
// struct ConnectionRequest {
|
||||
// ConnectionRequest() : type(CONNECTION_REQUEST) {}
|
||||
// char type = CONNECTION_REQUEST;
|
||||
// };
|
||||
|
||||
// struct ConnectionAccepted {
|
||||
// ConnectionAccepted() : type(CONNECTION_ACCEPTED) {}
|
||||
// char type;
|
||||
// int index;
|
||||
// };
|
||||
|
||||
// struct ConnectionDenied {
|
||||
// ConnectionDenied() : type(CONNECTION_DENIED) {}
|
||||
// char type;
|
||||
// };
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
// #include "Server.h"
|
||||
// #include "Protocoll.h"
|
||||
|
||||
// #include <string>
|
||||
// #include <iostream>
|
||||
// #include <thread>
|
||||
|
||||
// Server::Server(int port) : m_maxClients(constants::MAX_CLIENTS), m_clientConnected{0}
|
||||
// {
|
||||
// udpSocket = SDLNet_UDP_Open(port);
|
||||
|
||||
// if (udpSocket == nullptr)
|
||||
// {
|
||||
// std::cout << "\tSDLNet_UDP_Open failed : " << SDLNet_GetError() << std::endl;
|
||||
// }
|
||||
// std::cout << "Server was started and is listening on port: " << port << std::endl;
|
||||
|
||||
// //Creating ConnectionAccepted packet!
|
||||
// // Allocate udp packet with 512 byte size
|
||||
// connectionAccepted = SDLNet_AllocPacket(512);
|
||||
|
||||
// if (connectionAccepted == nullptr)
|
||||
// {
|
||||
// std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl;
|
||||
// }
|
||||
// ConnectionAccepted conAcc = ConnectionAccepted();
|
||||
// memcpy(connectionAccepted->data, &conAcc, sizeof(ConnectionAccepted));
|
||||
// connectionAccepted->len = sizeof(ConnectionAccepted);
|
||||
|
||||
// connectionDenied = SDLNet_AllocPacket(512);
|
||||
|
||||
// if (connectionDenied == nullptr)
|
||||
// {
|
||||
// std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl;
|
||||
// }
|
||||
// ConnectionDenied conDen = ConnectionDenied();
|
||||
// memcpy(connectionDenied->data, &conDen, sizeof(ConnectionDenied));
|
||||
// connectionDenied->len = sizeof(ConnectionDenied);
|
||||
|
||||
// //Creating receiver packet!
|
||||
// receivedPacket = SDLNet_AllocPacket(512);
|
||||
|
||||
// if (receivedPacket == nullptr)
|
||||
// {
|
||||
// std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl;
|
||||
// }
|
||||
// }
|
||||
|
||||
// int Server::FindFreeClientIndex() const
|
||||
// {
|
||||
// for (int i = 0; i < m_maxClients; ++i)
|
||||
// {
|
||||
// if (!m_clientConnected[i])
|
||||
// return i;
|
||||
// }
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// int Server::FindExistingClientIndex(const IPaddress &ip) const
|
||||
// {
|
||||
// for (int i = 0; i < m_maxClients; ++i)
|
||||
// {
|
||||
// if (m_clientConnected[i] && m_clients[i].host == ip.host && m_clients[i].port == ip.port)
|
||||
// return i;
|
||||
// }
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
// bool Server::IsClientConnected(int clientIndex) const
|
||||
// {
|
||||
// return m_clientConnected[clientIndex];
|
||||
// }
|
||||
|
||||
// const IPaddress &Server::GetClientAddress(int clientIndex) const
|
||||
// {
|
||||
// return m_clients[clientIndex];
|
||||
// }
|
||||
|
||||
// void Server::update(unsigned int delta)
|
||||
// {
|
||||
// //Receive packages
|
||||
// if (SDLNet_UDP_Recv(udpSocket, receivedPacket))
|
||||
// {
|
||||
// switch (*(receivedPacket->data))
|
||||
// {
|
||||
// case CONNECTION_REQUEST:
|
||||
// std::cout << "Connection request package received\n";
|
||||
// int freeIndex;
|
||||
// if ((freeIndex = this->FindFreeClientIndex()) == -1)
|
||||
// {
|
||||
// std::cout << "Connection denied because server full" << std::endl;
|
||||
// //Send Connection denied
|
||||
// this->sendConnectionDenied(receivedPacket->address);
|
||||
// break;
|
||||
// }
|
||||
// std::cout << "Free index found: " << freeIndex << std::endl;
|
||||
// int indexOfExistingClient;
|
||||
// if ((indexOfExistingClient = FindExistingClientIndex(receivedPacket->address)) == -1)
|
||||
// {
|
||||
// std::cout << "Client doesent exist create new" << std::endl;
|
||||
// m_clients[freeIndex] = receivedPacket->address;
|
||||
// m_clientConnected[freeIndex] = true;
|
||||
// //Send connection accepted with index
|
||||
// this->sendConnectionAccepted(receivedPacket->address, freeIndex);
|
||||
// m_numConnectedClients++;
|
||||
// break;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// std::cout << "Client exist sending accepted" << std::endl;
|
||||
// //Send connection accepted with index
|
||||
// this->sendConnectionAccepted(receivedPacket->address, indexOfExistingClient);
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// //Wait 10 sec
|
||||
// using namespace std::chrono_literals;
|
||||
// std::this_thread::sleep_for(1s);
|
||||
|
||||
// //Send data
|
||||
// /*for(auto &value: clients) {
|
||||
// value.send(this->udpSocket,*helloWorldPacket);
|
||||
// }
|
||||
// std::cout << "Data was send!!" << std::endl;*/
|
||||
// }
|
||||
|
||||
// bool Server::sendPacket(UDPpacket &packet)
|
||||
// {
|
||||
// // Send
|
||||
// // SDLNet_UDP_Send returns number of packets sent. 0 means error
|
||||
// if (SDLNet_UDP_Send(this->udpSocket, -1, &packet) == 0)
|
||||
// {
|
||||
// std::cout << "\tSDLNet_UDP_Send failed : " << SDLNet_GetError() << "\n"
|
||||
// << "==========================================================================================================\n";
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// bool Server::sendConnectionDenied(IPaddress dest)
|
||||
// {
|
||||
// this->connectionDenied->address.host = dest.host;
|
||||
// this->connectionDenied->address.port = dest.port;
|
||||
// return this->sendPacket(*connectionDenied);
|
||||
// }
|
||||
|
||||
// bool Server::sendConnectionAccepted(IPaddress dest, int index)
|
||||
// {
|
||||
// this->connectionAccepted->address.host = dest.host;
|
||||
// this->connectionAccepted->address.port = dest.port;
|
||||
// ((ConnectionAccepted *) connectionAccepted->data)->index = index;
|
||||
// return this->sendPacket(*connectionAccepted);
|
||||
// }
|
||||
|
||||
// Server::~Server()
|
||||
// {
|
||||
// SDLNet_FreePacket(receivedPacket);
|
||||
// SDLNet_FreePacket(connectionAccepted);
|
||||
// SDLNet_UDP_Close(udpSocket);
|
||||
// }
|
||||
@@ -1,36 +0,0 @@
|
||||
// #pragma once
|
||||
|
||||
// #include <SDL_net.h>
|
||||
// #include "Constants.h"
|
||||
|
||||
// class Server {
|
||||
// public:
|
||||
// Server(int port);
|
||||
// ~Server();
|
||||
|
||||
// int FindFreeClientIndex() const;
|
||||
// int FindExistingClientIndex( const IPaddress &ip ) const;
|
||||
// bool IsClientConnected( int clientIndex ) const;
|
||||
// const IPaddress & GetClientAddress( int clientIndex ) const;
|
||||
|
||||
// void update(unsigned int delta);
|
||||
|
||||
// void gameTick();
|
||||
|
||||
// private:
|
||||
// UDPsocket udpSocket;
|
||||
|
||||
// UDPpacket *connectionDenied;
|
||||
// UDPpacket *connectionAccepted;
|
||||
// UDPpacket *receivedPacket;
|
||||
|
||||
// int m_maxClients;
|
||||
// int m_numConnectedClients;
|
||||
// bool m_clientConnected[constants::MAX_CLIENTS];
|
||||
// IPaddress m_clients[constants::MAX_CLIENTS];
|
||||
|
||||
// bool sendPacket(UDPpacket &packet);
|
||||
|
||||
// bool sendConnectionDenied(IPaddress dest);
|
||||
// bool sendConnectionAccepted(IPaddress dest, int index);
|
||||
// };
|
||||
12
protocol.md
12
protocol.md
@@ -1,12 +0,0 @@
|
||||
## Loading Screen
|
||||
|
||||
- [Client]
|
||||
Client sends unique UserID.
|
||||
|
||||
- [Server]
|
||||
assign slot to Client
|
||||
|
||||
- [Client]
|
||||
Send User Name
|
||||
|
||||
- [Server_START_UPDATE_ROUTINE]
|
||||
@@ -1,6 +1,11 @@
|
||||
//std
|
||||
#include <signal.h>
|
||||
#include <iostream>
|
||||
|
||||
//thread
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
// Vendor
|
||||
#include <yojimbo.h>
|
||||
|
||||
@@ -18,7 +23,26 @@ static GameServer *serv;
|
||||
|
||||
void interrupt_handler(int /*dummy*/)
|
||||
{
|
||||
serv->m_running = false;
|
||||
serv->dispatchCommand("stop");
|
||||
}
|
||||
|
||||
void ReadCin(std::atomic<bool> &run)
|
||||
{
|
||||
std::string buffer;
|
||||
|
||||
while (run.load())
|
||||
{
|
||||
std::getline(std::cin, buffer);
|
||||
serv->dispatchCommand(buffer);
|
||||
if (buffer == "stop")
|
||||
{
|
||||
run.store(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parseArguments() {
|
||||
//TODO
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -29,12 +53,12 @@ int main(int argc, char *argv[])
|
||||
DWORD prev_mode;
|
||||
hInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
GetConsoleMode(hInput, &prev_mode);
|
||||
SetConsoleMode(hInput, prev_mode & ENABLE_EXTENDED_FLAGS);
|
||||
prev_mode &= ~ENABLE_QUICK_EDIT_MODE;
|
||||
SetConsoleMode(hInput, prev_mode);
|
||||
#endif
|
||||
|
||||
if (!InitializeYojimbo())
|
||||
{
|
||||
printf("error: failed to initialize Yojimbo!\n");
|
||||
std::cout << "error: failed to initialize Yojimbo!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
yojimbo_log_level(YOJIMBO_LOG_LEVEL_INFO);
|
||||
@@ -45,8 +69,15 @@ int main(int argc, char *argv[])
|
||||
yojimbo::Address addr(127, 0, 0, 1, 9999);
|
||||
GameServer server(addr);
|
||||
serv = &server; //For interrupt
|
||||
|
||||
std::atomic<bool> run(true);
|
||||
std::thread cinThread(ReadCin, std::ref(run));
|
||||
|
||||
server.Run();
|
||||
|
||||
run.store(false);
|
||||
cinThread.join();
|
||||
|
||||
ShutdownYojimbo();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#include <memory>
|
||||
|
||||
//own
|
||||
#include "messages/Command.h"
|
||||
#include "core/Components.h"
|
||||
#include "core/systems/PhysicSharer.h"
|
||||
#include "core/systems/InputProcessor.h"
|
||||
|
||||
using namespace yojimbo;
|
||||
|
||||
@@ -18,7 +19,8 @@ GameServer::GameServer(const yojimbo::Address &address) : m_time(yojimbo_time())
|
||||
m_connectionConfig,
|
||||
m_adapter,
|
||||
m_time),
|
||||
m_running(false)
|
||||
m_running(false),
|
||||
world(b2Vec2(0.0, 0.0)) //2D top down gravity
|
||||
{
|
||||
// start the server
|
||||
m_server.Start(MAX_PLAYERS);
|
||||
@@ -32,12 +34,42 @@ GameServer::GameServer(const yojimbo::Address &address) : m_time(yojimbo_time())
|
||||
m_server.GetAddress().ToString(buffer, sizeof(buffer));
|
||||
|
||||
// ... load game ...
|
||||
ex.systems.add<PhysicsShareSystem>(this);
|
||||
ex.systems.add<InputProcessor>(this);
|
||||
ex.systems.configure();
|
||||
|
||||
// load an custom object
|
||||
// entityx::Entity entity = ex.entities.create();
|
||||
// b2BodyDef playerBodyDef;
|
||||
// playerBodyDef.type = b2_kinematicBody;
|
||||
// playerBodyDef.position.Set(0.0f, 0.0f);
|
||||
// b2Body *bod = this->world.CreateBody(&playerBodyDef);
|
||||
|
||||
// b2PolygonShape hitbox;
|
||||
// hitbox.SetAsBox(5.0f, 5.0f);
|
||||
|
||||
// bod->CreateFixture(&hitbox, 0.0f);
|
||||
// entity.assign<PhysicBody>(bod);
|
||||
//TODO: -- add box2d components --
|
||||
}
|
||||
|
||||
void GameServer::ClientConnected(int clientIndex)
|
||||
{
|
||||
entityx::Entity entity = ex.entities.create();
|
||||
entity.assign<NetworkPlayerProperties>();
|
||||
//---Add network info
|
||||
entity.assign<NetworkPlayerProperties>(clientIndex);
|
||||
//---Add networked physics
|
||||
b2BodyDef playerBodyDef;
|
||||
playerBodyDef.type = b2_kinematicBody;
|
||||
playerBodyDef.position.Set(0.0f, 0.0f);
|
||||
b2Body *bod = this->world.CreateBody(&playerBodyDef);
|
||||
|
||||
b2PolygonShape hitbox;
|
||||
hitbox.SetAsBox(5.0f, 5.0f);
|
||||
bod->CreateFixture(&hitbox, 0.0f);
|
||||
entity.assign<PhysicBody>(bod);
|
||||
entity.assign<InputVelocity>(0.0f,0.0f);
|
||||
//--Usual continue
|
||||
serverToEntityX.insert(std::pair<int, entityx::Entity>(clientIndex, entity));
|
||||
std::cout << "client " << clientIndex << " connected" << std::endl;
|
||||
}
|
||||
@@ -86,12 +118,38 @@ void GameServer::Update(float dt)
|
||||
ProcessMessages();
|
||||
|
||||
// ... process client inputs ...
|
||||
this->m_commandQueueMutex.lock(); //As long as the server is processing the que the adding is blocked
|
||||
while (!this->commandQueue.empty())
|
||||
{
|
||||
std::unique_ptr<Command> command_ptr = std::move(commandQueue.front());
|
||||
commandQueue.pop();
|
||||
command_ptr->execute(this);
|
||||
}
|
||||
this->m_commandQueueMutex.unlock();
|
||||
|
||||
// ... update game ...
|
||||
int velocityIterations = 6;
|
||||
int positionIterations = 2;
|
||||
this->world.Step(dt, velocityIterations, positionIterations);
|
||||
|
||||
// ... send game state to clients ...
|
||||
ex.systems.update<InputProcessor>(dt);
|
||||
// ex.systems.update<PhysicsShareSystem>(dt);
|
||||
|
||||
m_server.SendPackets();
|
||||
}
|
||||
|
||||
void GameServer::dispatchCommand(std::string commandStr) //thread safe
|
||||
{
|
||||
std::unique_ptr<Command> u_ptr(Command::create(commandStr));
|
||||
if (u_ptr)
|
||||
{
|
||||
this->m_commandQueueMutex.lock();
|
||||
this->commandQueue.push(std::move(u_ptr));
|
||||
this->m_commandQueueMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void GameServer::ProcessMessages()
|
||||
{
|
||||
for (int i = 0; i < MAX_PLAYERS; i++)
|
||||
@@ -106,7 +164,9 @@ void GameServer::ProcessMessages()
|
||||
std::unique_ptr<Command> command(Command::create(i, message));
|
||||
if (command)
|
||||
{
|
||||
command->execute(this);
|
||||
this->m_commandQueueMutex.lock();
|
||||
this->commandQueue.push(std::move(command));
|
||||
this->m_commandQueueMutex.unlock();
|
||||
}
|
||||
m_server.ReleaseMessage(i, message);
|
||||
message = m_server.ReceiveMessage(i, j);
|
||||
@@ -115,21 +175,3 @@ void GameServer::ProcessMessages()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerAdapter::ServerAdapter(GameServer *server) : m_server(server) {}
|
||||
|
||||
void ServerAdapter::OnServerClientConnected(int clientIndex)
|
||||
{
|
||||
if (m_server != NULL)
|
||||
{
|
||||
m_server->ClientConnected(clientIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerAdapter::OnServerClientDisconnected(int clientIndex)
|
||||
{
|
||||
if (m_server != NULL)
|
||||
{
|
||||
m_server->ClientDisconnected(clientIndex);
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,22 @@
|
||||
//Std
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
//Vendor
|
||||
#include <yojimbo.h>
|
||||
#include <entityx/entityx.h>
|
||||
|
||||
//Own
|
||||
#include "Shared.h"
|
||||
|
||||
static const int MAX_PLAYERS = 64;
|
||||
#include <Box2D/Box2D.h>
|
||||
|
||||
class GameServer;
|
||||
|
||||
//Own
|
||||
#include "network/Shared.h"
|
||||
#include "commands/Command.h"
|
||||
|
||||
static const int MAX_PLAYERS = 64;
|
||||
|
||||
class ServerAdapter : public SharedAdapter
|
||||
{
|
||||
public:
|
||||
@@ -37,24 +41,28 @@ public:
|
||||
void ClientConnected(int clientIndex);
|
||||
void ClientDisconnected(int clientIndex);
|
||||
|
||||
void ProcessCommand(std::string command);
|
||||
void dispatchCommand(std::string commandStr); //thread safe
|
||||
void ProcessMessages();
|
||||
void ProcessMessage(int clientIndex, yojimbo::Message *message);
|
||||
|
||||
void Run();
|
||||
void Update(float dt);
|
||||
|
||||
bool m_running;
|
||||
|
||||
entityx::EntityX ex;
|
||||
std::map<int, entityx::Entity> serverToEntityX;
|
||||
std::queue<std::unique_ptr<Command>> commandQueue;
|
||||
|
||||
private:
|
||||
double m_time;
|
||||
entityx::EntityX ex;
|
||||
b2World world;
|
||||
|
||||
std::map<int, entityx::Entity> serverToEntityX;
|
||||
|
||||
GameConnectionConfig m_connectionConfig;
|
||||
ServerAdapter m_adapter;
|
||||
yojimbo::Server m_server;
|
||||
|
||||
private:
|
||||
double m_time;
|
||||
std::mutex m_commandQueueMutex;
|
||||
};
|
||||
|
||||
#endif //GAMESERVER_H
|
||||
42
src/commands/Command.cpp
Normal file
42
src/commands/Command.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "Command.h"
|
||||
#include "../network/Shared.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
Command *Command::create(int clientIndex, yojimbo::Message *message)
|
||||
{
|
||||
switch (message->GetType())
|
||||
{
|
||||
case (int)GameMessageType::TEST:
|
||||
return new TestCommand(clientIndex, ((TestMessage *)message)->m_data);
|
||||
case (int)GameMessageType::SETNAME:
|
||||
return new SetNameCommand(clientIndex, std::string(((SetNameMessage *)message)->buffer));
|
||||
case (int)GameMessageType::INPUTSTATEMESSAGE:
|
||||
return new PlayerInputCommand(clientIndex, ((InputStateMessage *) message)->m_vel_x, ((InputStateMessage *) message)->m_vel_y);
|
||||
default:
|
||||
std::cout << "Unknown message type received over network!" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Command *Command::create(std::string command)
|
||||
{
|
||||
std::stringstream ss(command);
|
||||
std::string token;
|
||||
ss >>
|
||||
token;
|
||||
if (token == "stop")
|
||||
{
|
||||
return new StopCommand();
|
||||
}
|
||||
else if (token == "test")
|
||||
{
|
||||
return new TestCommand(-1, 100);
|
||||
} else if (token == "sendTest")
|
||||
{
|
||||
return new SendTestCommand(0, 42);
|
||||
}
|
||||
std::cout << "Local command don't exists: " << command << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
94
src/commands/Command.h
Normal file
94
src/commands/Command.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
//Vendor
|
||||
#include <yojimbo.h>
|
||||
|
||||
class Command;
|
||||
#include "../GameServer.h"
|
||||
|
||||
// ---- Interface:
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
// Create Commands from Network messages (Limited list)
|
||||
static Command *create(int clientIndex, yojimbo::Message *message);
|
||||
// Create Commands from Strings internal (Limited list)
|
||||
static Command *create(std::string);
|
||||
|
||||
virtual void execute(GameServer *server) = 0;
|
||||
};
|
||||
|
||||
// --- Classes Network:
|
||||
|
||||
class TestCommand : public Command
|
||||
{
|
||||
public:
|
||||
TestCommand(int clientIndex, int data)
|
||||
: m_clientIndex(clientIndex),
|
||||
m_data(data)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void execute(GameServer *server) override;
|
||||
|
||||
private:
|
||||
int m_clientIndex;
|
||||
int m_data;
|
||||
};
|
||||
|
||||
class SetNameCommand : public Command
|
||||
{
|
||||
public:
|
||||
SetNameCommand(int clientIndex, std::string name)
|
||||
: m_clientIndex(clientIndex),
|
||||
m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void execute(GameServer *server) override;
|
||||
|
||||
private:
|
||||
int m_clientIndex;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
// --- Classes local:
|
||||
|
||||
class StopCommand : public Command
|
||||
{
|
||||
public:
|
||||
virtual void execute(GameServer *server) override;
|
||||
};
|
||||
|
||||
class SendTestCommand : public Command
|
||||
{
|
||||
public:
|
||||
SendTestCommand(int clientIndex, int data)
|
||||
: m_clientIndex(clientIndex),
|
||||
m_data(data)
|
||||
{
|
||||
}
|
||||
virtual void execute(GameServer *server) override;
|
||||
|
||||
private:
|
||||
int m_clientIndex;
|
||||
int m_data;
|
||||
};
|
||||
|
||||
class PlayerInputCommand : public Command
|
||||
{
|
||||
public:
|
||||
PlayerInputCommand(int clientIndex, float vel_x, float vel_y)
|
||||
: m_clientIndex(clientIndex),
|
||||
m_vel_x(vel_x),
|
||||
m_vel_y(vel_y)
|
||||
{
|
||||
}
|
||||
virtual void execute(GameServer *server) override;
|
||||
|
||||
private:
|
||||
int m_clientIndex;
|
||||
float m_vel_x, m_vel_y;
|
||||
};
|
||||
|
||||
14
src/commands/PlayerInputCommand.cpp
Normal file
14
src/commands/PlayerInputCommand.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "Command.h"
|
||||
|
||||
#include "../core/Components.h"
|
||||
|
||||
void PlayerInputCommand::execute(GameServer *server)
|
||||
{
|
||||
entityx::Entity entity = server->serverToEntityX.at(m_clientIndex);
|
||||
entityx::ComponentHandle<InputVelocity> iVel = entity.component<InputVelocity>();
|
||||
if (iVel)
|
||||
{
|
||||
iVel->m_vel_x = this->m_vel_x;
|
||||
iVel->m_vel_y = this->m_vel_y;
|
||||
}
|
||||
}
|
||||
9
src/commands/SendTestCommand.cpp
Normal file
9
src/commands/SendTestCommand.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "Command.h"
|
||||
|
||||
void SendTestCommand::execute(GameServer *server)
|
||||
{
|
||||
std::cout << "Sending Test command to ClientID: " << this->m_clientIndex << " with data: " << this->m_data << std::endl;
|
||||
TestMessage *msg = (TestMessage *)server->m_server.CreateMessage(this->m_clientIndex, (int)GameMessageType::TEST);
|
||||
msg->m_data = this->m_data;
|
||||
server->m_server.SendMessage(this->m_clientIndex, (int)GameChannel::RELIABLE, msg);
|
||||
}
|
||||
@@ -8,7 +8,7 @@ void SetNameCommand::execute(GameServer *server)
|
||||
entityx::ComponentHandle<NetworkPlayerProperties> playerproperties = entity.component<NetworkPlayerProperties>();
|
||||
if (playerproperties)
|
||||
{
|
||||
playerproperties->name = std::string(m_message->buffer);
|
||||
playerproperties->name = m_name;
|
||||
}
|
||||
std::cout << "Entity name changed to " << playerproperties->name << " Buffer content: " << std::string(m_message->buffer) << std::endl;
|
||||
std::cout << "Entity name changed to " << playerproperties->name << " Buffer content: " << m_name << std::endl;
|
||||
}
|
||||
6
src/commands/StopCommand.cpp
Normal file
6
src/commands/StopCommand.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "Command.h"
|
||||
|
||||
void StopCommand::execute(GameServer *server)
|
||||
{
|
||||
server->m_running = false;
|
||||
}
|
||||
17
src/commands/TestCommand.cpp
Normal file
17
src/commands/TestCommand.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "Command.h"
|
||||
|
||||
#include "../core/Components.h"
|
||||
|
||||
void TestCommand::execute(GameServer *server)
|
||||
{
|
||||
if (m_clientIndex == -1)
|
||||
{
|
||||
std::cout << "Test message received from server cmd :" << m_clientIndex << " with data: " << m_data << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
entityx::Entity entity = server->serverToEntityX.at(m_clientIndex);
|
||||
entityx::ComponentHandle<NetworkPlayerProperties> playerproperties = entity.component<NetworkPlayerProperties>();
|
||||
std::cout << "Test message received from client " << playerproperties->name << ":" << m_clientIndex << " with data: " << m_data << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,29 @@
|
||||
|
||||
struct NetworkPlayerProperties
|
||||
{
|
||||
NetworkPlayerProperties(std::string name = "unknown")
|
||||
: name(name) {}
|
||||
NetworkPlayerProperties(int clientIndex,std::string name = "unknown")
|
||||
: name(name),
|
||||
m_clientIndex(clientIndex)
|
||||
{}
|
||||
|
||||
std::string name;
|
||||
int m_clientIndex;
|
||||
};
|
||||
|
||||
#include <Box2D/Box2D.h>
|
||||
|
||||
struct PhysicBody
|
||||
{
|
||||
PhysicBody(b2Body* b) : body(b) {}
|
||||
|
||||
b2Body* body;
|
||||
};
|
||||
|
||||
struct InputVelocity
|
||||
{
|
||||
InputVelocity(float vel_x, float vel_y)
|
||||
: m_vel_x(vel_x), m_vel_y(vel_y)
|
||||
{}
|
||||
|
||||
float m_vel_x, m_vel_y;
|
||||
};
|
||||
18
src/core/systems/DebugPositionPrinter.h
Normal file
18
src/core/systems/DebugPositionPrinter.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <entityx/entityx.h>
|
||||
#include "../../GameServer.h"
|
||||
#include "../Components.h"
|
||||
|
||||
struct DebugPositionPrinter : public entityx::System<DebugPositionPrinter>
|
||||
{
|
||||
DebugPositionPrinter(GameServer *server) : m_gserver(server) {}
|
||||
GameServer *m_gserver;
|
||||
|
||||
void update(entityx::EntityManager &es, entityx::EventManager &events, entityx::TimeDelta dt) override
|
||||
{
|
||||
es.each<NetworkPlayerProperties, PhysicBody>([](entityx::Entity entity, NetworkPlayerProperties &nProp, PhysicBody &bod) {
|
||||
std::cout << "Client " << nProp.name << ":" << nProp.m_clientIndex << " Pos: " << bod.body->GetPosition << std::endl;
|
||||
});
|
||||
};
|
||||
};
|
||||
19
src/core/systems/InputProcessor.h
Normal file
19
src/core/systems/InputProcessor.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <entityx/entityx.h>
|
||||
#include "../../GameServer.h"
|
||||
#include "../Components.h"
|
||||
|
||||
struct InputProcessor : public entityx::System<InputProcessor>
|
||||
{
|
||||
InputProcessor(GameServer *server) : m_gserver(server) {}
|
||||
GameServer *m_gserver;
|
||||
|
||||
void update(entityx::EntityManager &es, entityx::EventManager &events, entityx::TimeDelta dt) override
|
||||
{
|
||||
//For each with input component look for id
|
||||
es.each<InputVelocity, PhysicBody>([](entityx::Entity entity, InputVelocity &iVel, PhysicBody &bod) {
|
||||
// Do things with entity, position and direction.
|
||||
});
|
||||
};
|
||||
};
|
||||
26
src/core/systems/PhysicSharer.h
Normal file
26
src/core/systems/PhysicSharer.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <entityx/entityx.h>
|
||||
#include "../../GameServer.h"
|
||||
#include "../Components.h"
|
||||
|
||||
struct PhysicsShareSystem : public entityx::System<PhysicsShareSystem>
|
||||
{
|
||||
PhysicsShareSystem(GameServer *server) : m_gserver(server) {}
|
||||
GameServer *m_gserver;
|
||||
|
||||
void update(entityx::EntityManager &es, entityx::EventManager &events, entityx::TimeDelta dt) override
|
||||
{
|
||||
es.each<PhysicBody>([&es, dt, this](entityx::Entity entity, PhysicBody &body) { //For every phyicbody filter networked kinematic bodys
|
||||
//ONLY 10 TIMES PER SECOND
|
||||
//body.body->IsActive
|
||||
es.each<NetworkPlayerProperties>([body, dt, this](entityx::Entity entity, NetworkPlayerProperties &net) { //For every networkplayer
|
||||
PhysicStateMessage *msg = (PhysicStateMessage *)this->m_gserver->m_server.CreateMessage(net.m_clientIndex, (int)GameMessageType::PHYSICSTATEMESSAGE);
|
||||
msg->isActive = body.body->IsActive();
|
||||
msg->m_posX = body.body->GetPosition().x;
|
||||
msg->m_posY = body.body->GetPosition().y;
|
||||
this->m_gserver->m_server.SendMessage(net.m_clientIndex, (int)GameChannel::UNRELIABLE, msg);
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
#include "Command.h"
|
||||
#include "../Shared.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
Command *Command::create(int clientIndex, yojimbo::Message *message)
|
||||
{
|
||||
switch (message->GetType())
|
||||
{
|
||||
case (int)GameMessageType::TEST:
|
||||
return new TestCommand(clientIndex, message);
|
||||
break;
|
||||
case (int)GameMessageType::SETNAME:
|
||||
return new SetNameCommand(clientIndex, message);
|
||||
break;
|
||||
default:
|
||||
std::cout << "Unknown message type received!" << std::endl;
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
//Vendor
|
||||
#include <yojimbo.h>
|
||||
#include "../GameServer.h"
|
||||
|
||||
// ---- Interface:
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
// Create Commands from Network messages (Limited list)
|
||||
static Command *create(int clientIndex, yojimbo::Message *message);
|
||||
// Create Commands from Strings (Limited list)
|
||||
virtual void execute(GameServer *server) = 0;
|
||||
};
|
||||
|
||||
// --- implemented Classes:
|
||||
|
||||
class TestCommand : public Command
|
||||
{
|
||||
public:
|
||||
TestCommand(int clientIndex, yojimbo::Message *message)
|
||||
: m_clientIndex(clientIndex), m_message((TestMessage *)message) {}
|
||||
|
||||
virtual void execute(GameServer *server) override;
|
||||
|
||||
private:
|
||||
int m_clientIndex;
|
||||
TestMessage *m_message;
|
||||
};
|
||||
|
||||
class SetNameCommand : public Command
|
||||
{
|
||||
public:
|
||||
SetNameCommand(int clientIndex, yojimbo::Message *message)
|
||||
: m_clientIndex(clientIndex), m_message((SetNameMessage *)message) {}
|
||||
|
||||
virtual void execute(GameServer *server) override;
|
||||
|
||||
private:
|
||||
int m_clientIndex;
|
||||
SetNameMessage *m_message;
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
#include "Command.h"
|
||||
|
||||
#include "../core/Components.h"
|
||||
|
||||
void TestCommand::execute(GameServer *server)
|
||||
{
|
||||
// ... process test message ...
|
||||
entityx::Entity entity = server->serverToEntityX.at(m_clientIndex);
|
||||
entityx::ComponentHandle<NetworkPlayerProperties> playerproperties = entity.component<NetworkPlayerProperties>();
|
||||
|
||||
std::cout << "Test message received from client " << playerproperties->name << ":" << m_clientIndex << " with data: " << m_message->m_data << std::endl;
|
||||
}
|
||||
20
src/network/ServerAdapter.cpp
Normal file
20
src/network/ServerAdapter.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "../GameServer.h"
|
||||
|
||||
|
||||
ServerAdapter::ServerAdapter(GameServer *server) : m_server(server) {}
|
||||
|
||||
void ServerAdapter::OnServerClientConnected(int clientIndex)
|
||||
{
|
||||
if (m_server != NULL)
|
||||
{
|
||||
m_server->ClientConnected(clientIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerAdapter::OnServerClientDisconnected(int clientIndex)
|
||||
{
|
||||
if (m_server != NULL)
|
||||
{
|
||||
m_server->ClientDisconnected(clientIndex);
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,6 @@
|
||||
|
||||
#include <yojimbo.h>
|
||||
|
||||
// a simple test message
|
||||
enum class GameMessageType
|
||||
{
|
||||
TEST,
|
||||
SETNAME,
|
||||
COUNT
|
||||
};
|
||||
|
||||
// two channels, one for each type that Yojimbo supports
|
||||
enum class GameChannel
|
||||
{
|
||||
@@ -30,6 +22,16 @@ struct GameConnectionConfig : yojimbo::ClientServerConfig
|
||||
}
|
||||
};
|
||||
|
||||
// message types
|
||||
enum class GameMessageType
|
||||
{
|
||||
TEST,
|
||||
SETNAME,
|
||||
PHYSICSTATEMESSAGE,
|
||||
INPUTSTATEMESSAGE,
|
||||
COUNT
|
||||
};
|
||||
|
||||
class TestMessage : public yojimbo::Message
|
||||
{
|
||||
public:
|
||||
@@ -51,8 +53,7 @@ class SetNameMessage : public yojimbo::Message
|
||||
{
|
||||
public:
|
||||
char buffer[yojimbo::MaxAddressLength];
|
||||
SetNameMessage() {
|
||||
}
|
||||
SetNameMessage() {}
|
||||
|
||||
template <typename Stream>
|
||||
bool Serialize(Stream &stream)
|
||||
@@ -64,22 +65,62 @@ public:
|
||||
YOJIMBO_VIRTUAL_SERIALIZE_FUNCTIONS();
|
||||
};
|
||||
|
||||
class PhysicStateMessage : public yojimbo::Message
|
||||
{
|
||||
public:
|
||||
int m_objectID;
|
||||
float m_posX;
|
||||
float m_posY;
|
||||
bool isActive;
|
||||
PhysicStateMessage() : m_objectID(0), m_posX(0), m_posY(0), isActive(false) {}
|
||||
|
||||
template <typename Stream>
|
||||
bool Serialize(Stream &stream)
|
||||
{
|
||||
serialize_int(stream, m_objectID, 0, 512);
|
||||
serialize_float(stream, m_posX);
|
||||
serialize_float(stream, m_posY);
|
||||
serialize_bool(stream, isActive);
|
||||
return true;
|
||||
}
|
||||
|
||||
YOJIMBO_VIRTUAL_SERIALIZE_FUNCTIONS();
|
||||
};
|
||||
|
||||
class InputStateMessage : public yojimbo::Message
|
||||
{
|
||||
public:
|
||||
float m_vel_x, m_vel_y;
|
||||
|
||||
InputStateMessage() : m_vel_x(0), m_vel_y(0) {}
|
||||
|
||||
template <typename Stream>
|
||||
bool Serialize(Stream &stream)
|
||||
{
|
||||
serialize_float(stream, m_vel_x);
|
||||
serialize_float(stream, m_vel_y);
|
||||
return true;
|
||||
}
|
||||
|
||||
YOJIMBO_VIRTUAL_SERIALIZE_FUNCTIONS();
|
||||
};
|
||||
|
||||
// the message factory
|
||||
YOJIMBO_MESSAGE_FACTORY_START(GameMessageFactory, (int)GameMessageType::COUNT);
|
||||
YOJIMBO_DECLARE_MESSAGE_TYPE((int)GameMessageType::TEST, TestMessage);
|
||||
YOJIMBO_DECLARE_MESSAGE_TYPE((int)GameMessageType::SETNAME, SetNameMessage);
|
||||
YOJIMBO_DECLARE_MESSAGE_TYPE((int)GameMessageType::TEST, TestMessage);
|
||||
YOJIMBO_DECLARE_MESSAGE_TYPE((int)GameMessageType::SETNAME, SetNameMessage);
|
||||
YOJIMBO_DECLARE_MESSAGE_TYPE((int)GameMessageType::PHYSICSTATEMESSAGE, PhysicStateMessage);
|
||||
YOJIMBO_DECLARE_MESSAGE_TYPE((int)GameMessageType::INPUTSTATEMESSAGE, InputStateMessage);
|
||||
YOJIMBO_MESSAGE_FACTORY_FINISH();
|
||||
|
||||
// the adapter
|
||||
class SharedAdapter : public yojimbo::Adapter
|
||||
{
|
||||
public:
|
||||
|
||||
yojimbo::MessageFactory *CreateMessageFactory(yojimbo::Allocator &allocator) override
|
||||
{
|
||||
return YOJIMBO_NEW(allocator, GameMessageFactory, allocator);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static const uint8_t DEFAULT_PRIVATE_KEY[yojimbo::KeyBytes] = {0};
|
||||
@@ -1,41 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(DarkRP2D_TEST_CLIENT)
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
include(ExternalProject)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RELEASE)
|
||||
add_definitions(-DNDEBUG)
|
||||
endif(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
MESSAGE( STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR} )
|
||||
MESSAGE( STATUS "DarkRP2D_TEST_CLIENT_SOURCE_DIR: " ${DarkRP2D_TEST_CLIENT_SOURCE_DIR} )
|
||||
|
||||
set(DarkRP2D_EXTERNAL_DIR ${DarkRP2D_TEST_CLIENT_SOURCE_DIR}/../external)
|
||||
set(SDL2_net_DIR ${DarkRP2D_EXTERNAL_DIR}/SDL2_net-2.0.1)
|
||||
set(SDL2_DIR ${DarkRP2D_EXTERNAL_DIR}/SDL2-2.0.8)
|
||||
|
||||
#Libs
|
||||
|
||||
find_package(SDL2 REQUIRED CONFIG)
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
|
||||
find_package(SDL2_net REQUIRED CONFIG)
|
||||
include_directories(${SDL2_NET_INCLUDE_DIRS})
|
||||
|
||||
MESSAGE( STATUS "SDL2 Lib: " ${SDL2_LIBRARIES} )
|
||||
MESSAGE( STATUS "SDL2_NET Lib: " ${SDL2_NET_LIBRARIES} )
|
||||
|
||||
file(GLOB_RECURSE DarkRP2D_TEST_CLIENT_SOURCE_FILES ${DarkRP2D_TEST_CLIENT_SOURCE_DIR}/src/*.cpp)
|
||||
|
||||
add_executable(DarkRP2DTestClient ${DarkRP2D_TEST_CLIENT_SOURCE_FILES})
|
||||
|
||||
target_link_libraries(DarkRP2DTestClient ${SDL2_LIBRARIES}
|
||||
${SDL2_NET_LIBRARIES} )
|
||||
|
||||
add_custom_target(CopyBinaries
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${SDL2_DLL} ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${SDL2_NET_DLL} ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_dependencies(DarkRP2DTestClient CopyBinaries)
|
||||
@@ -1,87 +0,0 @@
|
||||
#include "Client.h"
|
||||
#include "Constants.h"
|
||||
#include "Protocoll.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
Client::Client(std::string _serverIP, int port) : connected(new Connected(this)),
|
||||
connecting(new Connecting(this)),
|
||||
disconnected(new Disconnected(this))
|
||||
{
|
||||
|
||||
udpSocket = SDLNet_UDP_Open(constants::CLIENT_PORT);
|
||||
|
||||
if (udpSocket == nullptr)
|
||||
{
|
||||
std::cout << "\tSDLNet_UDP_Open failed : " << SDLNet_GetError() << std::endl;
|
||||
}
|
||||
|
||||
// Set IP and port number with correct endianess
|
||||
if (SDLNet_ResolveHost(&serverIP, _serverIP.c_str(), port) == -1)
|
||||
{
|
||||
std::cout << "\tSDLNet_ResolveHost failed : " << SDLNet_GetError() << std::endl;
|
||||
}
|
||||
|
||||
connectionRequest = SDLNet_AllocPacket(512);
|
||||
|
||||
if (connectionRequest == nullptr)
|
||||
{
|
||||
std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl;
|
||||
}
|
||||
ConnectionRequest conReq = ConnectionRequest();
|
||||
memcpy(connectionRequest->data, &conReq, sizeof(ConnectionRequest));
|
||||
connectionRequest->len = sizeof(ConnectionRequest);
|
||||
|
||||
receivedPacket = SDLNet_AllocPacket(512);
|
||||
|
||||
if (receivedPacket == nullptr)
|
||||
{
|
||||
std::cout << "\tSDLNet_AllocPacket failed : " << SDLNet_GetError() << std::endl;
|
||||
}
|
||||
|
||||
this->setClientState(connecting);
|
||||
}
|
||||
|
||||
void Client::setClientState(ClientState *state)
|
||||
{
|
||||
std::cout << "State changed!" << std::endl;
|
||||
currentState = state;
|
||||
}
|
||||
|
||||
void Client::update(unsigned int delta)
|
||||
{
|
||||
currentState->update(delta);
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(2s);
|
||||
}
|
||||
|
||||
bool Client::sendConnectionRequest(IPaddress dest)
|
||||
{
|
||||
connectionRequest->address.host = dest.host;
|
||||
connectionRequest->address.port = dest.port;
|
||||
return this->sendPacket(*connectionRequest);
|
||||
}
|
||||
|
||||
bool Client::sendPacket(UDPpacket &packet)
|
||||
{
|
||||
// Send
|
||||
// SDLNet_UDP_Send returns number of packets sent. 0 means error
|
||||
if (SDLNet_UDP_Send(this->udpSocket, -1, &packet) == 0)
|
||||
{
|
||||
std::cout << "\tSDLNet_UDP_Send failed : " << SDLNet_GetError() << "\n"
|
||||
<< "==========================================================================================================\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
{
|
||||
delete connected;
|
||||
delete connecting;
|
||||
delete disconnected;
|
||||
SDLNet_FreePacket(connectionRequest);
|
||||
SDLNet_FreePacket(receivedPacket);
|
||||
SDLNet_UDP_Close(udpSocket);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL_net.h>
|
||||
#include <string>
|
||||
|
||||
class Client;
|
||||
|
||||
#include "ClientStates.h"
|
||||
|
||||
|
||||
class Client {
|
||||
public:
|
||||
Client(std::string serverIP, int port);
|
||||
~Client();
|
||||
|
||||
Client(const Client&) = delete;
|
||||
|
||||
void setClientState(ClientState *state);
|
||||
|
||||
void update(unsigned int delta);
|
||||
|
||||
|
||||
bool sendConnectionRequest(IPaddress dest);
|
||||
bool sendPacket(UDPpacket &packet);
|
||||
|
||||
UDPsocket udpSocket;
|
||||
IPaddress serverIP;
|
||||
|
||||
UDPpacket *connectionRequest;
|
||||
UDPpacket *receivedPacket;
|
||||
|
||||
ClientState *currentState;
|
||||
|
||||
Connected *connected;
|
||||
Connecting *connecting;
|
||||
Disconnected *disconnected;
|
||||
};
|
||||
@@ -1,40 +0,0 @@
|
||||
#include "ClientStates.h"
|
||||
|
||||
#include "Protocoll.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void Connecting::update(unsigned int delta)
|
||||
{
|
||||
std::cout << "Connecting.. (Sending Request)" << std::endl;
|
||||
m_client->sendConnectionRequest(m_client->serverIP);
|
||||
if (SDLNet_UDP_Recv(m_client->udpSocket, m_client->receivedPacket))
|
||||
{
|
||||
std::cout << "Something received.." << std::endl;
|
||||
switch (*(m_client->receivedPacket->data))
|
||||
{
|
||||
case CONNECTION_ACCEPTED:
|
||||
{
|
||||
int index = ((ConnectionAccepted *)(m_client->receivedPacket->data))->index;
|
||||
std::cout << "Server accepted Connection! My Index ist: " << index << std::endl;
|
||||
m_client->setClientState(m_client->connected);
|
||||
}
|
||||
break;
|
||||
case CONNECTION_DENIED:
|
||||
std::cout << "Server denied Connection!" << std::endl;
|
||||
m_client->setClientState(m_client->disconnected);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Connected::update(unsigned int delta)
|
||||
{
|
||||
std::cout << "I AM IN CONNECTED STATE!" << std::endl;
|
||||
}
|
||||
|
||||
void Disconnected::update(unsigned int delta)
|
||||
{
|
||||
std::cout << "I AM IN DISCONNECTED STATE!" << std::endl;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class ClientState;
|
||||
|
||||
class Connecting;
|
||||
class Connected;
|
||||
class Disconnected;
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
class ClientState
|
||||
{
|
||||
public:
|
||||
virtual void update(unsigned int delta) = 0;
|
||||
};
|
||||
|
||||
class Connecting : public ClientState {
|
||||
public:
|
||||
Connecting(Client *client) : m_client(client) {}
|
||||
|
||||
virtual void update(unsigned int delta) override;
|
||||
|
||||
private:
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
class Connected : public ClientState
|
||||
{
|
||||
public:
|
||||
Connected(Client *client) : m_client(client) {}
|
||||
|
||||
virtual void update(unsigned int delta) override;
|
||||
|
||||
private:
|
||||
Client *m_client;
|
||||
};
|
||||
|
||||
class Disconnected : public ClientState
|
||||
{
|
||||
public:
|
||||
Disconnected(Client *client) : m_client(client) {}
|
||||
|
||||
virtual void update(unsigned int delta) override;
|
||||
|
||||
private:
|
||||
Client *m_client;
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace constants {
|
||||
|
||||
const int CLIENT_PORT = 9999;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define CONNECTION_REQUEST 0x01
|
||||
#define CONNECTION_ACCEPTED 0x02
|
||||
#define CONNECTION_DENIED 0x03
|
||||
|
||||
struct ConnectionRequest {
|
||||
ConnectionRequest() : type(CONNECTION_REQUEST) {}
|
||||
char type = CONNECTION_REQUEST;
|
||||
};
|
||||
|
||||
struct ConnectionAccepted {
|
||||
ConnectionAccepted() : type(CONNECTION_ACCEPTED) {}
|
||||
char type;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct ConnectionDenied {
|
||||
ConnectionDenied() : type(CONNECTION_DENIED) {}
|
||||
char type;
|
||||
};
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#include <SDL_net.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "Client.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::cout << "Starting DarkRP2D Client..." << std::endl;
|
||||
|
||||
if (SDLNet_Init() < 0)
|
||||
{
|
||||
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bool clientQuit = false;
|
||||
{
|
||||
Client client("127.0.0.1",12000);
|
||||
unsigned int lastTime = SDL_GetTicks(), currentTime, elapsedTime;
|
||||
while (!clientQuit)
|
||||
{
|
||||
currentTime = SDL_GetTicks();
|
||||
elapsedTime = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
client.update(elapsedTime);
|
||||
}
|
||||
}
|
||||
|
||||
SDLNet_Quit();
|
||||
std::cout << "Client closed!" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user