diff --git a/client/in_world.cpp b/client/in_world.cpp index c9429b7..8e6fb5e 100644 --- a/client/in_world.cpp +++ b/client/in_world.cpp @@ -12,6 +12,7 @@ InWorld::InWorld() { #ifdef DEBUG cout << "entering InWorld" << endl; #endif + cout << "Client Index: " << infoMgr->GetClientIndex() << endl; } InWorld::~InWorld() { @@ -29,7 +30,7 @@ void InWorld::FrameStart() { } void InWorld::Update(double delta) { - // + while(HandlePacket(popNetworkPacket())); } void InWorld::FrameEnd() { @@ -44,6 +45,12 @@ void InWorld::Render(SDL_Surface* const screen) { //Event handlers //------------------------- +void InWorld::QuitEvent() { + //ensure that the client is disconnected properly + ExitGame(); + SetNextScene(SceneList::QUIT); +} + void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) { // } @@ -59,7 +66,7 @@ void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) { void InWorld::KeyDown(SDL_KeyboardEvent const& key) { switch(key.keysym.sym) { case SDLK_ESCAPE: - QuitEvent(); + ExitGame(); break; } } @@ -67,3 +74,79 @@ void InWorld::KeyDown(SDL_KeyboardEvent const& key) { void InWorld::KeyUp(SDL_KeyboardEvent const& key) { // } + +//------------------------- +//Utilities +//------------------------- + +int InWorld::HandlePacket(Packet p) { + switch(p.meta.type) { + case PacketType::NONE: + //DO NOTHING + return 0; + break; + case PacketType::PING: + //quick pong + p.meta.type = PacketType::PONG; + netUtil->Send(&p.meta.address, &p, sizeof(Packet)); + break; + case PacketType::PONG: + // + break; +// case PacketType::BROADCAST_REQUEST: +// // +// break; +// case PacketType::BROADCAST_RESPONSE: +// // +// break; +// case PacketType::JOIN_REQUEST: +// // +// break; +// case PacketType::JOIN_RESPONSE: +// // +// break; + case PacketType::DISCONNECT: + HandleDisconnection(p.disconnect); + break; +// case PacketType::SYNCHRONIZE: +// // +// break; +// case PacketType::PLAYER_NEW: +// // +// break; +// case PacketType::PLAYER_DELETE: +// // +// break; +// case PacketType::PLAYER_MOVE: +// // +// break; + default: + throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type)))); + } + return 1; +} + +void InWorld::Disconnect() { + //disconnect + Packet p; + p.meta.type = PacketType::DISCONNECT; + p.disconnect.clientIndex = infoMgr->GetClientIndex(); + netUtil->Send(GAME_CHANNEL, reinterpret_cast(&p), sizeof(Packet)); + netUtil->Unbind(GAME_CHANNEL); + endQueueThread(); + + //reset the client + infoMgr->ResetClientIndex(); +} + +void InWorld::ExitGame() { + Disconnect(); + SetNextScene(SceneList::MAINMENU); + cout << "The game session has ended" << endl; +} + +void InWorld::HandleDisconnection(::Disconnect& disconnect) { + Disconnect(); + SetNextScene(SceneList::MAINMENU); + cout << "You have been disconnected" << endl; +} diff --git a/client/in_world.hpp b/client/in_world.hpp index 05f930c..5cee9af 100644 --- a/client/in_world.hpp +++ b/client/in_world.hpp @@ -2,26 +2,53 @@ #define INWORLD_HPP_ #include "base_scene.hpp" +#include "defines.hpp" +#include "service_locator.hpp" +#include "packet_type.hpp" +#include "network_queue.hpp" +#include "information_manager.hpp" + +#include "config_utility.hpp" +#include "surface_manager.hpp" +#include "udp_network_utility.hpp" +#include "button.hpp" +#include "raster_font.hpp" class InWorld : public BaseScene { public: - /* Public access members */ + //Public access members InWorld(); ~InWorld(); protected: - /* Frame loop */ + //Frame loop void FrameStart(); void Update(double delta); void FrameEnd(); void Render(SDL_Surface* const); - /* Event handlers */ + //Event handlers + void QuitEvent(); void MouseMotion(SDL_MouseMotionEvent const&); void MouseButtonDown(SDL_MouseButtonEvent const&); void MouseButtonUp(SDL_MouseButtonEvent const&); void KeyDown(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&); + + //Utilities + int HandlePacket(Packet p); + void Disconnect(); + void ExitGame(); + void HandleDisconnection(::Disconnect&); + + //services + ConfigUtility* configUtil = ServiceLocator::Get(); + SurfaceManager* surfaceMgr = ServiceLocator::Get(); + UDPNetworkUtility* netUtil = ServiceLocator::Get(); + InformationManager* infoMgr = ServiceLocator::Get(); + + //members + //... }; #endif diff --git a/client/information_manager.hpp b/client/information_manager.hpp index 6d48546..967b6a8 100644 --- a/client/information_manager.hpp +++ b/client/information_manager.hpp @@ -5,6 +5,7 @@ class InformationManager { public: int SetClientIndex(int i) { return clientIndex = i; } int GetClientIndex() { return clientIndex; } + void ResetClientIndex() { clientIndex = -1; } private: int clientIndex = -1; }; diff --git a/client/lobby.cpp b/client/lobby.cpp index 5990e28..fcd3a52 100644 --- a/client/lobby.cpp +++ b/client/lobby.cpp @@ -26,12 +26,12 @@ Lobby::Lobby() { serverList.push_back({"bar",{0,0}}); serverList.push_back({"foobar",{0,0}}); - BeginQueueThread(); + flushNetworkQueue(); + beginQueueThread(); BroadcastNetwork(); } Lobby::~Lobby() { - EndQueueThread(); #ifdef DEBUG cout << "leaving Lobby" << endl; #endif @@ -46,13 +46,7 @@ void Lobby::FrameStart() { } void Lobby::Update(double delta) { - try { - //process all packets on the network queue - while(HandlePacket(popNetworkPacket())); - } - catch(exception& e) { - cerr << "Network Error: " << e.what() << endl; - } + while(HandlePacket(popNetworkPacket())); } void Lobby::FrameEnd() { @@ -102,6 +96,7 @@ void Lobby::MouseButtonUp(SDL_MouseButtonEvent const& button) { } else if (backButton.MouseButtonUp(button) == Button::State::HOVER) { SetNextScene(SceneList::MAINMENU); + endQueueThread(); } else if ( //clicked within bounds TODO: make the damn collision system @@ -178,7 +173,7 @@ int Lobby::HandlePacket(Packet p) { // // // break; default: - throw(runtime_error("Failed to recognize the packet type")); + throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type)))); } return 1; } diff --git a/client/lobby.hpp b/client/lobby.hpp index 1fe27f6..6eea9b7 100644 --- a/client/lobby.hpp +++ b/client/lobby.hpp @@ -1,8 +1,8 @@ #ifndef LOBBY_HPP_ #define LOBBY_HPP_ -#include "defines.hpp" #include "base_scene.hpp" +#include "defines.hpp" #include "service_locator.hpp" #include "packet_type.hpp" #include "network_queue.hpp" @@ -14,8 +14,6 @@ #include "button.hpp" #include "raster_font.hpp" -#include "SDL/SDL_thread.h" - #include #include diff --git a/client/splash_screen.hpp b/client/splash_screen.hpp index 0fdd562..f0fa3ed 100644 --- a/client/splash_screen.hpp +++ b/client/splash_screen.hpp @@ -2,8 +2,8 @@ #define SPLASHSCREEN_HPP_ #include "base_scene.hpp" -#include "service_locator.hpp" #include "defines.hpp" +#include "service_locator.hpp" #include "config_utility.hpp" #include "surface_manager.hpp" diff --git a/libs/common/defines.cpp b/libs/common/defines.cpp new file mode 100644 index 0000000..f045d74 --- /dev/null +++ b/libs/common/defines.cpp @@ -0,0 +1,9 @@ +#include "defines.hpp" + +#include + +std::string itos(int i) { + char buffer[20]; + snprintf(buffer, 20, "%d", i); + return std::string(buffer); +} \ No newline at end of file diff --git a/libs/common/defines.hpp b/libs/common/defines.hpp index 3765ced..d803dd9 100644 --- a/libs/common/defines.hpp +++ b/libs/common/defines.hpp @@ -2,10 +2,13 @@ #define DEFINES_HPP #include +#include #define GAME_CHANNEL 0 #define CHAT_CHANNEL 1 typedef std::chrono::high_resolution_clock Clock; +std::string itos(int i); + #endif diff --git a/libs/common/network_queue.cpp b/libs/common/network_queue.cpp index 774d3ba..caf1603 100644 --- a/libs/common/network_queue.cpp +++ b/libs/common/network_queue.cpp @@ -31,7 +31,7 @@ static int networkQueue(void*) { return 0; } -void BeginQueueThread() { +void beginQueueThread() { if (running) { return; } @@ -41,7 +41,7 @@ void BeginQueueThread() { } } -void EndQueueThread() { +void endQueueThread() { if (!running) { return; } @@ -50,7 +50,7 @@ void EndQueueThread() { queueThread = nullptr; } -void KillQueueThread() { +void killQueueThread() { if (!running) { return; } @@ -78,4 +78,12 @@ Packet popNetworkPacket() { } SDL_SemPost(lock); return p; +} + +void flushNetworkQueue() { + UDPNetworkUtility* netUtil = ServiceLocator::Get(); + SDL_SemWait(lock); + while(netUtil->Receive()); + queue.clear(); + SDL_SemPost(lock); } \ No newline at end of file diff --git a/libs/common/network_queue.hpp b/libs/common/network_queue.hpp index 30f6582..0abd517 100644 --- a/libs/common/network_queue.hpp +++ b/libs/common/network_queue.hpp @@ -3,10 +3,11 @@ #include "packet_type.hpp" -void BeginQueueThread(); -void EndQueueThread(); -void KillQueueThread(); +void beginQueueThread(); +void endQueueThread(); +void killQueueThread(); Packet peekNetworkPacket(); Packet popNetworkPacket(); +void flushNetworkQueue(); #endif diff --git a/libs/common/packet_type.hpp b/libs/common/packet_type.hpp index bd62515..ff11d5a 100644 --- a/libs/common/packet_type.hpp +++ b/libs/common/packet_type.hpp @@ -62,6 +62,7 @@ struct JoinResponse { struct Disconnect { Metadata meta; + int clientIndex; }; struct Synchronize { diff --git a/server/server_application.cpp b/server/server_application.cpp index 7fdf66c..326e80b 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -56,7 +56,7 @@ void ServerApplication::Init() { netUtil->Open(configUtil->Int("server.port"), sizeof(Packet)); //create the threads - BeginQueueThread(); + beginQueueThread(); //output the server information cout << configUtil->String("server.name") << endl; @@ -84,7 +84,7 @@ void ServerApplication::Proc() { void ServerApplication::Quit() { //close the threads - EndQueueThread(); + endQueueThread(); //clean up the services netUtil->Close(); @@ -126,7 +126,7 @@ int ServerApplication::HandlePacket(Packet p) { // break; case PacketType::BROADCAST_REQUEST: - Broadcast(p.broadcastRequest); + HandleBroadcast(p.broadcastRequest); break; // case PacketType::BROADCAST_RESPONSE: // // @@ -137,9 +137,9 @@ int ServerApplication::HandlePacket(Packet p) { // case PacketType::JOIN_RESPONSE: // // // break; -// case PacketType::DISCONNECT: -// // -// break; + case PacketType::DISCONNECT: + HandleDisconnection(p.disconnect); + break; // case PacketType::SYNCHRONIZE: // // // break; @@ -153,12 +153,12 @@ int ServerApplication::HandlePacket(Packet p) { // // // break; default: - throw(runtime_error("Failed to recognize the packet type")); + throw(runtime_error("Failed to recognize the packet type: " + itos(int(p.meta.type)))); } return 1; } -void ServerApplication::Broadcast(BroadcastRequest& bcast) { +void ServerApplication::HandleBroadcast(BroadcastRequest& bcast) { //respond to a broadcast request with the server's data Packet p; p.meta.type = PacketType::BROADCAST_RESPONSE; @@ -189,6 +189,19 @@ void ServerApplication::HandleConnection(JoinRequest& request) { netUtil->Send(client.channel, &p, sizeof(Packet)); //pretty - cout << "New connection" << endl; + cout << "New connection: index " << client.index << endl; + cout << "number of clients: " << clients.size() << endl; +} + +void ServerApplication::HandleDisconnection(Disconnect& disconnect) { + //disconnect a client (redundant message) + netUtil->Send(clients[disconnect.clientIndex].channel, &disconnect, sizeof(Packet)); + netUtil->Unbind(clients[disconnect.clientIndex].channel); + clients.erase(disconnect.clientIndex); + + //remove the player... + + //pretty + cout << "Lost connection: index " << disconnect.clientIndex << endl; cout << "number of clients: " << clients.size() << endl; } \ No newline at end of file diff --git a/server/server_application.hpp b/server/server_application.hpp index 3b1056f..bbde866 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -50,8 +50,9 @@ private: //network loop int HandlePacket(Packet p); - void Broadcast(BroadcastRequest&); + void HandleBroadcast(BroadcastRequest&); void HandleConnection(JoinRequest&); + void HandleDisconnection(Disconnect&); //services ConfigUtility* configUtil = nullptr; diff --git a/test/main.cpp b/test/main.cpp index 24d0efa..b858b9d 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,11 +1,7 @@ -#include "packet_type.hpp" +#include "defines.hpp" -#include - -using namespace std; int main(int, char**) { - Packet p; - cout << int(p.meta.type) << endl; + std::string s = itos(5); return 0; } \ No newline at end of file