mirror of
https://github.com/BreizhHardware/bloubloulespoissons.git
synced 2026-03-19 06:00:36 +01:00
233 lines
8.7 KiB
C++
233 lines
8.7 KiB
C++
//
|
|
// Created by BreizhHardware on 04/12/2024.
|
|
//
|
|
|
|
#include "networking.h"
|
|
std::unordered_map<int, std::pair<int, int>> playerPositions;
|
|
std::unordered_map<int, std::chrono::time_point<std::chrono::steady_clock>> lastKeepAlive;
|
|
|
|
bool initServer() {
|
|
std::cout << "Initializing server..." << std::endl;
|
|
if (SDLNet_ResolveHost(&ip, NULL, 1234) == -1) {
|
|
std::cerr << "SDLNet_ResolveHost: " << SDLNet_GetError() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
server = SDLNet_TCP_Open(&ip);
|
|
if (!server) {
|
|
std::cerr << "SDLNet_TCP_Open: " << SDLNet_GetError() << std::endl;
|
|
return false;
|
|
}
|
|
std::cout << "Server initialized!" << std::endl;
|
|
return true;
|
|
}
|
|
|
|
void acceptClients() {
|
|
while (game_running) {
|
|
TCPsocket clientSocket = SDLNet_TCP_Accept(server);
|
|
if (clientSocket) {
|
|
clients.push_back(clientSocket);
|
|
int clientId = clients.size() - 1;
|
|
createNewPlayer(clientId);
|
|
updateKeepAlive(clientId);
|
|
Shark shark(0, 0, 0.1, 0.1,0, 150, 150, renderer,players_server);
|
|
shark.updatePosition(0, 0);
|
|
std::thread clientThread([clientSocket, clientId, &shark]() {
|
|
std::thread keepAliveThread(sendKeepAlive, clientSocket);
|
|
keepAliveThread.detach();
|
|
while (running) {
|
|
std::string message = receiveMessage(clientSocket);
|
|
if (!message.empty()) {
|
|
message = processReceivedData(message);
|
|
std::cout << "Server received: " << message << std::endl;
|
|
if (message == "keepalive") {
|
|
updateKeepAlive(clientId);
|
|
} else if (message.find(";move;") != std::string::npos) {
|
|
char direction[20];
|
|
sscanf(message.c_str(), "%d;move;%s", &clientId, &direction);
|
|
|
|
int newX = 0, newY = 0;
|
|
std::tie(newX, newY) = updatePlayerPosition(clientId, direction);
|
|
// Mettre à jour la position du joueur
|
|
players_server[clientId].updatePosition(newX, newY);
|
|
std::string updatedMessage = std::to_string(clientId) + ";moved;" + std::to_string(newX) + "," + std::to_string(newY);
|
|
for (TCPsocket client : clients) {
|
|
sendMessage(client, updatedMessage);
|
|
}
|
|
} else if (message.find(";shark_moved;") != std::string::npos) {
|
|
int sharkId, x, y;
|
|
sscanf(message.c_str(), "%d;shark_moved;%d,%d", &sharkId, &x, &y);
|
|
shark.updatePosition(x, y);
|
|
std::string updatedMessage = std::to_string(sharkId) + ";shark_moved;" + std::to_string(x) + "," + std::to_string(y);
|
|
for (TCPsocket client : clients) {
|
|
sendMessage(client, updatedMessage);
|
|
}
|
|
}
|
|
}
|
|
SDL_Delay(1);
|
|
}
|
|
lastKeepAlive.erase(clientId);
|
|
SDLNet_TCP_Close(clientSocket);
|
|
});
|
|
clientThread.detach();
|
|
}
|
|
SDL_Delay(100);
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> split(const std::string& str, char delimiter) {
|
|
std::vector<std::string> result;
|
|
std::string temp;
|
|
for (char ch : str) {
|
|
if (ch == delimiter) {
|
|
if (!temp.empty()) { // On évite d'ajouter des chaînes vides si nécessaire
|
|
result.push_back(temp);
|
|
}
|
|
temp.clear(); // Réinitialise pour le prochain segment
|
|
} else {
|
|
temp += ch;
|
|
}
|
|
}
|
|
if (!temp.empty()) { // Ajouter le dernier segment s'il existe
|
|
result.push_back(temp);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::pair<int, int> updatePlayerPosition(int clientId, const std::string& direction) {
|
|
std::cout << "Updating player position for client " << clientId << " Direction: "<< direction << std::endl;
|
|
auto& pos = playerPositions[clientId];
|
|
int& newX = pos.first;
|
|
int& newY = pos.second;
|
|
int speed = 5;
|
|
|
|
std::vector<std::string> directions = split(direction, '-');
|
|
|
|
if(directions.size() > 1 ){
|
|
speed = 3;
|
|
}
|
|
|
|
for(const std::string dist : directions){
|
|
if (dist == "up") {
|
|
if (newY-speed < 0) {
|
|
newY = 0;
|
|
} else {
|
|
newY -= speed;
|
|
}
|
|
} else if (dist == "down") {
|
|
if (newY+speed > ENV_HEIGHT - windowHeight) {
|
|
newY = ENV_HEIGHT - windowHeight;
|
|
} else {
|
|
newY += speed;
|
|
}
|
|
} else if (dist == "left") {
|
|
if (newX-speed < 0) {
|
|
newX = 0;
|
|
} else {
|
|
newX -= speed;
|
|
}
|
|
} else if (dist == "right") {
|
|
if (newX+speed > ENV_WIDTH - windowWidth) {
|
|
newX = ENV_WIDTH - windowWidth;
|
|
} else {
|
|
newX += speed;
|
|
}
|
|
}
|
|
}
|
|
|
|
return {newX, newY};
|
|
}
|
|
|
|
void createNewPlayer(int clientId) {
|
|
if (clientId < 0) {
|
|
std::cerr << "Invalid client ID: " << clientId << std::endl;
|
|
return;
|
|
}
|
|
// Create a new player at a default position (e.g., 0, 0)
|
|
Player newPlayer(0, 0, 5, renderer, clientId);
|
|
players_server.push_back(newPlayer);
|
|
playerPositions[clientId] = {0, 0}; // Initialize player position
|
|
|
|
// Send the list of existing players to the new client
|
|
std::string playerListMessage = "playerList;";
|
|
for (auto& player : players_server) {
|
|
auto [x, y] = player.getPlayerPos();
|
|
playerListMessage += std::to_string(player.getPlayerId()) + "," + std::to_string(x) + "," + std::to_string(y) + ";";
|
|
}
|
|
sendMessage(clients[clientId], playerListMessage);
|
|
|
|
// Broadcast the new player to all clients
|
|
std::string newPlayerMessage = "newPlayer;" + std::to_string(clientId) + ",0,0;";
|
|
for (TCPsocket client : clients) {
|
|
sendMessage(client, newPlayerMessage);
|
|
}
|
|
}
|
|
|
|
void updateKeepAlive(int clientId) {
|
|
lastKeepAlive[clientId] = std::chrono::steady_clock::now();
|
|
}
|
|
|
|
void checkClientAlive() {
|
|
auto now = std::chrono::steady_clock::now();
|
|
for (auto it = lastKeepAlive.begin(); it != lastKeepAlive.end();) {
|
|
if (std::chrono::duration_cast<std::chrono::seconds>(now - it->second).count() > 5) {
|
|
std::cerr << "Client " << it->first << " is not responding. Removing..." << std::endl;
|
|
SDLNet_TCP_Close(clients[it->first]);
|
|
clients.erase(clients.begin() + it->first);
|
|
playerPositions.erase(it->first); // Supprimer la position du joueur
|
|
it = lastKeepAlive.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
void closeServer() {
|
|
std::string quitMessage = "host;quit";
|
|
for (TCPsocket client : clients) {
|
|
sendMessage(client, quitMessage);
|
|
}
|
|
// Fermer les sockets et nettoyer les ressources
|
|
for (TCPsocket client : clients) {
|
|
SDLNet_TCP_Close(client);
|
|
}
|
|
clients.clear();
|
|
SDLNet_TCP_Close(server);
|
|
}
|
|
|
|
void handleServerMessages() {
|
|
std::string message = receiveMessage(server);
|
|
if (!message.empty()) {
|
|
std::cout << "Server received: " << message << std::endl;
|
|
if (message.find(";moved;") != std::string::npos) {
|
|
int clientId, x, y;
|
|
sscanf(message.c_str(), "%d;moved;%d,%d", &clientId, &x, &y);
|
|
// Mettre à jour la position du joueur dans players_server
|
|
for (auto& player : players_server) {
|
|
std::cout << "Player ID: " << player.getPlayerId() << std::endl;
|
|
std::cout << "Client ID: " << clientId << std::endl;
|
|
std::cout << "PlayerId == ClientId: " << (player.getPlayerId() == clientId) << std::endl;
|
|
if (player.getPlayerId() == clientId) {
|
|
player.updatePosition(x, y);
|
|
std::cout << "Player " << clientId << " moved to " << player.getUnifiedX() << ", " << player.getUnifiedY() << std::endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void sendSharkPosition(TCPsocket socket, int sharkId, int x, int y) {
|
|
std::string message = std::to_string(sharkId) + ";shark_moved;" + std::to_string(x) + "," + std::to_string(y);
|
|
sendMessage(socket, message);
|
|
}
|
|
|
|
std::string processReceivedData(const std::string& data) {
|
|
std::string filteredData;
|
|
for (char c : data) {
|
|
if (std::isalnum(c) || c == ';' || c == '-' || c == '_' || std::isalpha(c)) {
|
|
filteredData += c;
|
|
}
|
|
}
|
|
return filteredData;
|
|
} |