Maelstrom: You can click the buttons to join the game!

https://github.com/libsdl-org/Maelstrom/commit/9a62c9218c3a4160e256dcda2c48b543a4975ccd

From 9a62c9218c3a4160e256dcda2c48b543a4975ccd Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 6 Nov 2011 03:42:18 -0500
Subject: [PATCH] You can click the buttons to join the game!

---
 UI/lobby.xml          |  10 ++--
 netlogic/gameinfo.cpp |   6 +-
 netlogic/lobby.cpp    | 128 ++++++++++++++++++++++++++++++++++++------
 netlogic/lobby.h      |   4 ++
 4 files changed, 126 insertions(+), 22 deletions(-)

diff --git a/UI/lobby.xml b/UI/lobby.xml
index 72d95e7f..55879888 100644
--- a/UI/lobby.xml
+++ b/UI/lobby.xml
@@ -33,7 +33,7 @@
 					<Size h="30"/>
 					<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT" x="14" y="71"/>
 					<Elements>
-						<DialogButton name="join" text="Join" default="true">
+						<DialogButton name="join" closeDialog="false" text="Join" default="true">
 							<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT"/>
 						</DialogButton>
 						<DialogLabel name="name" text="This is a name">
@@ -52,7 +52,7 @@
 					<Size h="30"/>
 					<Anchor anchorFrom="TOPLEFT" anchorTo="BOTTOMLEFT" anchor="game1"/>
 					<Elements>
-						<DialogButton name="join" text="Join">
+						<DialogButton name="join" closeDialog="false" text="Join">
 							<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT"/>
 						</DialogButton>
 						<DialogLabel name="name" text="This is a name">
@@ -71,7 +71,7 @@
 					<Size h="30"/>
 					<Anchor anchorFrom="TOPLEFT" anchorTo="BOTTOMLEFT" anchor="game2"/>
 					<Elements>
-						<DialogButton name="join" text="Join">
+						<DialogButton name="join" closeDialog="false" text="Join">
 							<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT"/>
 						</DialogButton>
 						<DialogLabel name="name" text="This is a name">
@@ -90,7 +90,7 @@
 					<Size h="30"/>
 					<Anchor anchorFrom="TOPLEFT" anchorTo="BOTTOMLEFT" anchor="game3"/>
 					<Elements>
-						<DialogButton name="join" text="Join">
+						<DialogButton name="join" closeDialog="false" text="Join">
 							<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT"/>
 						</DialogButton>
 						<DialogLabel name="name" text="This is a name">
@@ -109,7 +109,7 @@
 					<Size h="30"/>
 					<Anchor anchorFrom="TOPLEFT" anchorTo="BOTTOMLEFT" anchor="game4"/>
 					<Elements>
-						<DialogButton name="join" text="Join">
+						<DialogButton name="join" closeDialog="false" text="Join">
 							<Anchor anchorFrom="TOPLEFT" anchorTo="TOPLEFT"/>
 						</DialogButton>
 						<DialogLabel name="name" text="This is a name">
diff --git a/netlogic/gameinfo.cpp b/netlogic/gameinfo.cpp
index 4e6e31e2..5297c254 100644
--- a/netlogic/gameinfo.cpp
+++ b/netlogic/gameinfo.cpp
@@ -138,7 +138,11 @@ GameInfo::UpdateUI(GameInfoPlayer *player)
 		}
 	}
 	if (player->UI.host) {
-		if (player->address.host) {
+		if (player->playerID == localID) {
+			//player->UI.host->Show();
+			//player->UI.host->SetText("localhost");
+			player->UI.host->Hide();
+		} else if (player->address.host) {
 			player->UI.host->Show();
 			player->UI.host->SetText(SDLNet_ResolveIP(&player->address));
 		} else {
diff --git a/netlogic/lobby.cpp b/netlogic/lobby.cpp
index f83653ee..fea0cd91 100644
--- a/netlogic/lobby.cpp
+++ b/netlogic/lobby.cpp
@@ -99,6 +99,11 @@ LobbyDialogDelegate::OnLoad()
 		if (!GetElement(name, m_gameListElements[i])) {
 			return false;
 		}
+
+		UIElement *button = m_gameListElements[i]->GetElement<UIElement>("join");
+		if (button) {
+			button->SetClickCallback(this, &LobbyDialogDelegate::JoinGameClicked, m_gameListElements[i]);
+		}
 	}
 
 	count = SDL_arraysize(m_gameInfoPlayers);
@@ -158,8 +163,10 @@ LobbyDialogDelegate::OnTick()
 	    (now - m_lastRefresh) > GLOBAL_CHECK_INTERVAL) {
 		if (m_state == STATE_HOSTING) {
 			AdvertiseGame();
-		} else {
+		} else if (m_state == STATE_LISTING) {
 			GetGameList();
+		} else {
+			GetGameInfo();
 		}
 		m_lastRefresh = now;
 	}
@@ -219,6 +226,19 @@ LobbyDialogDelegate::GlobalGameChanged(void*)
 	}
 }
 
+void
+LobbyDialogDelegate::JoinGameClicked(void *_element)
+{
+	UIElement *element = (UIElement *)_element;
+	for (int i = 0; (unsigned)i < SDL_arraysize(m_gameListElements); ++i) {
+		if (element == m_gameListElements[i]) {
+			// We found the one that was clicked!
+			JoinGame(m_gameList[i]);
+			break;
+		}
+	}
+}
+
 void
 LobbyDialogDelegate::UpdateUI()
 {
@@ -290,6 +310,30 @@ LobbyDialogDelegate::GetGameList()
 	SDLNet_UDP_Send(gNetFD, -1, &m_packet);
 }
 
+void
+LobbyDialogDelegate::GetGameInfo()
+{
+	m_packet.StartLobbyMessage(LOBBY_REQUEST_GAME_INFO);
+	m_packet.address = m_game.players[0].address;
+	SDLNet_UDP_Send(gNetFD, -1, &m_packet);
+}
+
+void
+LobbyDialogDelegate::JoinGame(GameInfo &game)
+{
+	m_packet.StartLobbyMessage(LOBBY_REQUEST_JOIN);
+	m_packet.Write(game.gameID);
+	m_packet.Write(m_uniqueID);
+	m_packet.Write(prefs->GetString(PREFERENCES_HANDLE));
+	m_packet.address = game.players[0].address;;
+
+	SDLNet_UDP_Send(gNetFD, -1, &m_packet);
+
+	m_game.CopyFrom(game);
+	m_state = STATE_JOINING;
+	UpdateUI();
+}
+
 void
 LobbyDialogDelegate::ClearGameInfo()
 {
@@ -348,12 +392,15 @@ LobbyDialogDelegate::ProcessPacket(DynamicPacket &packet)
 		} else if (cmd == LOBBY_REQUEST_GAME_INFO) {
 			ProcessRequestGameInfo(packet);
 		} else if (cmd == LOBBY_REQUEST_JOIN) {
-			//ProcessRequestJoin(packet);
+			ProcessRequestJoin(packet);
 		} else if (cmd == LOBBY_REQUEST_LEAVE) {
 			//ProcessRequestLeave(packet);
 		}
+		return;
 
-	} else if (m_state == STATE_LISTING) {
+	}
+
+	if (m_state == STATE_LISTING) {
 		if (cmd == LOBBY_GAME_SERVERS) {
 			if (m_globalGame->IsChecked()) {
 				ProcessGameServerList(packet);
@@ -361,20 +408,14 @@ LobbyDialogDelegate::ProcessPacket(DynamicPacket &packet)
 			return;
 		}
 
-		if (cmd == LOBBY_PING) {
-			// Somebody thinks we're still in a game lobby
-			//RejectPing(packet);
-		} else if (cmd == LOBBY_GAME_INFO) {
-			ProcessGameInfo(packet);
-		}
-
-	} else if (m_state == STATE_JOINING) {
+	}
 
-		if (cmd == LOBBY_PING) {
-			//ProcessPing(packet);
-		} else if (cmd == LOBBY_REQUEST_GAME_INFO) {
-			ProcessGameInfo(packet);
-		}
+	// These packets we handle in all the join states
+	if (cmd == LOBBY_PING) {
+		// Somebody thinks we're still in a game lobby
+		//RejectPing(packet);
+	} else if (cmd == LOBBY_GAME_INFO) {
+		ProcessGameInfo(packet);
 	}
 }
 
@@ -411,6 +452,61 @@ LobbyDialogDelegate::ProcessRequestGameInfo(DynamicPacket &packet)
 	SDLNet_UDP_Send(gNetFD, -1, &m_reply);
 }
 
+void
+LobbyDialogDelegate::ProcessRequestJoin(DynamicPacket &packet)
+{
+	Uint32 gameID;
+	Uint32 playerID;
+	char name[MAX_NAMELEN+1];
+
+	if (!packet.Read(gameID) || gameID != m_game.gameID) {
+		return;
+	}
+	if (!packet.Read(playerID)) {
+		return;
+	}
+	if (!packet.Read(name, sizeof(name))) {
+		return;
+	}
+
+	// Find an empty slot
+	int slot;
+	for (slot = 0; slot < MAX_PLAYERS; ++slot) {
+		if (playerID == m_game.players[slot].playerID) {
+			// We already have this player, just update it.
+			break;
+		}
+	}
+	if (slot == MAX_PLAYERS) {
+		for (slot = 0; slot < MAX_PLAYERS; ++slot) {
+			if (!m_game.players[slot].playerID) {
+				break;
+			}
+		}
+	}
+	assert(slot < MAX_PLAYERS);
+
+	// Fill in the data
+	GameInfo::GameInfoPlayer *player = &m_game.players[slot];
+	player->playerID = playerID;
+	player->address = packet.address;
+	SDL_strlcpy(player->name, name, sizeof(player->name));
+
+	// Let everybody know!
+	m_reply.StartLobbyMessage(LOBBY_GAME_INFO);
+	m_game.WriteToPacket(m_reply);
+	for (slot = 0; slot < MAX_PLAYERS; ++slot) {
+		Uint32 playerID = m_game.players[slot].playerID;
+		if (playerID && playerID != m_uniqueID) {
+			m_reply.address = m_game.players[slot].address;
+			SDLNet_UDP_Send(gNetFD, -1, &m_reply);
+		}
+	}
+
+	// Update our own UI
+	UpdateUI();
+}
+
 void
 LobbyDialogDelegate::ProcessGameInfo(DynamicPacket &packet)
 {
diff --git a/netlogic/lobby.h b/netlogic/lobby.h
index 5c8a8cfb..01ec2a29 100644
--- a/netlogic/lobby.h
+++ b/netlogic/lobby.h
@@ -53,12 +53,15 @@ class LobbyDialogDelegate : public UIDialogDelegate
 	bool GetElement(const char *name, UIElement *&element);
 	void SetHostOrJoin(void*, int value);
 	void GlobalGameChanged(void*);
+	void JoinGameClicked(void *element);
 
 	void UpdateUI();
 
 	void AdvertiseGame();
 	void RemoveGame();
 	void GetGameList();
+	void GetGameInfo();
+	void JoinGame(GameInfo &game);
 	void ClearGameInfo();
 	void ClearGameList();
 
@@ -67,6 +70,7 @@ class LobbyDialogDelegate : public UIDialogDelegate
 	void ProcessPacket(DynamicPacket &packet);
 	void ProcessAnnouncePlayer(DynamicPacket &packet);
 	void ProcessRequestGameInfo(DynamicPacket &packet);
+	void ProcessRequestJoin(DynamicPacket &packet);
 	void ProcessGameServerList(DynamicPacket &packet);
 	void ProcessGameInfo(DynamicPacket &packet);