From 6ccc874583fb61f14545c46a56a2bf10c883a082 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Sat, 23 Nov 2013 17:53:36 +1100 Subject: [PATCH] Implemented the log on and log off systems This is a pretty straight forward port of the old version, including the incredibly hacky server list. But I just need to remember that this is a prototype. --- client/channels.hpp | 8 +++ client/client_application.cpp | 4 +- client/client_application.hpp | 1 + client/in_world.cpp | 85 ++++++++++++++++++++++++++++--- client/in_world.hpp | 22 +++++++- client/lobby_menu.cpp | 50 +++++++++++++++--- client/lobby_menu.hpp | 13 +++-- common/network/network_packet.hpp | 9 ++++ server/main.cpp | 43 +--------------- server/server_application.cpp | 42 +++++++++++++-- server/server_application.hpp | 11 ++++ 11 files changed, 220 insertions(+), 68 deletions(-) create mode 100644 client/channels.hpp diff --git a/client/channels.hpp b/client/channels.hpp new file mode 100644 index 0000000..92695cd --- /dev/null +++ b/client/channels.hpp @@ -0,0 +1,8 @@ +#ifndef CHANNELS_HPP_ +#define CHANNELS_HPP_ + +enum Channels { + SERVER = 0 +}; + +#endif diff --git a/client/client_application.cpp b/client/client_application.cpp index 5c76c7e..faac031 100644 --- a/client/client_application.cpp +++ b/client/client_application.cpp @@ -135,10 +135,10 @@ void ClientApplication::LoadScene(SceneList sceneIndex) { activeScene = new OptionsMenu(&config); break; case SceneList::LOBBYMENU: - activeScene = new LobbyMenu(&config, &network); + activeScene = new LobbyMenu(&config, &network, &clientIndex); break; case SceneList::INWORLD: - activeScene = new InWorld(); + activeScene = new InWorld(&config, &network, &clientIndex); break; case SceneList::INCOMBAT: activeScene = new InCombat(); diff --git a/client/client_application.hpp b/client/client_application.hpp index bf8af4b..d35a85a 100644 --- a/client/client_application.hpp +++ b/client/client_application.hpp @@ -51,6 +51,7 @@ private: ConfigUtility config; UDPNetworkUtility network; + int clientIndex = -1; //replace with a struct? }; #endif diff --git a/client/in_world.cpp b/client/in_world.cpp index 38a4a32..fdbea22 100644 --- a/client/in_world.cpp +++ b/client/in_world.cpp @@ -21,12 +21,39 @@ */ #include "in_world.hpp" +#include "channels.hpp" + +#include + //------------------------- //Public access members //------------------------- -InWorld::InWorld() { - // +InWorld::InWorld(ConfigUtility* const arg1, UDPNetworkUtility* const arg2, int* const arg3): + config(*arg1), + network(*arg2), + clientIndex(*arg3) +{ + //setup the utility objects + image.LoadSurface(config["dir.interface"] + "button_menu.bmp"); + image.SetClipH(image.GetClipH()/3); + font.LoadSurface(config["dir.fonts"] + "pk_white_8.bmp"); + + //pass the utility objects + disconnectButton.SetImage(&image); + disconnectButton.SetFont(&font); + shutDownButton.SetImage(&image); + shutDownButton.SetFont(&font); + + //set the button positions + disconnectButton.SetX(50); + disconnectButton.SetY(50 + image.GetClipH() * 0); + shutDownButton.SetX(50); + shutDownButton.SetY(50 + image.GetClipH() * 1); + + //set the button texts + disconnectButton.SetText("Disconnect"); + shutDownButton.SetText("Shut Down"); } InWorld::~InWorld() { @@ -42,7 +69,13 @@ void InWorld::FrameStart() { } void InWorld::Update(double delta) { - // + //suck in all waiting packets + NetworkPacket packet; + while(network.Receive()) { + memcpy(&packet, network.GetInData(), sizeof(NetworkPacket)); + packet.meta.srcAddress = network.GetInPacket()->address; + HandlePacket(packet); + } } void InWorld::FrameEnd() { @@ -50,7 +83,8 @@ void InWorld::FrameEnd() { } void InWorld::Render(SDL_Surface* const screen) { - // + disconnectButton.DrawTo(screen); + shutDownButton.DrawTo(screen); } //------------------------- @@ -58,20 +92,39 @@ void InWorld::Render(SDL_Surface* const screen) { //------------------------- void InWorld::MouseMotion(SDL_MouseMotionEvent const& motion) { - // + disconnectButton.MouseMotion(motion); + shutDownButton.MouseMotion(motion); } void InWorld::MouseButtonDown(SDL_MouseButtonEvent const& button) { - // + disconnectButton.MouseButtonDown(button); + shutDownButton.MouseButtonDown(button); } void InWorld::MouseButtonUp(SDL_MouseButtonEvent const& button) { - // + if (disconnectButton.MouseButtonUp(button) == Button::State::HOVER) { + //send a disconnect request + NetworkPacket packet; + packet.meta.type = NetworkPacket::Type::DISCONNECT; + packet.clientInfo.index = clientIndex; + network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket)); + } + if (shutDownButton.MouseButtonUp(button) == Button::State::HOVER) { + //send a shutdown request + NetworkPacket packet; + packet.meta.type = NetworkPacket::Type::SHUTDOWN; + network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket)); + } } void InWorld::KeyDown(SDL_KeyboardEvent const& key) { switch(key.keysym.sym) { case SDLK_ESCAPE: + //send a disconnect request + NetworkPacket packet; + packet.meta.type = NetworkPacket::Type::DISCONNECT; + packet.clientInfo.index = clientIndex; + network.Send(Channels::SERVER, &packet, sizeof(NetworkPacket)); QuitEvent(); break; } @@ -80,3 +133,21 @@ void InWorld::KeyDown(SDL_KeyboardEvent const& key) { void InWorld::KeyUp(SDL_KeyboardEvent const& key) { // } + +void InWorld::HandlePacket(NetworkPacket packet) { + switch(packet.meta.type) { + case NetworkPacket::Type::DISCONNECT: + network.Unbind(Channels::SERVER); + clientIndex = -1; + SetNextScene(SceneList::MAINMENU); + break; + case NetworkPacket::Type::SYNCHRONIZE: + //TODO + break; + + //handle errors + default: + throw(std::runtime_error("Unknown NetworkPacket::Type encountered")); + break; + } +} \ No newline at end of file diff --git a/client/in_world.hpp b/client/in_world.hpp index 6763db7..7af63a1 100644 --- a/client/in_world.hpp +++ b/client/in_world.hpp @@ -24,10 +24,17 @@ #include "base_scene.hpp" +#include "config_utility.hpp" +#include "udp_network_utility.hpp" +#include "network_packet.hpp" +#include "image.hpp" +#include "raster_font.hpp" +#include "button.hpp" + class InWorld : public BaseScene { public: //Public access members - InWorld(); + InWorld(ConfigUtility* const, UDPNetworkUtility* const, int* const); ~InWorld(); protected: @@ -43,6 +50,19 @@ protected: void MouseButtonUp(SDL_MouseButtonEvent const&); void KeyDown(SDL_KeyboardEvent const&); void KeyUp(SDL_KeyboardEvent const&); + + void HandlePacket(NetworkPacket); + + //global + ConfigUtility& config; + UDPNetworkUtility& network; + int& clientIndex; + + //members + Image image; + RasterFont font; + Button disconnectButton; + Button shutDownButton; }; #endif diff --git a/client/lobby_menu.cpp b/client/lobby_menu.cpp index 2355122..cfea108 100644 --- a/client/lobby_menu.cpp +++ b/client/lobby_menu.cpp @@ -21,15 +21,18 @@ */ #include "lobby_menu.hpp" +#include "channels.hpp" + #include //------------------------- //Public access members //------------------------- -LobbyMenu::LobbyMenu(ConfigUtility* const arg1, UDPNetworkUtility* const arg2): +LobbyMenu::LobbyMenu(ConfigUtility* const arg1, UDPNetworkUtility* const arg2, int* const arg3): config(*arg1), - network(*arg2) + network(*arg2), + clientIndex(*arg3) { //setup the utility objects image.LoadSurface(config["dir.interface"] + "button_menu.bmp"); @@ -56,6 +59,9 @@ LobbyMenu::LobbyMenu(ConfigUtility* const arg1, UDPNetworkUtility* const arg2): search.SetText("Search"); join.SetText("Join"); back.SetText("Back"); + + //set the server list's position + listBox = {300, 50, 200, font.GetCharH()}; } LobbyMenu::~LobbyMenu() { @@ -89,7 +95,15 @@ void LobbyMenu::Render(SDL_Surface* const screen) { join.DrawTo(screen); back.DrawTo(screen); for (int i = 0; i < serverInfo.size(); i++) { - font.DrawStringTo(serverInfo[i].name, screen, 300, 50 + i*font.GetCharH()); + //draw the selected server's highlight + if (selection == &serverInfo[i]) { + SDL_Rect r = listBox; + r.y += i * listBox.h; + SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39)); + } + + //draw the server name + font.DrawStringTo(serverInfo[i].name, screen, listBox.x, listBox.y + i*listBox.h); } } @@ -118,15 +132,33 @@ void LobbyMenu::MouseButtonUp(SDL_MouseButtonEvent const& button) { //reset the server list serverInfo.clear(); + selection = nullptr; } - if (join.MouseButtonUp(button) == Button::State::HOVER) { - //TODO: join the selected server + else if (join.MouseButtonUp(button) == Button::State::HOVER && selection != nullptr) { + //join the selected server + NetworkPacket packet; + packet.meta.type = NetworkPacket::Type::JOIN_REQUEST; + network.Send(&selection->address, &packet, sizeof(NetworkPacket)); + selection = nullptr; } - if (back.MouseButtonUp(button) == Button::State::HOVER) { + else if (back.MouseButtonUp(button) == Button::State::HOVER) { SetNextScene(SceneList::MAINMENU); } + + else if ( + //has the user selected a server on the list? + button.x > listBox.x && + button.x < listBox.x + listBox.w && + button.y > listBox.y && + button.y < listBox.y + listBox.h * serverInfo.size() + ) { + selection = &serverInfo[(button.y - listBox.y)/listBox.h]; + } + else { + selection = nullptr; + } } void LobbyMenu::KeyDown(SDL_KeyboardEvent const& key) { @@ -144,14 +176,16 @@ void LobbyMenu::KeyUp(SDL_KeyboardEvent const& key) { void LobbyMenu::HandlePacket(NetworkPacket packet) { switch(packet.meta.type) { case NetworkPacket::Type::BROADCAST_RESPONSE: { - ServerInfo server; + ServerInformation server; server.name = packet.serverInfo.name; server.address = packet.meta.srcAddress; serverInfo.push_back(server); } break; case NetworkPacket::Type::JOIN_RESPONSE: - // + clientIndex = packet.clientInfo.index; + network.Bind(&packet.meta.srcAddress, Channels::SERVER); + SetNextScene(SceneList::INWORLD); break; //handle errors diff --git a/client/lobby_menu.hpp b/client/lobby_menu.hpp index ad93245..fc3551a 100644 --- a/client/lobby_menu.hpp +++ b/client/lobby_menu.hpp @@ -37,7 +37,7 @@ class LobbyMenu : public BaseScene { public: //Public access members - LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const); + LobbyMenu(ConfigUtility* const, UDPNetworkUtility* const, int* const); ~LobbyMenu(); protected: @@ -59,6 +59,7 @@ protected: //global ConfigUtility& config; UDPNetworkUtility& network; + int& clientIndex; //members Image image; @@ -67,12 +68,18 @@ protected: Button join; Button back; - struct ServerInfo { + //server list + struct ServerInformation { std::string name; IPaddress address; }; - std::vector serverInfo; + std::vector serverInfo; + + //a terrible hack, forgive me + //I'd love a proper gui system for this + SDL_Rect listBox; + ServerInformation* selection = nullptr; }; #endif diff --git a/common/network/network_packet.hpp b/common/network/network_packet.hpp index 0660a87..1954ade 100644 --- a/common/network/network_packet.hpp +++ b/common/network/network_packet.hpp @@ -52,6 +52,9 @@ union NetworkPacket { //mass update SYNCHRONIZE = 8, + //shut down the server + SHUTDOWN = 9, + //Player movement, etc. }; @@ -69,6 +72,12 @@ union NetworkPacket { //TODO: player count }serverInfo; + //information about the client + struct ClientInformation { + Metadata meta; + int index; + }clientInfo; + //defaults NetworkPacket() { meta.type = Type::NONE; diff --git a/server/main.cpp b/server/main.cpp index 2ad55b5..560bb95 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -42,45 +42,4 @@ int main(int argc, char** argv) { } cout << "Clean exit" << endl; return 0; -} -/*/ -#include "thread_safe_queue.hpp" - -#include "SDL/SDL.h" - -#include - -using namespace std; - -struct Object { - int value = 0; -}; - -int func(void* arg) { - ThreadSafeQueue& queue = *reinterpret_cast*>(arg); - while(1) { - Object o = queue.PopFront(); - if (o.value != 0) { - cout << o.value; - SDL_Delay(500); - cout << endl; - } - } -} - -int main(int, char**) { - ThreadSafeQueue queue; - - SDL_Thread* thread1 = SDL_CreateThread(func, reinterpret_cast(&queue)); - SDL_Thread* thread2 = SDL_CreateThread(func, reinterpret_cast(&queue)); - SDL_Thread* thread3 = SDL_CreateThread(func, reinterpret_cast(&queue)); - - while(1) { - SDL_Delay(1000); - Object o; - o.value = 3; - queue.PushBack(o); - } - return 0; -} -//*/ \ No newline at end of file +} \ No newline at end of file diff --git a/server/server_application.cpp b/server/server_application.cpp index 3f12b1f..f940edc 100644 --- a/server/server_application.cpp +++ b/server/server_application.cpp @@ -34,7 +34,7 @@ using namespace std; //Declarations //------------------------- -//int ServerApplication::ClientEntry::indexCounter = 0; +int ClientInformation::counter = 0; //------------------------- //Define the network thread @@ -164,14 +164,46 @@ void ServerApplication::HandlePacket(NetworkPacket packet) { snprintf(packet.serverInfo.name, PACKET_STRING_SIZE, "%s", config["server.name"].c_str()); networkUtil.Send(&packet.meta.srcAddress, &packet, sizeof(NetworkPacket)); break; - case NetworkPacket::Type::JOIN_REQUEST: - // + case NetworkPacket::Type::JOIN_REQUEST: { + //TODO: prevent duplicate logins from the same address? + + //create the new client, filling it with the correct info + ClientInformation newClient; + newClient.index = ClientInformation::counter++; + newClient.address = packet.meta.srcAddress; + + //push the new client + clientInfo[newClient.index] = newClient; + + //send the client their info + packet.meta.type = NetworkPacket::Type::JOIN_RESPONSE; + packet.clientInfo.index = newClient.index; + networkUtil.Send(&newClient.address, &packet, sizeof(NetworkPacket)); + + cout << "connect, total: " << clientInfo.size() << endl; + } break; case NetworkPacket::Type::DISCONNECT: - // + //disconnect the specified client + networkUtil.Send(&clientInfo[packet.clientInfo.index].address, &packet, sizeof(NetworkPacket)); + clientInfo.erase(packet.clientInfo.index); + + cout << "disconnect, total: " << clientInfo.size() << endl; break; case NetworkPacket::Type::SYNCHRONIZE: - // + //TODO + break; + case NetworkPacket::Type::SHUTDOWN: + //end the server + running = false; + + //disconnect all clients + packet.meta.type = NetworkPacket::Type::DISCONNECT; + for (auto& it : clientInfo) { + networkUtil.Send(&it.second.address, &packet, sizeof(NetworkPacket)); + } + + cout << "shutting down" << endl; break; //handle errors diff --git a/server/server_application.hpp b/server/server_application.hpp index e4c21ac..e579fe5 100644 --- a/server/server_application.hpp +++ b/server/server_application.hpp @@ -36,6 +36,15 @@ #include "config_utility.hpp" #include "world_room.hpp" +#include + +//hold the client info +struct ClientInformation { + static int counter; + int index; + IPaddress address; +}; + //The main application class class ServerApplication { public: @@ -63,6 +72,8 @@ private: bool running = true; ConfigUtility config; WorldRoom worldRoom; + + std::map clientInfo; }; #endif