Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIG Serialization Update #102

Merged
merged 19 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super minor, but as we move to the final deadline, feel free to cut lines like this instead of commenting. Old versions are always available on GitHub anyway!
(I don't think we'd take points off for something like this, unless it's particularly egregious.)


// 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to update this, looks like it's the same as ClientInterface

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this and client interface both match NetworkingInterface. It's worth taking a pass to clean these up. I know keeping up with them is a pain, but it really does help orient folks who are new to the code.

* @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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm being nitpicky here, but it would be nice if ID was consistent between this and GetActionID.
I prefer ID over Id, but consistency is the important part.

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these aren't used elsewhere. I'm assuming they come into play in multiplayer? If so that's totally fine.


/**
* 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
Loading