Skip to content

Commit

Permalink
Merge branch 'group_5' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
FergusonAJ committed Oct 19, 2023
2 parents 4508593 + 9e0e219 commit 7205928
Show file tree
Hide file tree
Showing 10 changed files with 687 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ if(${BUILD_MAIN})
PRIVATE ${CMAKE_SOURCE_DIR}/source
)
target_link_libraries(${EXE_NAME}
PRIVATE sfml-window sfml-audio sfml-graphics sfml-system
PRIVATE sfml-window sfml-audio sfml-graphics sfml-system sfml-network
)
if(EXISTS ${CMAKE_SOURCE_DIR}/source/${EXE_NAME}.cmake)
message(STATUS "Loading ${EXE_NAME}.cmake")
Expand Down
97 changes: 97 additions & 0 deletions source/Interfaces/NetWorth/NetworkInterface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* 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 <cassert>
#include <string>
#include <vector>
#include <array>
#include <SFML/Network/UdpSocket.hpp>
#include <SFML/Network/Packet.hpp>
#include "../../core/InterfaceBase.hpp"

namespace netWorth{

using namespace sf;
/**
* TODO: Delete or incorporate
*/
class NetworkingInterface {
private:

protected:
UdpSocket m_socket; ///The socket we are going to make our connection
std::optional<IpAddress> m_ip; /// the local address of the machine
unsigned short m_port; /// local port number of the machine
//Thought about making m_clients a shared pointer to a vector, but it'll be a vector for now
std::vector<std::string> m_clients; ///list of all the clients that will connect with the server

public:
NetworkingInterface() = default;
~NetworkingInterface() = default;

/**
* Receives a socket that has been connected between client and server
* @return the udp socket
*/
UdpSocket * GetSocket(){
return &m_socket;
}

/**
* Bind socket to port number
* @param socket Socket to be bound
* @param port Port number
* @return true if successful
*/
virtual bool BindSocket(UdpSocket &socket, unsigned short port) {
if (socket.bind(port) != Socket::Status::Done) {
std::cerr << "Failed to bind socket" << std::endl;
return false;
}
return true;
}

/**
* Sends a packet across the socket
* @param packet the packet we want to send
* @param destAddr the destination address we want to send to
* @param port the port of the connection
* @return true if successfully sent
*/
virtual bool SendPacket(Packet packet, IpAddress destAddr, const unsigned short port){
if (m_socket.send(packet, destAddr, port) != Socket::Status::Done) {
std::cerr << "Could not connect to" << destAddr << " at port " << port << std::endl;
return false;
}
return true;
}
/**
* Starts the connection by receiving the first packet
* @param sender IP of sending machine
* @param port port number of sending machine
* @return received packet
*/
virtual bool ReceivePacket(Packet & pkt, std::optional<IpAddress> &sender, unsigned short &port){
if (m_socket.receive(pkt, sender, port) != Socket::Status::Done) {
std::cerr << "Failed to receive" << std::endl;
return false;
}
return true;
}

/**
* Processes the packet and outputs it
* @param packet the packet we want to output
*/
virtual void ProcessPacket(Packet packet){
std::string actionInd;
packet >> actionInd;
std::cout << actionInd;
}
};
}//End of namespace networth
141 changes: 141 additions & 0 deletions source/Interfaces/NetWorth/client/ClientInterface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* 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 <cassert>
#include <string>
#include <vector>
#include <SFML/Network/UdpSocket.hpp>
#include <SFML/Network/Packet.hpp>
#include <memory>

#include "../NetworkInterface.hpp"
#include "../../TrashInterface.hpp"

namespace netWorth{
/**
* The interface of our client that will be interacting and connection with our server
*/
using namespace sf;

class ClientInterface : public NetworkingInterface {
private:
std::optional<IpAddress> m_dest_ip; /// the destination address (server address)
unsigned short m_dest_port; /// the destination port (server port)

/**
* Get user input to be sent to server
* @return string corresponding to action
*/
static std::string GameLoop_GetInput() {
bool valid_input = false;
std::string action;
char input;

while (!valid_input) {
std::cin >> input;
switch (input) {
case 'w': case 'W': action = "up"; valid_input = true; break;
case 'a': case 'A': action = "left"; valid_input = true; break;
case 's': case 'S': action = "down"; valid_input = true; break;
case 'd': case 'D': action = "right"; valid_input = true; break;
case 'q': case 'Q': action = "quit"; valid_input = true; break;
default: valid_input = false;
}
if (!valid_input) {
std::cout << "Your move?";
}
}

return action;
}

protected:

public:
/**
* ClientInterface constructor (NetworkingInterface superclass)
* @param ip_string String for destination IP address, make into IpAddress object
* @param port Destination port number
*/
ClientInterface(const std::string & ip_string,
unsigned short port) {
m_dest_ip = IpAddress::resolve(ip_string);
m_dest_port = port;
}

/**
* Default destructor
*/
~ClientInterface() = default;

/**
* Establish connection with server
* @return True if successful, false if error
*/
bool EstablishConnection() {
Packet send_pkt, recv_pkt;

// send request message
send_pkt << "New client requesting connection.";
if (!SendPacket(send_pkt, m_dest_ip.value(), m_dest_port)) return false;

// receive from server
if (!ReceivePacket(recv_pkt, m_dest_ip, m_dest_port)) return false;

// print received string (Connection established.)
std::string str;
recv_pkt >> str;
std::cout << str << std::endl;

return true;
}

/**
* Game loop
*/
void GameLoop() {
Packet send_pkt, recv_pkt;
std::string recv_str;

cse491::WorldGrid grid;
cse491::type_options_t type_options;
cse491::item_set_t item_set;
cse491::agent_set_t agent_set;
std::string action;

send_pkt << "Game started.";

// ask for map
if (!SendPacket(send_pkt, m_dest_ip.value(), m_dest_port)) return;

while (action != "quit") {
// receive map
if (!ReceivePacket(recv_pkt, m_dest_ip, m_dest_port)) return;

// print map
recv_pkt >> recv_str;
std::cout << std::endl << recv_str;

// get user input
action = GameLoop_GetInput();

// TODO: Unpack recv_pkt into world grid, agent list, etc
// We need to serialize these classes...
//recv_pkt >> grid >> type_options >> item_set >> agent_set;

//action = mTrash->SelectAction(grid, type_options, item_set, agent_set);

// send packet with action
send_pkt.clear();
send_pkt << action;

if (!SendPacket(send_pkt, m_dest_ip.value(), m_dest_port)) return;
}
}
}; //End of ClientInterface
}// End of namespace NetWorth
129 changes: 129 additions & 0 deletions source/Interfaces/NetWorth/server/ServerInterface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/**
* 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 <cassert>
#include <string>
#include <vector>
#include <sstream>
#include <SFML/Network/UdpSocket.hpp>
#include <SFML/Network/Packet.hpp>

#include "../NetworkInterface.hpp"
#include "networkingworld.hpp"

namespace netWorth{
using namespace sf;

class NetworkMazeWorld;

/**
* The server that will be running and that allows clients to connect to
*/
class ServerInterface : public NetworkingInterface {
private:

protected:

public:
ServerInterface() = default;
~ServerInterface() = default;

/**
* The initial connection for the server to a client
* @param sender address of the sender
* @param send_pkt the packet that the server will send initially
* @param recv_pkt the packet that the server will receive initially
* @param port port of the connection
* @param str string for the receive packet
* @return true if successful
*/
bool InitialConnection(std::optional<IpAddress> &sender, unsigned short &port){
Packet send_pkt, recv_pkt;
std::string str;

BindSocket(m_socket, 55002);

// Await client
if (!ReceivePacket(recv_pkt, sender, port)) return false;

recv_pkt >> str;
std::cout << str << std::endl;
std::cout << sender.value() << " has connected successfully." << std::endl;

// Acknowledge client
send_pkt << "Connection established.";
if (!SendPacket(send_pkt, sender.value(), port)) return false;

// await request for map
if (!ReceivePacket(recv_pkt, sender, port)) return false;

recv_pkt >> str;
std::cout << str << std::endl;

return true;
}

/**
* The grid that will be sent to the client from the server after the connection
* so the client can start asking to make moves
* @param grid the grid to send to the server
* @param type_options different cell types of the world
* @param item_set the items that may be apart of the grid
* @param agent_set the agents that may be apart of the grid
* @return the grid that will be sent to the client
*/
static Packet GridToPacket(const cse491::WorldGrid & grid, const cse491::type_options_t & type_options,
const cse491::item_set_t & item_set, const cse491::agent_set_t & agent_set)
{
std::vector<std::string> packet_grid(grid.GetHeight());

// Load the world into the symbol_grid;
for (size_t y=0; y < grid.GetHeight(); ++y) {
packet_grid[y].resize(grid.GetWidth());
for (size_t x=0; x < grid.GetWidth(); ++x) {
packet_grid[y][x] = type_options[ grid.At(x,y) ].symbol;
}
}

// Add in the agents / entities
for (const auto & entity_ptr : item_set) {
cse491::GridPosition pos = entity_ptr->GetPosition();
packet_grid[pos.CellY()][pos.CellX()] = '+';
}

for (const auto & agent_ptr : agent_set) {
cse491::GridPosition pos = agent_ptr->GetPosition();
char c = '*';
if(agent_ptr->HasProperty("symbol")){
c = agent_ptr->GetProperty<char>("symbol");
}
packet_grid[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 : packet_grid) {
oss << "|";
for (char cell : row) {
oss << cell;
}
oss << "|\n";
}
oss << '+' << std::string(grid.GetWidth(),'-') << "+\n";
oss << "\nYour move? ";
std::string gridString = oss.str();

Packet gridPacket;
gridPacket << gridString;

return gridPacket;
}

};//End of class ServerInterface
}//End of namespace netWorth
Loading

0 comments on commit 7205928

Please sign in to comment.