Skip to content

Commit

Permalink
Merge pull request #102 from ZaneMODell/serial-experiments-lain
Browse files Browse the repository at this point in the history
BIG Serialization Update
  • Loading branch information
FergusonAJ authored Dec 5, 2023
2 parents d5abd3b + 448771e commit 0cc9410
Show file tree
Hide file tree
Showing 18 changed files with 848 additions and 38 deletions.
30 changes: 19 additions & 11 deletions source/Interfaces/NetWorth/client/ClientInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Interfaces/NetWorth/NetworkInterface.hpp"
#include "Interfaces/TrashInterface.hpp"
#include "Interfaces/MainInterface.hpp"
#include "ClientManager.hpp"

namespace netWorth{
/**
Expand All @@ -18,6 +19,7 @@ namespace netWorth{

class ClientInterface : public NetworkingInterface, i_2D::MainInterface {
private:
netWorth::ClientManager *m_manager = nullptr;

protected:

Expand All @@ -39,6 +41,8 @@ namespace netWorth{
// resolve port and IP from entity properties
m_ip = sf::IpAddress::resolve(NetworkingInterface::GetProperty<std::string>("ip"));
m_port = NetworkingInterface::GetProperty<unsigned short>("port");
m_manager = GetProperty<netWorth::ClientManager *>("manager");
m_manager->SetupSocket(&m_socket, m_ip, m_port);

Packet send_pkt, recv_pkt;
std::string str;
Expand Down Expand Up @@ -75,34 +79,38 @@ namespace netWorth{
const cse491::item_map_t & item_set,
const cse491::agent_map_t & agent_set) override
{
// Receive and draw map
sf::Packet send_pkt, recv_pkt;
std::string map;

ReceivePacket(recv_pkt, m_ip, m_port);
ProcessPacket(recv_pkt);
sf::Packet send_pkt;

// grab action ID from MainInterface
std::uint32_t action_id = i_2D::MainInterface::SelectAction(grid, type_options,
item_set, agent_set);
std::cout << action_id << std::endl;
//std::cout << action_id << std::endl;

// Send instruction to server
send_pkt << action_id;
SendPacket(send_pkt, m_ip.value(), m_port);

m_manager->ClearActionMap();

// Do the action!
return action_id;
}

/**
* Process packet from server (just print map for now)
* Process packet from server (just print agent action map for now)
* @param packet packet from server
*/
void ProcessPacket(Packet packet) override {
std::string str;
packet >> str;
std::cout << str;
size_t data_size, data;
packet >> data_size;
std::cout << data_size << " agents" << std::endl;
for (size_t i = 0; i < data_size; i++) {
packet >> data;
std::cout << "agent " << data;
packet >> data;
std::cout << " action " << data << std::endl;
}
std::cout << std::endl;
}

}; // End of ClientInterface
Expand Down
99 changes: 99 additions & 0 deletions source/Interfaces/NetWorth/client/ClientManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
* This file is part of the Fall 2023, CSE 491 course project.
* @brief A networking interface that allows information to be sent across a network
* @note Status: PROTOTYPE
**/

#pragma once
#include <map>
#include <sstream>
#include <vector>
#include "Interfaces/NetWorth/NetworkInterface.hpp"

namespace netWorth{
using namespace sf;

/**
* The server that will be running and that allows clients to connect to
*/
class ClientManager {
private:
sf::UdpSocket *m_socket; /// Socket shared with ClientInterface
std::optional<sf::IpAddress> m_ip; /// Server IP address
unsigned short m_port; /// Server port
std::unordered_map<size_t, size_t> m_action_map; ///Map of agent IDs to most recent action selected

protected:

public:
/**
* Default constructor (AgentBase)
* @param id agent ID
* @param name agent name
*/
ClientManager()= default;

/**
* Turn packet from server into action map for ControlledAgents
* @param pkt received packet
*/
void PacketToActionMap(sf::Packet pkt) {
size_t data_size, agent_id, action_id;
pkt >> data_size;
for (size_t i = 0; i < data_size; i++) {
pkt >> agent_id >> action_id;
m_action_map[agent_id] = action_id;
}
}

/**
* Set receiving socket for action map and IP/port info
* @param socket pointer to ClientInterface's socket
* @param ip server IP
* @param port server port
*/
void SetupSocket(sf::UdpSocket *socket, std::optional<sf::IpAddress> ip, unsigned short port) {
m_socket = socket;
m_ip = ip;
m_port = port;
}

/**
* Wait until server sends action map
*/
void RequestActionMap() {
sf::Packet recv_pkt;
if (m_socket->receive(recv_pkt, m_ip, m_port) != sf::Socket::Status::Done) {
std::cerr << "Failed to receive" << std::endl;
return;
}
PacketToActionMap(recv_pkt);
}

/**
* Check if Agent ID is present in agent action map
* @param id Agent ID
* @return true if ID is present
*/
bool IdPresent(size_t id) {
return m_action_map.find(id) == m_action_map.end();
}

/**
* Return action ID correspoding to agent ID
* @param id Agent ID
* @return action ID
*/
size_t GetActionID(size_t id) {
return m_action_map[id];
}

/**
* Clear action map after ClientInterface moves
*/
void ClearActionMap() {
m_action_map.clear();
}

}; // End of class ClientManager
} // End of namespace netWorth
48 changes: 48 additions & 0 deletions source/Interfaces/NetWorth/client/ControlledAgent.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* This file is part of the Fall 2023, CSE 491 course project.
* @brief An Agent that will walk back and forth along a row or column.
* @note Status: PROPOSAL
**/

#pragma once

#include <cassert>

#include "../../../core/AgentBase.hpp"
#include "ClientManager.hpp"

namespace netWorth {

class ControlledAgent : public cse491::AgentBase {
private:
ClientManager *m_manager = nullptr; /// Client manager to access agent action map

protected:

public:
ControlledAgent(size_t id, const std::string & name) : AgentBase(id, name) { }
~ControlledAgent() = default;

/// @brief This agent needs a specific set of actions to function.
/// @return Success.
bool Initialize() override {
m_manager = GetProperty<ClientManager *>("manager");
return HasAction("up") && HasAction("down") && HasAction("left") && HasAction("right");
}

/// Choose the action to take a step in the appropriate direction.
size_t SelectAction(const cse491::WorldGrid & /* grid*/,
const cse491::type_options_t & /* type_options*/,
const cse491::item_map_t & /* item_map*/,
const cse491::agent_map_t & /* agent_map*/) override
{
if (m_manager->IdPresent(id)) {
// wait for server to complete agent movements
m_manager->RequestActionMap();
}
return m_manager->GetActionID(id);
}

};

} // End of namespace cse491
17 changes: 12 additions & 5 deletions source/Interfaces/NetWorth/server/ServerInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include "ServerManager.hpp"
#include "Interfaces/NetWorth/NetworkInterface.hpp"
#include <string>
#include <sstream>
Expand All @@ -18,6 +19,7 @@ namespace netWorth{
*/
class ServerInterface : public NetworkingInterface {
private:
ServerManager *m_manager = nullptr;

protected:

Expand All @@ -33,6 +35,10 @@ namespace netWorth{
InitialConnection(m_ip, m_port);
}

bool Initialize() override {
m_manager = GetProperty<ServerManager *>("server_manager");
return true;
}

/**
* The initial connection for the server to a client
Expand Down Expand Up @@ -139,21 +145,22 @@ namespace netWorth{
const cse491::item_map_t & item_set,
const cse491::agent_map_t & agent_set) override
{
// send map to client
sf::Packet send_pkt = GridToPacket(grid, type_options, item_set, agent_set);
// send action map to client
sf::Packet send_pkt = m_manager->ActionMapToPacket();
SendPacket(send_pkt, m_ip.value(), m_port);

// print map (for test purposes)
// print server-side map (for test purposes)
sf::Packet map_pkt = GridToPacket(grid, type_options, item_set, agent_set);
std::string map;
send_pkt >> map;
map_pkt >> map;
std::cout << map << std::endl;

// receive player input
sf::Packet recv_pkt;
std::uint32_t action_id;

ReceivePacket(recv_pkt, m_ip, m_port);
ProcessPacket(recv_pkt);
//ProcessPacket(recv_pkt);
recv_pkt >> action_id;

// TODO: Figure out how to quit (client-side exit(0) in MainInterface upon q/esc)
Expand Down
59 changes: 59 additions & 0 deletions source/Interfaces/NetWorth/server/ServerManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* This file is part of the Fall 2023, CSE 491 course project.
* @brief A networking interface that allows information to be sent across a network
* @note Status: PROTOTYPE
**/

#pragma once
#include <map>
#include <sstream>
#include <vector>
#include "SFML/Network/Packet.hpp"

namespace netWorth{
/**
* The server that will be running and that allows clients to connect to
*/
class ServerManager {
private:
std::unordered_map<size_t, size_t> m_action_map; ///Map of agent IDs to most recent action selected

protected:

public:
const static constexpr unsigned short m_initConnectionPort = 55000; ///Port for initial client connection

unsigned short m_maxClientPort = 55000; ///Port that is incremented for client thread handoff

/**
* Default constructor (AgentBase)
* @param id agent ID
* @param name agent name
*/
ServerManager() = default;

/**
* Report action from agent to manager
* @param entity_id ID of reorting entity
* @param action_id action ID
*/
void TellAction(size_t entity_id, size_t action_id) {
m_action_map[entity_id] = action_id;
}

/**
* Convert action map to packet to send to client
* @return packet containing action map as series of integers
*/
sf::Packet ActionMapToPacket() {
sf::Packet pkt;
pkt << m_action_map.size();
for (auto pair : m_action_map) {
pkt << pair.first << pair.second;
}
//std::cout << m_action_map.size();
return pkt;
}

}; // End of class ServerManager
} // End of namespace netWorth
1 change: 1 addition & 0 deletions source/Worlds/GenerativeWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class GenerativeWorld : public WorldBase {

main_grid.Read("../assets/grids/generated_maze.grid", type_options);
}

~GenerativeWorld() = default;

/// Allow the agents to move around the maze.
Expand Down
1 change: 1 addition & 0 deletions source/Worlds/ManualWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ namespace cse491_team8 {
portal_id_d = AddCellType("portal_d", "Portal that teleports player to another d-portal spot.", ')');
main_grid.Read("../assets/grids/team8_grid_large.grid", type_options);
}

~ManualWorld() = default;

/// @brief Generates move sets for all the agents
Expand Down
1 change: 1 addition & 0 deletions source/Worlds/MazeWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class MazeWorld : public WorldBase {
// Load map
main_grid.Read("../assets/grids/default_maze.grid", type_options);
}

~MazeWorld() = default;

/// Allow the agents to move around the maze.
Expand Down
9 changes: 9 additions & 0 deletions source/core/AgentBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ namespace cse491 {
virtual void Notify(const std::string & /*message*/,
const std::string & /*msg_type*/="none") { }

/**
* Serialize agent (assume no properties)
* @param os ostream
*/
void Serialize(std::ostream &os) override {
os << name << '\n';
os << position.GetX() << '\n';
os << position.GetY() << '\n';
}

// virtual void Serialize(std::ostream & os) {};
//
Expand Down
6 changes: 6 additions & 0 deletions source/core/Data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,10 @@ namespace cse491 {
/// @brief Maps of agent IDs to agent pointers
using agent_map_t = std::map<size_t, std::unique_ptr<AgentBase>>;

/// @brief Common types of properties in network serialization
enum class PropertyType {t_double, t_int, t_char, t_string, t_other};

/// @brief Enum for World types in network serialization
enum class WorldType {w_maze, w_second, w_generative, w_manual};

}
Loading

0 comments on commit 0cc9410

Please sign in to comment.