prepare code for dedicated server support

This commit is contained in:
NOTPIES 2026-03-08 22:13:19 -03:00
parent 6b89993c04
commit 00f6df9605
14 changed files with 161 additions and 23 deletions

3
.gitignore vendored
View file

@ -205,3 +205,6 @@ Minecraft.Client/PS3/PS3Extras/HeapInspector/
# Sony remote storage libs
Minecraft.Client/Common/Network/Sony/
Minecraft.Server/
build_dedicated/

View file

@ -1,6 +1,7 @@

#include "stdafx.h"
#include <time.h>
#include "..\..\Minecraft.World\Recipy.h"
#include "..\..\Minecraft.Client\Options.h"
#include "..\..\Minecraft.World\AABB.h"
@ -241,6 +242,26 @@ void CMinecraftApp::DebugPrintf(const char *szFormat, ...)
vsnprintf(buf, sizeof(buf), szFormat, ap);
va_end(ap);
OutputDebugStringA(buf);
#ifdef _DEDICATED_SERVER
bool hasContent = false;
for (const char *p = buf; *p; p++) {
if (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\r' && *p != '=') {
hasContent = true;
break;
}
}
if (hasContent)
{
size_t len = strlen(buf);
while (len > 0 && (buf[len-1] == '\n' || buf[len-1] == '\r'))
buf[--len] = '\0';
time_t now = time(NULL);
struct tm t;
localtime_s(&t, &now);
printf("[%02d:%02d:%02d] [Server thread/INFO]: %s\n", t.tm_hour, t.tm_min, t.tm_sec, buf);
}
#endif
#endif
}
@ -303,6 +324,9 @@ LPCWSTR CMinecraftApp::GetString(int iID)
{
//return L"Değişiklikler ve Yenilikler";
//return L"ÕÕÕÕÖÖÖÖ";
#ifdef _DEDICATED_SERVER
if (!app.m_stringTable) return L"";
#endif
return app.m_stringTable->getString(iID);
}

View file

@ -790,10 +790,12 @@ int CGameNetworkManager::JoinFromInvite_SignInReturned(void *pParam,bool bContin
void CGameNetworkManager::UpdateAndSetGameSessionData(INetworkPlayer *pNetworkPlayerLeaving)
{
#ifndef _DEDICATED_SERVER
Minecraft *pMinecraft = Minecraft::GetInstance();
TexturePack *tPack = pMinecraft->skins->getSelected();
s_pPlatformNetworkManager->SetSessionTexturePackParentId( tPack->getDLCParentPackId() );
s_pPlatformNetworkManager->SetSessionSubTexturePackId( tPack->getDLCSubPackId() );
#endif
s_pPlatformNetworkManager->UpdateAndSetGameSessionData( pNetworkPlayerLeaving );
}
@ -1421,6 +1423,7 @@ void CGameNetworkManager::CreateSocket( INetworkPlayer *pNetworkPlayer, bool loc
// Add this user to the game server if the game is started already
if( g_NetworkManager.IsHost() && g_NetworkManager.IsInGameplay() )
{
app.DebugPrintf("Adding incoming socket for smallId=%d\n", pNetworkPlayer->GetSmallId());
Socket::addIncomingSocket(socket);
}

View file

@ -1,5 +1,7 @@
#include "stdafx.h"
#include "CreativeMode.h"
#include "MultiPlayerLevel.h"
#include "MultiPlayerLocalPlayer.h"
#include "User.h"
#include "LocalPlayer.h"
#include "..\Minecraft.World\\net.minecraft.world.entity.player.h"
@ -66,12 +68,12 @@ bool CreativeMode::useItemOn(shared_ptr<Player> player, Level *level, shared_ptr
int t = level->getTile(x, y, z);
if (t > 0)
{
if (Tile::tiles[t]->use(level, x, y, z, player)) return true;
if (Tile::tiles[t]->use(level, x, y, z, player, face, 0.0f, 0.0f, 0.0f)) return true;
}
if (item == NULL) return false;
int aux = item->getAuxValue();
int count = item->count;
bool success = item->useOn(player, level, x, y, z, face);
bool success = item->useOn(player, level, x, y, z, face, 0.0f, 0.0f, 0.0f);
item->setAuxValue(aux);
item->count = count;
return success;

View file

@ -5046,11 +5046,18 @@ void Minecraft::handleClientTextureReceived(const wstring &textureName)
unsigned int Minecraft::getCurrentTexturePackId()
{
#ifdef _DEDICATED_SERVER
return 0;
#else
return skins->getSelected()->getId();
#endif
}
ColourTable *Minecraft::getColourTable()
{
#ifdef _DEDICATED_SERVER
return NULL;
#else
TexturePack *selected = skins->getSelected();
ColourTable *colours = selected->getColourTable();
@ -5061,6 +5068,7 @@ ColourTable *Minecraft::getColourTable()
}
return colours;
#endif
}
#if defined __ORBIS__

View file

@ -33,7 +33,11 @@
#include "..\Minecraft.World\net.minecraft.world.entity.h"
#include "ProgressRenderer.h"
#include "ServerPlayer.h"
#include "PlayerConnection.h"
#include "GameRenderer.h"
#ifdef _WINDOWS64
#include "Windows64\Network\WinsockNetLayer.h"
#endif
#include "..\Minecraft.World\ThreadName.h"
#include "..\Minecraft.World\IntCache.h"
#include "..\Minecraft.World\CompressedTileStorage.h"
@ -45,6 +49,11 @@
#endif
#include "PS3\PS3Extras\ShutdownManager.h"
#include "ServerCommandDispatcher.h"
#ifdef _DEDICATED_SERVER
#include "..\Minecraft.Server\ServerCommands.h"
#endif
#include "..\Minecraft.World\BiomeSource.h"
#include "PlayerChunkMap.h"
#include "Common\Telemetry\TelemetryManager.h"
@ -134,13 +143,11 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
#endif
settings = new Settings(new File(L"server.properties"));
app.DebugPrintf("\n*** SERVER SETTINGS ***\n");
app.DebugPrintf("ServerSettings: host-friends-only is %s\n",(app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0)?"on":"off");
app.DebugPrintf("ServerSettings: game-type is %s\n",(app.GetGameHostOption(eGameHostOption_GameType)==0)?"Survival Mode":"Creative Mode");
app.DebugPrintf("ServerSettings: pvp is %s\n",(app.GetGameHostOption(eGameHostOption_PvP)>0)?"on":"off");
app.DebugPrintf("ServerSettings: fire spreads is %s\n",(app.GetGameHostOption(eGameHostOption_FireSpreads)>0)?"on":"off");
app.DebugPrintf("ServerSettings: tnt explodes is %s\n",(app.GetGameHostOption(eGameHostOption_TNT)>0)?"on":"off");
app.DebugPrintf("\n");
app.DebugPrintf("host-friends-only is %s",(app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0)?"on":"off");
app.DebugPrintf("game-type is %s",(app.GetGameHostOption(eGameHostOption_GameType)==0)?"Survival Mode":"Creative Mode");
app.DebugPrintf("pvp is %s",(app.GetGameHostOption(eGameHostOption_PvP)>0)?"on":"off");
app.DebugPrintf("fire-spreads is %s",(app.GetGameHostOption(eGameHostOption_FireSpreads)>0)?"on":"off");
app.DebugPrintf("tnt-explodes is %s",(app.GetGameHostOption(eGameHostOption_TNT)>0)?"on":"off");
// TODO 4J Stu - Init a load of settings based on data passed as params
//settings->setBooleanAndSave( L"host-friends-only", (app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0) );
@ -267,6 +274,14 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
}
g_NetworkManager.ServerReady(); // 4J added
#ifdef _DEDICATED_SERVER
{
extern QNET_STATE _iQNetStubState;
_iQNetStubState = QNET_STATE_GAME_PLAY;
}
#endif
return m_bLoaded;
}
@ -389,7 +404,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
int gameTypeId = settings->getInt(L"gamemode", app.GetGameHostOption(eGameHostOption_GameType));//LevelSettings::GAMETYPE_SURVIVAL);
GameType *gameType = LevelSettings::validateGameType(gameTypeId);
app.DebugPrintf("Default game type: %d\n" , gameTypeId);
app.DebugPrintf("Default game type: %d" , gameTypeId);
LevelSettings *levelSettings = new LevelSettings(levelSeed, gameType, app.GetGameHostOption(eGameHostOption_Structures)>0?true:false, isHardcore(), true, pLevelType, initData->xzSize, initData->hellScale);
if( app.GetGameHostOption(eGameHostOption_BonusChest ) ) levelSettings->enableStartingBonusItems();
@ -481,7 +496,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
Minecraft *pMinecraft = Minecraft::GetInstance();
// m_lastSentDifficulty = pMinecraft->options->difficulty;
levels[i]->difficulty = app.GetGameHostOption(eGameHostOption_Difficulty); //pMinecraft->options->difficulty;
app.DebugPrintf("MinecraftServer::loadLevel - Difficulty = %d\n",levels[i]->difficulty);
app.DebugPrintf("MinecraftServer::loadLevel - Difficulty = %d",levels[i]->difficulty);
#if DEBUG_SERVER_DONT_SPAWN_MOBS
levels[i]->setSpawnSettings(false, false);
@ -659,8 +674,6 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
if(levels[0]->dimension->id==0)
{
app.DebugPrintf("===================================\n");
if(!levels[0]->getLevelData()->getHasStronghold())
{
int x,z;
@ -670,20 +683,19 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
levels[0]->getLevelData()->setZStronghold(z);
levels[0]->getLevelData()->setHasStronghold();
app.DebugPrintf("=== FOUND stronghold in terrain features list\n");
app.DebugPrintf("Found stronghold in terrain features list");
}
else
{
// can't find the stronghold position in the terrain feature list. Do we have to run a post-process?
app.DebugPrintf("=== Can't find stronghold in terrain features list\n");
app.DebugPrintf("Can't find stronghold in terrain features list");
}
}
else
{
app.DebugPrintf("=== Leveldata has stronghold position\n");
app.DebugPrintf("Leveldata has stronghold position");
}
app.DebugPrintf("===================================\n");
}
// printf("Post processing complete at %dms\n",System::currentTimeMillis() - startTime);
@ -1075,6 +1087,13 @@ void MinecraftServer::run(__int64 seed, void *lpParameter)
}
}
#ifdef _DEDICATED_SERVER
{
__int64 doneTime = System::currentTimeMillis();
app.DebugPrintf("Done! For help, type \"help\" or \"?\"");
}
#endif
__int64 lastTime = System::currentTimeMillis();
__int64 unprocessedTime = 0;
while (running && !s_bServerHalted)
@ -1527,6 +1546,11 @@ void MinecraftServer::tick()
}
Entity::tickExtraWandering(); // 4J added
#ifdef _DEDICATED_SERVER
g_NetworkManager.DoWork();
WinsockNetLayer::FlushPendingData();
#endif
PIXBeginNamedEvent(0,"Connection tick");
connection->tick();
PIXEndNamedEvent();
@ -1560,7 +1584,13 @@ void MinecraftServer::handleConsoleInputs()
AUTO_VAR(it, consoleInput.begin());
ConsoleInput *input = *it;
consoleInput.erase(it);
#ifdef _DEDICATED_SERVER
HandleServerCommand(input->msg, input->source, this);
delete input;
#else
// commands->handleCommand(input); // 4J - removed - TODO - do we want equivalent of console commands?
delete input;
#endif
}
}

View file

@ -89,6 +89,7 @@ void PendingConnection::handlePreLogin(shared_ptr<PreLoginPacket> packet)
return;
}
// printf("Server: handlePreLogin\n");
app.DebugPrintf("PreLogin received from \"%ls\"\n", packet->loginKey.c_str());
name = packet->loginKey; // 4J Stu - Change from the login packet as we know better on client end during the pre-login packet
sendPreLoginResponse();
}
@ -143,6 +144,7 @@ void PendingConnection::sendPreLoginResponse()
void PendingConnection::handleLogin(shared_ptr<LoginPacket> packet)
{
app.DebugPrintf("Login received from \"%ls\" (protocol %d)\n", name.c_str(), packet->clientVersion);
// printf("Server: handleLogin\n");
//name = packet->userName;
if (packet->clientVersion != SharedConstants::NETWORK_PROTOCOL_VERSION)

View file

@ -118,7 +118,7 @@ void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason)
return;
}
app.DebugPrintf("PlayerConnection disconect reason: %d\n", reason );
app.DebugPrintf("PlayerConnection disconnect reason: %d", reason );
player->disconnect();
// 4J Stu - Need to remove the player from the receiving list before their socket is NULLed so that we can find another player on their system
@ -130,10 +130,16 @@ void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason)
if(getWasKicked())
{
server->getPlayers()->broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(player->name, ChatPacket::e_ChatPlayerKickedFromGame) ) );
#ifdef _DEDICATED_SERVER
app.DebugPrintf("%ls was kicked from the game", player->name.c_str());
#endif
}
else
{
server->getPlayers()->broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(player->name, ChatPacket::e_ChatPlayerLeftGame) ) );
#ifdef _DEDICATED_SERVER
app.DebugPrintf("%ls left the game", player->name.c_str());
#endif
}
server->getPlayers()->remove(player);

View file

@ -236,6 +236,10 @@ void PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer>
//server->players->broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(L"<22>e" + playerEntity->name + L" joined the game.") ) );
broadcastAll( shared_ptr<ChatPacket>( new ChatPacket(player->name, ChatPacket::e_ChatPlayerJoinedGame) ) );
#ifdef _DEDICATED_SERVER
app.DebugPrintf("%ls joined the game", player->name.c_str());
#endif
MemSect(14);
add(player);
MemSect(0);

View file

@ -922,6 +922,7 @@ void ServerLevel::saveToDisc(ProgressListener *progressListener, bool autosave)
// 4J-PB - check that saves are enabled
if(StorageManager.GetSaveDisabled()) return;
#ifndef _DEDICATED_SERVER
// Check if we are using a trial version of a texture pack (which will be the case for going into the mash-up pack world with a trial version)
if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin())
{
@ -935,6 +936,7 @@ void ServerLevel::saveToDisc(ProgressListener *progressListener, bool autosave)
return;
}
}
#endif
if (progressListener != NULL) progressListener->progressStage(IDS_PROGRESS_SAVING_TO_DISC);
levelStorage->flushSaveFile(autosave);

View file

@ -49,6 +49,9 @@ std::vector<BYTE> WinsockNetLayer::s_pendingJoinSmallIds;
CRITICAL_SECTION WinsockNetLayer::s_freeSmallIdLock;
std::vector<BYTE> WinsockNetLayer::s_freeSmallIds;
CRITICAL_SECTION WinsockNetLayer::s_earlyDataLock;
std::vector<BYTE> WinsockNetLayer::s_earlyDataBuffers[WIN64_NET_MAX_CLIENTS + 1];
bool g_Win64MultiplayerHost = false;
bool g_Win64MultiplayerJoin = false;
int g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
@ -73,6 +76,7 @@ bool WinsockNetLayer::Initialize()
InitializeCriticalSection(&s_disconnectLock);
InitializeCriticalSection(&s_pendingJoinLock);
InitializeCriticalSection(&s_freeSmallIdLock);
InitializeCriticalSection(&s_earlyDataLock);
for (int i = 0; i < WIN64_NET_MAX_CLIENTS + 1; i++)
{
@ -356,6 +360,9 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port)
}
s_localSmallId = assignedSmallId;
DWORD noTimeout = 0;
setsockopt(s_hostConnectionSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&noTimeout, sizeof(noTimeout));
app.DebugPrintf("Win64 LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId);
s_active = true;
@ -458,13 +465,30 @@ void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsig
INetworkPlayer *pPlayerFrom = g_NetworkManager.GetPlayerBySmallId(fromSmallId);
INetworkPlayer *pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId);
if (pPlayerFrom == NULL || pPlayerTo == NULL) return;
if (pPlayerFrom == NULL || pPlayerTo == NULL)
{
if (s_isHost && fromSmallId > 0 && fromSmallId < WIN64_NET_MAX_CLIENTS + 1)
{
EnterCriticalSection(&s_earlyDataLock);
s_earlyDataBuffers[fromSmallId].insert(
s_earlyDataBuffers[fromSmallId].end(), data, data + dataSize);
LeaveCriticalSection(&s_earlyDataLock);
}
return;
}
if (s_isHost)
{
::Socket *pSocket = pPlayerFrom->GetSocket();
if (pSocket != NULL)
pSocket->pushDataToQueue(data, dataSize, false);
else
{
EnterCriticalSection(&s_earlyDataLock);
s_earlyDataBuffers[fromSmallId].insert(
s_earlyDataBuffers[fromSmallId].end(), data, data + dataSize);
LeaveCriticalSection(&s_earlyDataLock);
}
}
else
{
@ -474,6 +498,26 @@ void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsig
}
}
void WinsockNetLayer::FlushPendingData()
{
EnterCriticalSection(&s_earlyDataLock);
for (int i = 1; i < WIN64_NET_MAX_CLIENTS + 1; i++)
{
if (s_earlyDataBuffers[i].empty()) continue;
INetworkPlayer *pPlayer = g_NetworkManager.GetPlayerBySmallId((BYTE)i);
if (pPlayer == NULL) continue;
::Socket *pSocket = pPlayer->GetSocket();
if (pSocket == NULL) continue;
pSocket->pushDataToQueue(s_earlyDataBuffers[i].data(),
(DWORD)s_earlyDataBuffers[i].size(), false);
s_earlyDataBuffers[i].clear();
}
LeaveCriticalSection(&s_earlyDataLock);
}
DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param)
{
while (s_active)
@ -686,6 +730,11 @@ void WinsockNetLayer::CloseConnectionBySmallId(BYTE smallId)
app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId);
}
LeaveCriticalSection(&s_connectionsLock);
EnterCriticalSection(&s_earlyDataLock);
if (smallId < WIN64_NET_MAX_CLIENTS + 1)
s_earlyDataBuffers[smallId].clear();
LeaveCriticalSection(&s_earlyDataLock);
}
DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param)

View file

@ -83,6 +83,7 @@ public:
static SOCKET GetSocketForSmallId(BYTE smallId);
static void HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char *data, unsigned int dataSize);
static void FlushPendingData();
static bool PopDisconnectedSmallId(BYTE *outSmallId);
static void PushFreeSmallId(BYTE smallId);
@ -151,6 +152,9 @@ private:
static CRITICAL_SECTION s_freeSmallIdLock;
static std::vector<BYTE> s_freeSmallIds;
static CRITICAL_SECTION s_earlyDataLock;
static std::vector<BYTE> s_earlyDataBuffers[WIN64_NET_MAX_CLIENTS + 1];
};
extern bool g_Win64MultiplayerHost;

View file

@ -1889,7 +1889,8 @@ AABBList *Level::getCubes(shared_ptr<Entity> source, AABB *box, bool noEntities,
// 4J - now add in collision for any blocks which have actually been removed, but haven't had their render data updated to reflect this yet. This is to stop the player
// being able to move the view position inside a tile which is (visually) still there, and see out of the world. This is particularly a problem when moving upwards in
// creative mode as the player can get very close to the edge of tiles whilst looking upwards and can therefore very quickly move inside one.
Minecraft::GetInstance()->levelRenderer->destroyedTileManager->addAABBs( this, box, &boxes);
if(Minecraft::GetInstance()->levelRenderer != NULL)
Minecraft::GetInstance()->levelRenderer->destroyedTileManager->addAABBs( this, box, &boxes);
// 4J - added
if( noEntities ) return &boxes;

View file

@ -192,7 +192,7 @@ StructurePiece *StrongholdPieces::generateAndAddPiece(StartPiece *startPiece, li
{
return NULL;
}
if (abs(footX - startPiece->getBoundingBox()->x0) > 3 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 3 * 16)
if (abs(footX - startPiece->getBoundingBox()->x0) > 3 * 16 || abs(footZ - startPiece->getBoundingBox()->z0) > 3 * 16)
{
// Force attempt at spawning a portal room
if(startPiece->m_level->getOriginalSaveVersion() >= SAVE_FILE_VERSION_MOVED_STRONGHOLD && !startPiece->m_level->getLevelData()->getHasStrongholdEndPortal())
@ -204,7 +204,7 @@ StructurePiece *StrongholdPieces::generateAndAddPiece(StartPiece *startPiece, li
if(piece->pieceClass != EPieceClass_PortalRoom) continue;
#ifndef _CONTENT_PACKAGE
printf("Portal room forcing attempt\n");
app.DebugPrintf("Portal room forcing attempt\n");
#endif
StrongholdPiece *strongholdPiece = PortalRoom::createPiece(pieces, random, footX, footY, footZ, direction, depth);
if (strongholdPiece != NULL)
@ -217,7 +217,7 @@ StructurePiece *StrongholdPieces::generateAndAddPiece(StartPiece *startPiece, li
currentPieces.remove(piece);
}
#ifndef _CONTENT_PACKAGE
printf("Success\n");
app.DebugPrintf("Success\n");
#endif
return strongholdPiece;
}