Files
DrPerkyLegit-LCEServerTest/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
2026-05-16 11:30:28 -04:00

558 lines
16 KiB
C++

#include "stdafx.h"
#include <assert.h>
#include <iostream>
#include <ShellScalingApi.h>
#include <shellapi.h>
#include "GameConfig\Minecraft.spa.h"
#include "..\MinecraftServer.h"
#include "..\LocalPlayer.h"
#include "..\..\Minecraft.World\ItemInstance.h"
#include "..\..\Minecraft.World\MapItem.h"
#include "..\..\Minecraft.World\Recipes.h"
#include "..\..\Minecraft.World\Recipy.h"
#include "..\..\Minecraft.World\Language.h"
#include "..\..\Minecraft.World\StringHelpers.h"
#include "..\..\Minecraft.World\AABB.h"
#include "..\..\Minecraft.World\Vec3.h"
#include "..\..\Minecraft.World\Level.h"
#include "..\..\Minecraft.World\net.minecraft.world.level.tile.h"
#include "..\ClientConnection.h"
#include "..\Minecraft.h"
#include "KeyboardMouseInput.h"
#include "..\User.h"
#include "..\..\Minecraft.World\Socket.h"
#include "..\..\Minecraft.World\ThreadName.h"
#include "..\..\Minecraft.Client\StatsCounter.h"
//#include "Social\SocialManager.h"
//#include "Leaderboards\LeaderboardManager.h"
//#include "XUI\XUI_Scene_Container.h"
//#include "NetworkManager.h"
#include "..\..\Minecraft.Client\Tesselator.h"
#include "..\..\Minecraft.Client\Options.h"
#include "Sentient\SentientManager.h"
#include "..\..\Minecraft.World\IntCache.h"
#include "..\Textures.h"
#include "..\Settings.h"
#include "Resource.h"
#include "..\..\Minecraft.World\compression.h"
#include "..\..\Minecraft.World\OldChunkStorage.h"
#include "..\GameRenderer.h"
#include "Network\WinsockNetLayer.h"
#include "Windows64_Xuid.h"
#include "Windows64_Minecraft.h"
#include "../../Minecraft.Server/Utils/Logger.h"
// Forward-declare the internal Renderer class and its global instance from 4J_Render_PC_d.lib.
// C4JRender (RenderManager) is a stateless wrapper — all D3D state lives in InternalRenderManager.
class Renderer;
extern Renderer InternalRenderManager;
#ifdef _MSC_VER
#pragma comment(lib, "legacy_stdio_definitions.lib")
#endif
#define THEME_NAME "584111F70AAAAAAA"
#define THEME_FILESIZE 2797568
#define FIFTY_ONE_MB (1000000*51) // Maximum TCR space required for a save is 52MB (checking for this on a selected device)
#define NUM_PROFILE_VALUES 5
#define NUM_PROFILE_SETTINGS 4
DWORD dwProfileSettingsA[NUM_PROFILE_VALUES] = { 0,0,0,0,0 };
char g_Win64Username[17] = { 0 };
wchar_t g_Win64UsernameW[17] = { 0 };
//#define MEMORY_TRACKING
#ifdef MEMORY_TRACKING
void ResetMem();
void DumpMem();
void MemPixStuff();
#else
void MemSect(int sect)
{
}
#endif
// 4J Stu - These functions are referenced from the Windows Input library
void ClearGlobalText() { }
uint16_t* GetGlobalText() { return nullptr; }
void SeedEditBox() { }
static Minecraft* InitialiseMinecraftRuntime()
{
//app.loadMediaArchive();
//app.loadStringTable();
ProfileManager.Initialise(TITLEID_MINECRAFT,
app.m_dwOfferID,
PROFILE_VERSION_10,
NUM_PROFILE_VALUES,
NUM_PROFILE_SETTINGS,
dwProfileSettingsA,
app.GAME_DEFINED_PROFILE_DATA_BYTES * XUSER_MAX_COUNT,
&app.uiGameDefinedDataChangedBitmask
);
ProfileManager.SetDefaultOptionsCallback(&CConsoleMinecraftApp::DefaultOptionsCallback, (LPVOID)&app);
g_NetworkManager.Initialise();
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
{
IQNet::m_player[i].m_smallId = static_cast<BYTE>(i);
IQNet::m_player[i].m_isRemote = false;
IQNet::m_player[i].m_isHostPlayer = (i == 0);
swprintf_s(IQNet::m_player[i].m_gamertag, 32, L"Player%d", i);
}
wcscpy_s(IQNet::m_player[0].m_gamertag, 32, g_Win64UsernameW);
WinsockNetLayer::Initialize();
ProfileManager.SetDebugFullOverride(true);
Tesselator::CreateNewThreadStorage(1024 * 1024);
AABB::CreateNewThreadStorage();
Vec3::CreateNewThreadStorage();
IntCache::CreateNewThreadStorage();
Compression::CreateNewThreadStorage();
OldChunkStorage::CreateNewThreadStorage();
Level::enableLightingCache();
Tile::CreateNewThreadStorage();
Minecraft::main();
Minecraft* pMinecraft = Minecraft::GetInstance();
if (pMinecraft == nullptr)
return nullptr;
//app.InitGameSettings();
app.InitialiseTips();
return pMinecraft;
}
static int HeadlessServerConsoleThreadProc(void* lpParameter)
{
UNREFERENCED_PARAMETER(lpParameter);
std::string line;
while (!app.m_bShutdown)
{
if (!std::getline(std::cin, line))
{
if (std::cin.eof())
{
break;
}
std::cin.clear();
Sleep(50);
continue;
}
wstring command = trimString(convStringToWstring(line));
if (command.empty())
continue;
MinecraftServer* server = MinecraftServer::getInstance();
if (server != nullptr)
{
server->handleConsoleInput(command, server);
}
}
return 0;
}
PlayerUID Windows64Minecraft::ResolvePersistentXuidFromName(const std::wstring& playerName)
{
const unsigned __int64 fnvOffset = 14695981039346656037ULL;
const unsigned __int64 fnvPrime = 1099511628211ULL;
unsigned __int64 hash = fnvOffset;
for (size_t i = 0; i < playerName.length(); ++i)
{
unsigned short codeUnit = (unsigned short)playerName[i];
hash ^= (unsigned __int64)(codeUnit & 0xFF);
hash *= fnvPrime;
hash ^= (unsigned __int64)((codeUnit >> 8) & 0xFF);
hash *= fnvPrime;
}
// Namespace the hash away from legacy smallId-based values.
hash ^= 0x9E3779B97F4A7C15ULL;
hash |= 0x8000000000000000ULL;
if (hash == (unsigned __int64)INVALID_XUID)
{
hash ^= 0x0100000000000001ULL;
}
return (PlayerUID)hash;
}
void Windows64Minecraft::StartDedicatedServer() {
__int64 startupTime = System::currentRealTimeMillis();
Logger::Info("Loading Server Properties");
Settings serverSettings(new File(L"server.properties"));
const wstring configuredBindIp = serverSettings.getString(L"server-ip", L"");
const char* bindIp = "0.0.0.0";
if (g_Win64DedicatedServerBindIP[0] != 0)
bindIp = g_Win64DedicatedServerBindIP;
else if (!configuredBindIp.empty())
bindIp = wstringtochararray(configuredBindIp);
const int port = g_Win64DedicatedServerPort > 0 ? g_Win64DedicatedServerPort : serverSettings.getInt(L"server-port", WIN64_NET_DEFAULT_PORT);
const std::string addressCombo = std::string(bindIp) + ":" + std::to_string(port);
strncpy_s(g_Win64Username, sizeof(g_Win64Username), "Player", _TRUNCATE);
MultiByteToWideChar(CP_ACP, 0, g_Win64Username, -1, g_Win64UsernameW, 17);
const Minecraft* pMinecraft = InitialiseMinecraftRuntime();
if (pMinecraft == nullptr)
{
Logger::Error("Failed To Initialise Minecraft Runtime");
return;
}
app.SetGameHostOption(eGameHostOption_Difficulty, serverSettings.getInt(L"difficulty", 1));
app.SetGameHostOption(eGameHostOption_Gamertags, serverSettings.getBoolean(L"show-gamertags", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_GameType, serverSettings.getInt(L"gamemode", 0));
app.SetGameHostOption(eGameHostOption_LevelType, serverSettings.getBoolean(L"superflat", false) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_Structures, serverSettings.getBoolean(L"generate-structures", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_BonusChest, serverSettings.getBoolean(L"bonus-chest", false) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_PvP, serverSettings.getBoolean(L"pvp", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_TrustPlayers, serverSettings.getBoolean(L"trust-players", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_FireSpreads, serverSettings.getBoolean(L"fire-spreads", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_TNT, serverSettings.getBoolean(L"tnt", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_HostCanFly, 1);
app.SetGameHostOption(eGameHostOption_HostCanChangeHunger, 1);
app.SetGameHostOption(eGameHostOption_HostCanBeInvisible, 1);
app.SetGameHostOption(eGameHostOption_MobGriefing, serverSettings.getBoolean(L"mob-griefing", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_KeepInventory, serverSettings.getBoolean(L"keep-inventory", false) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1);
app.SetGameHostOption(eGameHostOption_DoMobLoot, 1);
app.SetGameHostOption(eGameHostOption_DoTileDrops, 1);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, serverSettings.getBoolean(L"natural-regeneration", true) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, serverSettings.getBoolean(L"daylight-cycle", true) ? 1 : 0);
MinecraftServer::resetFlags();
g_NetworkManager.HostGame(0, false, true, MINECRAFT_NET_MAX_PLAYERS, 0);
if (!WinsockNetLayer::IsActive())
{
Logger::Error(("Failed To Activate Socket Binding On" + addressCombo).c_str());
return;
}
g_NetworkManager.FakeLocalPlayerJoined();
NetworkGameInitData* param = new NetworkGameInitData();
param->seed = serverSettings.getInt(L"seed", 0);
std::wstring WorldSize = serverSettings.getString(L"world-size", L"small");
if (WorldSize == L"classic") {
param->hellScale = HELL_LEVEL_SCALE_CLASSIC;
param->xzSize = LEVEL_WIDTH_CLASSIC;
app.SetGameHostOption(eGameHostOption_WorldSize, 1);
}
else if (WorldSize == L"small") {
param->hellScale = HELL_LEVEL_SCALE_SMALL;
param->xzSize = LEVEL_WIDTH_SMALL;
app.SetGameHostOption(eGameHostOption_WorldSize, 2);
}
else if (WorldSize == L"medium") {
param->hellScale = HELL_LEVEL_SCALE_MEDIUM;
param->xzSize = LEVEL_WIDTH_MEDIUM;
app.SetGameHostOption(eGameHostOption_WorldSize, 3);
}
else if (WorldSize == L"large") {
param->hellScale = HELL_LEVEL_SCALE_LARGE;
param->xzSize = LEVEL_WIDTH_LARGE;
app.SetGameHostOption(eGameHostOption_WorldSize, 4);
}
wchar_t exePath[MAX_PATH] = {};
GetModuleFileNameW(NULL, exePath, MAX_PATH);
wchar_t* lastSlash = wcsrchr(exePath, L'\\');
if (lastSlash) {
*(lastSlash + 1) = L'\0'; // keep trailing slash
}
wchar_t filePath[MAX_PATH] = {};
_snwprintf_s(filePath, sizeof(filePath), _TRUNCATE, L"%sWindows64\\GameHDD\\saveData.ms", exePath);
File* saveFile = new File(filePath);
__int64 fileSize = saveFile->length();
if (fileSize > 0) {
FileInputStream fis(*saveFile);
byteArray ba(fileSize);
fis.read(ba);
fis.close();
LoadSaveDataThreadParam* saveData = new LoadSaveDataThreadParam(ba.data, ba.length, saveFile->getName());
param->saveData = saveData;
}
param->settings = app.GetGameHostOption(eGameHostOption_All);
g_NetworkManager.ServerStoppedCreate(true);
g_NetworkManager.ServerReadyCreate(true);
C4JThread* thread = new C4JThread(&CGameNetworkManager::ServerThreadProc, param, "Server", 256 * 1024);
thread->SetProcessor(CPU_CORE_SERVER);
thread->Run();
g_NetworkManager.ServerReadyWait();
g_NetworkManager.ServerReadyDestroy();
if (MinecraftServer::serverHalted())
{
Logger::Error("MinecraftServer Has Haulted During Startup");
g_NetworkManager.LeaveGame(false);
return;
}
app.SetGameStarted(true);
g_NetworkManager.DoWork();
double finishedStartupTime = ((System::currentRealTimeMillis() - startupTime) / 1000.0);
Logger::Info(("Server Has Started In: " + std::to_string(finishedStartupTime)).c_str());
C4JThread* consoleThread = new C4JThread(&HeadlessServerConsoleThreadProc, nullptr, "Server console", 128 * 1024);
consoleThread->Run();
MSG msg = { 0 };
while (WM_QUIT != msg.message && !app.m_bShutdown && !MinecraftServer::serverHalted())
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
app.UpdateTime();
ProfileManager.Tick();
StorageManager.Tick();
g_NetworkManager.DoWork();
app.HandleXuiActions();
Sleep(10);
}
printf("Stopping server...\n");
fflush(stdout);
app.m_bShutdown = true;
MinecraftServer::HaltServer();
g_NetworkManager.LeaveGame(false);
return;
}
#ifdef MEMORY_TRACKING
int totalAllocGen = 0;
unordered_map<int, int> allocCounts;
bool trackEnable = false;
bool trackStarted = false;
volatile size_t sizeCheckMin = 1160;
volatile size_t sizeCheckMax = 1160;
volatile int sectCheck = 48;
CRITICAL_SECTION memCS;
DWORD tlsIdx;
LPVOID XMemAlloc(SIZE_T dwSize, DWORD dwAllocAttributes)
{
if (!trackStarted)
{
void* p = XMemAllocDefault(dwSize, dwAllocAttributes);
size_t realSize = XMemSizeDefault(p, dwAllocAttributes);
totalAllocGen += realSize;
return p;
}
EnterCriticalSection(&memCS);
void* p = XMemAllocDefault(dwSize + 16, dwAllocAttributes);
size_t realSize = XMemSizeDefault(p, dwAllocAttributes) - 16;
if (trackEnable)
{
#if 1
int sect = ((int)TlsGetValue(tlsIdx)) & 0x3f;
*(((unsigned char*)p) + realSize) = sect;
if ((realSize >= sizeCheckMin) && (realSize <= sizeCheckMax) && ((sect == sectCheck) || (sectCheck == -1)))
{
app.DebugPrintf("Found one\n");
}
#endif
if (p)
{
totalAllocGen += realSize;
trackEnable = false;
int key = (sect << 26) | realSize;
int oldCount = allocCounts[key];
allocCounts[key] = oldCount + 1;
trackEnable = true;
}
}
LeaveCriticalSection(&memCS);
return p;
}
void* operator new (size_t size)
{
return (unsigned char*)XMemAlloc(size, MAKE_XALLOC_ATTRIBUTES(0, FALSE, TRUE, FALSE, 0, XALLOC_PHYSICAL_ALIGNMENT_DEFAULT, XALLOC_MEMPROTECT_READWRITE, FALSE, XALLOC_MEMTYPE_HEAP));
}
void operator delete (void* p)
{
XMemFree(p, MAKE_XALLOC_ATTRIBUTES(0, FALSE, TRUE, FALSE, 0, XALLOC_PHYSICAL_ALIGNMENT_DEFAULT, XALLOC_MEMPROTECT_READWRITE, FALSE, XALLOC_MEMTYPE_HEAP));
}
void WINAPI XMemFree(PVOID pAddress, DWORD dwAllocAttributes)
{
bool special = false;
if (dwAllocAttributes == 0)
{
dwAllocAttributes = MAKE_XALLOC_ATTRIBUTES(0, FALSE, TRUE, FALSE, 0, XALLOC_PHYSICAL_ALIGNMENT_DEFAULT, XALLOC_MEMPROTECT_READWRITE, FALSE, XALLOC_MEMTYPE_HEAP);
special = true;
}
if (!trackStarted)
{
size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes);
XMemFreeDefault(pAddress, dwAllocAttributes);
totalAllocGen -= realSize;
return;
}
EnterCriticalSection(&memCS);
if (pAddress)
{
size_t realSize = XMemSizeDefault(pAddress, dwAllocAttributes) - 16;
if (trackEnable)
{
int sect = *(((unsigned char*)pAddress) + realSize);
totalAllocGen -= realSize;
trackEnable = false;
int key = (sect << 26) | realSize;
int oldCount = allocCounts[key];
allocCounts[key] = oldCount - 1;
trackEnable = true;
}
XMemFreeDefault(pAddress, dwAllocAttributes);
}
LeaveCriticalSection(&memCS);
}
SIZE_T WINAPI XMemSize(
PVOID pAddress,
DWORD dwAllocAttributes
)
{
if (trackStarted)
{
return XMemSizeDefault(pAddress, dwAllocAttributes) - 16;
}
else
{
return XMemSizeDefault(pAddress, dwAllocAttributes);
}
}
void DumpMem()
{
int totalLeak = 0;
for (auto it = allocCounts.begin(); it != allocCounts.end(); it++)
{
if (it->second > 0)
{
app.DebugPrintf("%d %d %d %d\n", (it->first >> 26) & 0x3f, it->first & 0x03ffffff, it->second, (it->first & 0x03ffffff) * it->second);
totalLeak += (it->first & 0x03ffffff) * it->second;
}
}
app.DebugPrintf("Total %d\n", totalLeak);
}
void ResetMem()
{
if (!trackStarted)
{
trackEnable = true;
trackStarted = true;
totalAllocGen = 0;
InitializeCriticalSection(&memCS);
tlsIdx = TlsAlloc();
}
EnterCriticalSection(&memCS);
trackEnable = false;
allocCounts.clear();
trackEnable = true;
LeaveCriticalSection(&memCS);
}
void MemSect(int section)
{
unsigned int value = (unsigned int)TlsGetValue(tlsIdx);
if (section == 0) // pop
{
value = (value >> 6) & 0x03ffffff;
}
else
{
value = (value << 6) | section;
}
TlsSetValue(tlsIdx, (LPVOID)value);
}
void MemPixStuff()
{
const int MAX_SECT = 46;
int totals[MAX_SECT] = { 0 };
for (auto it = allocCounts.begin(); it != allocCounts.end(); it++)
{
if (it->second > 0)
{
int sect = (it->first >> 26) & 0x3f;
int bytes = it->first & 0x03ffffff;
totals[sect] += bytes * it->second;
}
}
unsigned int allSectsTotal = 0;
for (int i = 0; i < MAX_SECT; i++)
{
allSectsTotal += totals[i];
PIXAddNamedCounter(((float)totals[i]) / 1024.0f, "MemSect%d", i);
}
PIXAddNamedCounter(((float)allSectsTotal) / (4096.0f), "MemSect total pages");
}
#endif