* Implement basic multiplayer functionality * Update README.md --------- Co-authored-by: Slenderman <ssimulpong@outlook.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user