aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
diff options
context:
space:
mode:
authorlspepinho <162769565+lspepinho@users.noreply.github.com>2026-03-02 20:30:22 -0300
committerGitHub <noreply@github.com>2026-03-03 06:30:22 +0700
commit8b28c20d7adc3824f96fbcc34ad65d778a97a05b (patch)
treee61705a557e4e064d707ec542c53dbdac1acbe09 /Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
parent15129932da9442c2815974c519258345b22d5588 (diff)
Fixes for PR #96 (#170)
* Implement basic multiplayer functionality * Update README.md --------- Co-authored-by: Slenderman <ssimulpong@outlook.com>
Diffstat (limited to 'Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp')
-rw-r--r--Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp225
1 files changed, 222 insertions, 3 deletions
diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
index b6b0fe12..10d1a6a5 100644
--- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
+++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp
@@ -2,7 +2,12 @@
#include "..\..\..\Minecraft.World\Socket.h"
#include "..\..\..\Minecraft.World\StringHelpers.h"
#include "PlatformNetworkManagerStub.h"
-#include "..\..\Xbox\Network\NetworkPlayerXbox.h" // TODO - stub version of this?
+#include "..\..\Xbox\Network\NetworkPlayerXbox.h"
+#ifdef _WINDOWS64
+#include "..\..\Windows64\Network\WinsockNetLayer.h"
+#include "..\..\Minecraft.h"
+#include "..\..\User.h"
+#endif
CPlatformNetworkManagerStub *g_pPlatformNetworkManager;
@@ -114,10 +119,43 @@ void CPlatformNetworkManagerStub::NotifyPlayerJoined(IQNetPlayer *pQNetPlayer )
}
}
+void CPlatformNetworkManagerStub::NotifyPlayerLeaving(IQNetPlayer* pQNetPlayer)
+{
+ app.DebugPrintf("Player 0x%p \"%ls\" leaving.\n", pQNetPlayer, pQNetPlayer->GetGamertag());
+
+ INetworkPlayer* networkPlayer = getNetworkPlayer(pQNetPlayer);
+ if (networkPlayer == NULL)
+ return;
+
+ Socket* socket = networkPlayer->GetSocket();
+ if (socket != NULL)
+ {
+ if (m_pIQNet->IsHost())
+ g_NetworkManager.CloseConnection(networkPlayer);
+ }
+
+ if (m_pIQNet->IsHost())
+ {
+ SystemFlagRemovePlayer(networkPlayer);
+ }
+
+ g_NetworkManager.PlayerLeaving(networkPlayer);
+
+ for (int idx = 0; idx < XUSER_MAX_COUNT; ++idx)
+ {
+ if (playerChangedCallback[idx] != NULL)
+ playerChangedCallback[idx](playerChangedCallbackParam[idx], networkPlayer, true);
+ }
+
+ removeNetworkPlayer(pQNetPlayer);
+}
+
+
bool CPlatformNetworkManagerStub::Initialise(CGameNetworkManager *pGameNetworkManager, int flagIndexSize)
{
m_pGameNetworkManager = pGameNetworkManager;
m_flagIndexSize = flagIndexSize;
+ m_pIQNet = new IQNet();
g_pPlatformNetworkManager = this;
for( int i = 0; i < XUSER_MAX_COUNT; i++ )
{
@@ -174,6 +212,37 @@ bool CPlatformNetworkManagerStub::isSystemPrimaryPlayer(IQNetPlayer *pQNetPlayer
// We call this twice a frame, either side of the render call so is a good place to "tick" things
void CPlatformNetworkManagerStub::DoWork()
{
+#ifdef _WINDOWS64
+ extern QNET_STATE _iQNetStubState;
+ if (_iQNetStubState == QNET_STATE_SESSION_STARTING && app.GetGameStarted())
+ {
+ _iQNetStubState = QNET_STATE_GAME_PLAY;
+ if (m_pIQNet->IsHost())
+ WinsockNetLayer::UpdateAdvertiseJoinable(true);
+ }
+ if (_iQNetStubState == QNET_STATE_IDLE)
+ TickSearch();
+ if (_iQNetStubState == QNET_STATE_GAME_PLAY && m_pIQNet->IsHost())
+ {
+ BYTE disconnectedSmallId;
+ while (WinsockNetLayer::PopDisconnectedSmallId(&disconnectedSmallId))
+ {
+ IQNetPlayer* qnetPlayer = m_pIQNet->GetPlayerBySmallId(disconnectedSmallId);
+ if (qnetPlayer != NULL && qnetPlayer->m_smallId == disconnectedSmallId)
+ {
+ NotifyPlayerLeaving(qnetPlayer);
+ qnetPlayer->m_smallId = 0;
+ qnetPlayer->m_isRemote = false;
+ qnetPlayer->m_isHostPlayer = false;
+ qnetPlayer->m_gamertag[0] = 0;
+ qnetPlayer->SetCustomDataValue(0);
+ WinsockNetLayer::PushFreeSmallId(disconnectedSmallId);
+ if (IQNet::s_playerCount > 1)
+ IQNet::s_playerCount--;
+ }
+ }
+ }
+#endif
}
int CPlatformNetworkManagerStub::GetPlayerCount()
@@ -232,6 +301,10 @@ bool CPlatformNetworkManagerStub::LeaveGame(bool bMigrateHost)
m_bLeavingGame = true;
+#ifdef _WINDOWS64
+ WinsockNetLayer::StopAdvertising();
+#endif
+
// If we are the host wait for the game server to end
if(m_pIQNet->IsHost() && g_NetworkManager.ServerStoppedValid())
{
@@ -239,6 +312,22 @@ bool CPlatformNetworkManagerStub::LeaveGame(bool bMigrateHost)
g_NetworkManager.ServerStoppedWait();
g_NetworkManager.ServerStoppedDestroy();
}
+ else
+ {
+ m_pIQNet->EndGame();
+ }
+
+ for (AUTO_VAR(it, currentNetworkPlayers.begin()); it != currentNetworkPlayers.end(); it++)
+ delete* it;
+ currentNetworkPlayers.clear();
+ m_machineQNetPrimaryPlayers.clear();
+ SystemFlagReset();
+
+#ifdef _WINDOWS64
+ WinsockNetLayer::Shutdown();
+ WinsockNetLayer::Initialize();
+#endif
+
return true;
}
@@ -262,7 +351,24 @@ void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame,
m_pIQNet->HostGame();
+#ifdef _WINDOWS64
+ IQNet::m_player[0].m_smallId = 0;
+ IQNet::m_player[0].m_isRemote = false;
+ IQNet::m_player[0].m_isHostPlayer = true;
+ IQNet::s_playerCount = 1;
+#endif
+
_HostGame( localUsersMask, publicSlots, privateSlots );
+
+#ifdef _WINDOWS64
+ int port = WIN64_NET_DEFAULT_PORT;
+ if (!WinsockNetLayer::IsActive())
+ WinsockNetLayer::HostGame(port);
+
+ const wchar_t* hostName = IQNet::m_player[0].m_gamertag;
+ unsigned int settings = app.GetGameHostOption(eGameHostOption_All);
+ WinsockNetLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION);
+#endif
//#endif
}
@@ -275,9 +381,54 @@ bool CPlatformNetworkManagerStub::_StartGame()
return true;
}
-int CPlatformNetworkManagerStub::JoinGame(FriendSessionInfo *searchResult, int localUsersMask, int primaryUserIndex)
+int CPlatformNetworkManagerStub::JoinGame(FriendSessionInfo* searchResult, int localUsersMask, int primaryUserIndex)
{
+#ifdef _WINDOWS64
+ if (searchResult == NULL)
+ return CGameNetworkManager::JOINGAME_FAIL_GENERAL;
+
+ const char* hostIP = searchResult->data.hostIP;
+ int hostPort = searchResult->data.hostPort;
+
+ if (hostPort <= 0 || hostIP[0] == 0)
+ return CGameNetworkManager::JOINGAME_FAIL_GENERAL;
+
+ m_bLeavingGame = false;
+ IQNet::s_isHosting = false;
+ m_pIQNet->ClientJoinGame();
+
+ IQNet::m_player[0].m_smallId = 0;
+ IQNet::m_player[0].m_isRemote = true;
+ IQNet::m_player[0].m_isHostPlayer = true;
+ wcsncpy_s(IQNet::m_player[0].m_gamertag, 32, searchResult->data.hostName, _TRUNCATE);
+
+ WinsockNetLayer::StopDiscovery();
+
+ if (!WinsockNetLayer::JoinGame(hostIP, hostPort))
+ {
+ app.DebugPrintf("Win64 LAN: Failed to connect to %s:%d\n", hostIP, hostPort);
+ return CGameNetworkManager::JOINGAME_FAIL_GENERAL;
+ }
+
+ BYTE localSmallId = WinsockNetLayer::GetLocalSmallId();
+
+ IQNet::m_player[localSmallId].m_smallId = localSmallId;
+ IQNet::m_player[localSmallId].m_isRemote = false;
+ IQNet::m_player[localSmallId].m_isHostPlayer = false;
+
+ Minecraft* pMinecraft = Minecraft::GetInstance();
+ wcscpy_s(IQNet::m_player[localSmallId].m_gamertag, 32, pMinecraft->user->name.c_str());
+ IQNet::s_playerCount = localSmallId + 1;
+
+ NotifyPlayerJoined(&IQNet::m_player[0]);
+ NotifyPlayerJoined(&IQNet::m_player[localSmallId]);
+
+ m_pGameNetworkManager->StateChange_AnyToStarting();
+
return CGameNetworkManager::JOINGAME_SUCCESS;
+#else
+ return CGameNetworkManager::JOINGAME_SUCCESS;
+#endif
}
bool CPlatformNetworkManagerStub::SetLocalGame(bool isLocal)
@@ -315,6 +466,22 @@ void CPlatformNetworkManagerStub::HandleSignInChange()
bool CPlatformNetworkManagerStub::_RunNetworkGame()
{
+#ifdef _WINDOWS64
+ extern QNET_STATE _iQNetStubState;
+ _iQNetStubState = QNET_STATE_GAME_PLAY;
+
+ for (DWORD i = 0; i < IQNet::s_playerCount; i++)
+ {
+ if (IQNet::m_player[i].m_isRemote)
+ {
+ INetworkPlayer* pNetworkPlayer = getNetworkPlayer(&IQNet::m_player[i]);
+ if (pNetworkPlayer != NULL && pNetworkPlayer->GetSocket() != NULL)
+ {
+ Socket::addIncomingSocket(pNetworkPlayer->GetSocket());
+ }
+ }
+ }
+#endif
return true;
}
@@ -503,10 +670,60 @@ wstring CPlatformNetworkManagerStub::GatherRTTStats()
void CPlatformNetworkManagerStub::TickSearch()
{
+#ifdef _WINDOWS64
+ if (m_SessionsUpdatedCallback == NULL)
+ return;
+
+ static DWORD lastSearchTime = 0;
+ DWORD now = GetTickCount();
+ if (now - lastSearchTime < 2000)
+ return;
+ lastSearchTime = now;
+
+ SearchForGames();
+#endif
}
void CPlatformNetworkManagerStub::SearchForGames()
{
+#ifdef _WINDOWS64
+ std::vector<Win64LANSession> lanSessions = WinsockNetLayer::GetDiscoveredSessions();
+
+ for (size_t i = 0; i < friendsSessions[0].size(); i++)
+ delete friendsSessions[0][i];
+ friendsSessions[0].clear();
+
+ for (size_t i = 0; i < lanSessions.size(); i++)
+ {
+ FriendSessionInfo* info = new FriendSessionInfo();
+ size_t nameLen = wcslen(lanSessions[i].hostName);
+ info->displayLabel = new wchar_t[nameLen + 1];
+ wcscpy_s(info->displayLabel, nameLen + 1, lanSessions[i].hostName);
+ info->displayLabelLength = (unsigned char)nameLen;
+ info->displayLabelViewableStartIndex = 0;
+
+ info->data.netVersion = lanSessions[i].netVersion;
+ info->data.m_uiGameHostSettings = lanSessions[i].gameHostSettings;
+ info->data.texturePackParentId = lanSessions[i].texturePackParentId;
+ info->data.subTexturePackId = lanSessions[i].subTexturePackId;
+ info->data.isReadyToJoin = lanSessions[i].isJoinable;
+ info->data.isJoinable = lanSessions[i].isJoinable;
+ strncpy_s(info->data.hostIP, sizeof(info->data.hostIP), lanSessions[i].hostIP, _TRUNCATE);
+ info->data.hostPort = lanSessions[i].hostPort;
+ wcsncpy_s(info->data.hostName, XUSER_NAME_SIZE, lanSessions[i].hostName, _TRUNCATE);
+ info->data.playerCount = lanSessions[i].playerCount;
+ info->data.maxPlayers = lanSessions[i].maxPlayers;
+
+ info->sessionId = (SessionID)((unsigned __int64)inet_addr(lanSessions[i].hostIP) | ((unsigned __int64)lanSessions[i].hostPort << 32));
+
+ friendsSessions[0].push_back(info);
+ }
+
+ m_searchResultsCount[0] = (int)friendsSessions[0].size();
+
+ if (m_SessionsUpdatedCallback != NULL)
+ m_SessionsUpdatedCallback(m_pSearchParam);
+#endif
}
int CPlatformNetworkManagerStub::SearchForGamesThreadProc( void* lpParameter )
@@ -522,7 +739,9 @@ void CPlatformNetworkManagerStub::SetSearchResultsReady(int resultCount)
vector<FriendSessionInfo *> *CPlatformNetworkManagerStub::GetSessionList(int iPad, int localPlayers, bool partyOnly)
{
- vector<FriendSessionInfo *> *filteredList = new vector<FriendSessionInfo *>();;
+ vector<FriendSessionInfo*>* filteredList = new vector<FriendSessionInfo*>();
+ for (size_t i = 0; i < friendsSessions[0].size(); i++)
+ filteredList->push_back(friendsSessions[0][i]);
return filteredList;
}