File ServerInterface.hpp
File List > Interfaces > NetWorth > server > ServerInterface.hpp
Go to the documentation of this file
#pragma once
#include "ServerManager.hpp"
#include <thread>
#include <sstream>
#include "Interfaces/NetWorth/NetworkInterface.hpp"
#include "Worlds/MazeWorld.hpp"
namespace netWorth
{
using namespace sf;
class ServerInterface : public NetworkingInterface
{
private:
ServerManager* m_manager = nullptr;
unsigned short m_world_update_port = 0;
protected:
public:
ServerInterface(size_t id, const std::string& name)
: cse491::InterfaceBase(id, name),
NetworkingInterface(id, name)
{
}
bool Initialize() override
{
// resolve port and IP from entity properties
m_ip = sf::IpAddress::resolve(NetworkingInterface::GetProperty<std::string>("client_ip"));
m_world_update_port = NetworkingInterface::GetProperty<unsigned short>("client_port");
m_manager = GetProperty<netWorth::ServerManager*>("server_manager");
Packet sendPkt, recvPkt;
std::string str;
bindSocket(m_socket, GetProperty<unsigned short>("server_port"));
// Await client
if (!receivePacket(recvPkt, m_ip, m_port))
return false;
std::cout << m_ip.value() << " has connected successfully." << std::endl;
// Acknowledge client
sendPkt << "Connection established.";
if (!sendPacket(sendPkt, m_ip.value(), m_port))
return false;
recvPkt.clear();
// await request for map
if (!receivePacket(recvPkt, m_ip, m_port))
return false;
GetWorld().SetWorldRunning(true);
return true;
}
static Packet gridToPacket(const cse491::WorldGrid& grid,
const cse491::type_options_t& typeOptions,
const cse491::item_map_t& itemMap,
const cse491::agent_map_t& agentMap)
{
std::vector<std::string> packetGrid(grid.GetHeight());
// Load the world into the symbol_grid;
for (size_t y = 0; y < grid.GetHeight(); ++y)
{
packetGrid[y].resize(grid.GetWidth());
for (size_t x = 0; x < grid.GetWidth(); ++x)
{
packetGrid[y][x] = typeOptions[grid.At(x, y)].symbol;
}
}
// Add in the agents / entities
for (const auto& [id, entityPtr] : itemMap)
{
cse491::GridPosition pos = entityPtr->GetPosition();
if(!std::isnan(pos.GetX()) && !std::isnan(pos.GetY())
&& pos.CellX() < grid.GetWidth() && pos.CellY() < grid.GetHeight()){
packetGrid[pos.CellY()][pos.CellX()] = '+';
}
}
for (const auto& [id, agent_ptr] : agentMap)
{
cse491::GridPosition pos = agent_ptr->GetPosition();
char c = '*';
if (agent_ptr->HasProperty("symbol"))
{
c = agent_ptr->GetProperty<char>("symbol");
}
if(!std::isnan(pos.GetX()) && !std::isnan(pos.GetY())
&& pos.CellX() < grid.GetWidth() && pos.CellY() < grid.GetHeight()){
packetGrid[pos.CellY()][pos.CellX()] = c;
}
}
// Print out the symbol_grid with a box around it.
std::ostringstream oss;
oss << '+' << std::string(grid.GetWidth(), '-') << "+\n";
for (const auto& row : packetGrid)
{
oss << "|";
for (char cell : row)
{
oss << cell;
}
oss << "|\n";
}
oss << '+' << std::string(grid.GetWidth(), '-') << "+\n";
std::string gridString = oss.str();
Packet gridPacket;
gridPacket << gridString;
return gridPacket;
}
size_t SelectAction(const cse491::WorldGrid& grid,
const cse491::type_options_t& typeOptions,
const cse491::item_map_t& itemMap,
const cse491::agent_map_t& agentMap) override
{
// send action map to client
sf::Packet sendPkt = m_manager->actionMapToPacket();
std::cout << "Sending action map to " << m_ip.value().toString() << " on port " << m_port << std::endl;
sendPacket(sendPkt, m_ip.value(), m_port);
// print server-side map (for test purposes)
sf::Packet mapPkt = gridToPacket(grid, typeOptions, itemMap, agentMap);
std::string map;
mapPkt >> map;
std::cout << map << std::endl;
// receive player input
sf::Packet recvPkt;
uint64_t actionID;
receivePacket(recvPkt, m_ip, m_port);
recvPkt >> actionID;
// handle leaving client
if (actionID == 9999)
{
m_manager->removeInterface(GetID());
m_manager->removeFromActionMap(GetID());
m_manager->removeFromUpdatePairs(m_ip.value(), m_world_update_port);
}
// return actionId
return actionID;
}
}; // End of class ServerInterface
// End of namespace netWorth
}