aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
diff options
context:
space:
mode:
authorqwasdrizzel <145519042+qwasdrizzel@users.noreply.github.com>2026-03-16 21:44:26 -0500
committerGitHub <noreply@github.com>2026-03-16 21:44:26 -0500
commitce739f6045ec72127491286ea3f3f21e537c1b55 (patch)
treef33bd42a47c1b4a7b2153a7fb77127ee3b407db9 /Minecraft.Client/Windows64/Windows64_Minecraft.cpp
parent255a18fe8e9b57377975f82e2b227afe2a12eda0 (diff)
parent5a59f5d146b43811dde6a5a0245ee9875d7b5cd1 (diff)
Merge branch 'smartcmd:main' into main
Diffstat (limited to 'Minecraft.Client/Windows64/Windows64_Minecraft.cpp')
-rw-r--r--Minecraft.Client/Windows64/Windows64_Minecraft.cpp813
1 files changed, 516 insertions, 297 deletions
diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
index 2eef5f73..81430ffc 100644
--- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
+++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp
@@ -22,6 +22,9 @@
#include "..\..\Minecraft.World\net.minecraft.world.level.tile.h"
#include "..\ClientConnection.h"
+#include "..\Minecraft.h"
+#include "..\ChatScreen.h"
+#include "KeyboardMouseInput.h"
#include "..\User.h"
#include "..\..\Minecraft.World\Socket.h"
#include "..\..\Minecraft.World\ThreadName.h"
@@ -41,7 +44,15 @@
#include "..\..\Minecraft.World\compression.h"
#include "..\..\Minecraft.World\OldChunkStorage.h"
#include "Common/PostProcesser.h"
+#include "..\GameRenderer.h"
#include "Network\WinsockNetLayer.h"
+#include "Windows64_Xuid.h"
+#include "Common/UI/UI.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;
#include "Xbox/resource.h"
@@ -77,7 +88,6 @@ DWORD dwProfileSettingsA[NUM_PROFILE_VALUES]=
0,0,0,0,0
#endif
};
-
//-------------------------------------------------------------------------------------
// Time Since fAppTime is a float, we need to keep the quadword app time
// as a LARGE_INTEGER so that we don't lose precision after running
@@ -86,10 +96,20 @@ DWORD dwProfileSettingsA[NUM_PROFILE_VALUES]=
BOOL g_bWidescreen = TRUE;
+// Screen resolution — auto-detected from the monitor at startup.
+// The 3D world renders at native resolution; Flash UI is 16:9-fitted and centered
+// within each viewport (pillarboxed on ultrawide, letterboxed on tall displays).
+// ApplyScreenMode() can still override these for debug/test resolutions via launch args.
int g_iScreenWidth = 1920;
int g_iScreenHeight = 1080;
+// Real window dimensions — updated on every WM_SIZE so the 3D perspective
+// always matches the current window, even after a resize.
+int g_rScreenWidth = 1920;
+int g_rScreenHeight = 1080;
+
float g_iAspectRatio = static_cast<float>(g_iScreenWidth) / g_iScreenHeight;
+static bool g_bResizeReady = false;
char g_Win64Username[17] = { 0 };
wchar_t g_Win64UsernameW[17] = { 0 };
@@ -98,18 +118,10 @@ wchar_t g_Win64UsernameW[17] = { 0 };
static bool g_isFullscreen = false;
static WINDOWPLACEMENT g_wpPrev = { sizeof(g_wpPrev) };
-//--------------------------------------------------------------------------------------
-// Update the Aspect Ratio to support Any Aspect Ratio
-//--------------------------------------------------------------------------------------
-void UpdateAspectRatio(int width, int height)
-{
- g_iAspectRatio = static_cast<float>(width) / height;
-}
-
struct Win64LaunchOptions
{
int screenMode;
- bool serverMode;
+ bool fullscreen;
};
static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
@@ -118,17 +130,17 @@ static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
return;
dest[0] = 0;
- if (source == NULL)
+ if (source == nullptr)
return;
- WideCharToMultiByte(CP_ACP, 0, source, -1, dest, (int)destSize, NULL, NULL);
+ WideCharToMultiByte(CP_ACP, 0, source, -1, dest, static_cast<int>(destSize), nullptr, nullptr);
dest[destSize - 1] = 0;
}
// ---------- Persistent options (options.txt next to exe) ----------
static void GetOptionsFilePath(char *out, size_t outSize)
{
- GetModuleFileNameA(NULL, out, (DWORD)outSize);
+ GetModuleFileNameA(nullptr, out, static_cast<DWORD>(outSize));
char *p = strrchr(out, '\\');
if (p) *(p + 1) = '\0';
strncat_s(out, outSize, "options.txt", _TRUNCATE);
@@ -194,17 +206,13 @@ static Win64LaunchOptions ParseLaunchOptions()
{
Win64LaunchOptions options = {};
options.screenMode = 0;
- options.serverMode = false;
g_Win64MultiplayerJoin = false;
g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
- g_Win64DedicatedServer = false;
- g_Win64DedicatedServerPort = WIN64_NET_DEFAULT_PORT;
- g_Win64DedicatedServerBindIP[0] = 0;
int argc = 0;
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
- if (argv == NULL)
+ if (argv == nullptr)
return options;
if (argc > 1 && lstrlenW(argv[1]) == 1)
@@ -215,17 +223,6 @@ static Win64LaunchOptions ParseLaunchOptions()
for (int i = 1; i < argc; ++i)
{
- if (_wcsicmp(argv[i], L"-server") == 0)
- {
- options.serverMode = true;
- break;
- }
- }
-
- g_Win64DedicatedServer = options.serverMode;
-
- for (int i = 1; i < argc; ++i)
- {
if (_wcsicmp(argv[i], L"-name") == 0 && (i + 1) < argc)
{
CopyWideArgToAnsi(argv[++i], g_Win64Username, sizeof(g_Win64Username));
@@ -234,64 +231,26 @@ static Win64LaunchOptions ParseLaunchOptions()
{
char ipBuf[256];
CopyWideArgToAnsi(argv[++i], ipBuf, sizeof(ipBuf));
- if (options.serverMode)
- {
- strncpy_s(g_Win64DedicatedServerBindIP, sizeof(g_Win64DedicatedServerBindIP), ipBuf, _TRUNCATE);
- }
- else
- {
- strncpy_s(g_Win64MultiplayerIP, sizeof(g_Win64MultiplayerIP), ipBuf, _TRUNCATE);
- g_Win64MultiplayerJoin = true;
- }
+ strncpy_s(g_Win64MultiplayerIP, sizeof(g_Win64MultiplayerIP), ipBuf, _TRUNCATE);
+ g_Win64MultiplayerJoin = true;
}
else if (_wcsicmp(argv[i], L"-port") == 0 && (i + 1) < argc)
{
- wchar_t* endPtr = NULL;
- long port = wcstol(argv[++i], &endPtr, 10);
+ wchar_t* endPtr = nullptr;
+ const long port = wcstol(argv[++i], &endPtr, 10);
if (endPtr != argv[i] && *endPtr == 0 && port > 0 && port <= 65535)
{
- if (options.serverMode)
- g_Win64DedicatedServerPort = (int)port;
- else
- g_Win64MultiplayerPort = (int)port;
+ g_Win64MultiplayerPort = static_cast<int>(port);
}
}
+ else if (_wcsicmp(argv[i], L"-fullscreen") == 0)
+ options.fullscreen = true;
}
LocalFree(argv);
return options;
}
-static BOOL WINAPI HeadlessServerCtrlHandler(DWORD ctrlType)
-{
- switch (ctrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- app.m_bShutdown = true;
- MinecraftServer::HaltServer();
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-static void SetupHeadlessServerConsole()
-{
- if (AllocConsole())
- {
- FILE* stream = NULL;
- freopen_s(&stream, "CONIN$", "r", stdin);
- freopen_s(&stream, "CONOUT$", "w", stdout);
- freopen_s(&stream, "CONOUT$", "w", stderr);
- SetConsoleTitleA("Minecraft Server");
- }
-
- SetConsoleCtrlHandler(HeadlessServerCtrlHandler, TRUE);
-}
-
void DefineActions(void)
{
// The app needs to define the actions required, and the possible mappings for these
@@ -483,7 +442,7 @@ HRESULT InitD3D( IDirect3DDevice9 **ppDevice,
return pD3D->CreateDevice(
0,
D3DDEVTYPE_HAL,
- NULL,
+ nullptr,
D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_BUFFER_2_FRAMES,
pd3dPP,
ppDevice );
@@ -501,16 +460,16 @@ void MemSect(int sect)
}
#endif
-HINSTANCE g_hInst = NULL;
-HWND g_hWnd = NULL;
+HINSTANCE g_hInst = nullptr;
+HWND g_hWnd = nullptr;
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
-ID3D11Device* g_pd3dDevice = NULL;
-ID3D11DeviceContext* g_pImmediateContext = NULL;
-IDXGISwapChain* g_pSwapChain = NULL;
-ID3D11RenderTargetView* g_pRenderTargetView = NULL;
-ID3D11DepthStencilView* g_pDepthStencilView = NULL;
-ID3D11Texture2D* g_pDepthStencilBuffer = NULL;
+ID3D11Device* g_pd3dDevice = nullptr;
+ID3D11DeviceContext* g_pImmediateContext = nullptr;
+IDXGISwapChain* g_pSwapChain = nullptr;
+ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
+ID3D11DepthStencilView* g_pDepthStencilView = nullptr;
+ID3D11Texture2D* g_pDepthStencilBuffer = nullptr;
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
@@ -523,6 +482,11 @@ ID3D11Texture2D* g_pDepthStencilBuffer = NULL;
// WM_SIZE - handle resizing logic to support Any Aspect Ratio
//
//
+static bool ResizeD3D(int newW, int newH); // forward declaration
+static bool g_bInSizeMove = false; // true while the user is dragging the window border
+static int g_pendingResizeW = 0; // deferred resize dimensions
+static int g_pendingResizeH = 0;
+
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
@@ -568,14 +532,30 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_CHAR:
// Buffer typed characters so UIScene_Keyboard can dispatch them to the Iggy Flash player
if (wParam >= 0x20 || wParam == 0x08 || wParam == 0x0D) // printable chars + backspace + enter
- g_KBMInput.OnChar((wchar_t)wParam);
+ g_KBMInput.OnChar(static_cast<wchar_t>(wParam));
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
- int vk = (int)wParam;
- if (lParam & 0x40000000) break; // ignore auto-repeat
+ int vk = static_cast<int>(wParam);
+ if ((lParam & 0x40000000) && vk != VK_LEFT && vk != VK_RIGHT && vk != VK_BACK)
+ break;
+#ifdef _WINDOWS64
+ const Minecraft* pm = Minecraft::GetInstance();
+ ChatScreen* chat = pm && pm->screen ? dynamic_cast<ChatScreen*>(pm->screen) : nullptr;
+ if (chat)
+ {
+ if (vk == 'V' && (GetKeyState(VK_CONTROL) & 0x8000))
+ { chat->handlePasteRequest(); break; }
+ if ((vk == VK_UP || vk == VK_DOWN) && !(lParam & 0x40000000))
+ { if (vk == VK_UP) chat->handleHistoryUp(); else chat->handleHistoryDown(); break; }
+ if (vk >= '1' && vk <= '9') // Prevent hotkey conflicts
+ break;
+ if (vk == VK_SHIFT)
+ break;
+ }
+#endif
if (vk == VK_SHIFT)
vk = (MapVirtualKey((lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX) == VK_RSHIFT) ? VK_RSHIFT : VK_LSHIFT;
else if (vk == VK_CONTROL)
@@ -583,12 +563,12 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
else if (vk == VK_MENU)
vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU;
g_KBMInput.OnKeyDown(vk);
- break;
+ return DefWindowProc(hWnd, message, wParam, lParam);
}
case WM_KEYUP:
case WM_SYSKEYUP:
{
- int vk = (int)wParam;
+ int vk = static_cast<int>(wParam);
if (vk == VK_SHIFT)
vk = (MapVirtualKey((lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX) == VK_RSHIFT) ? VK_RSHIFT : VK_LSHIFT;
else if (vk == VK_CONTROL)
@@ -629,13 +609,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
case WM_INPUT:
{
UINT dwSize = 0;
- GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
+ GetRawInputData((HRAWINPUT)lParam, RID_INPUT, nullptr, &dwSize, sizeof(RAWINPUTHEADER));
if (dwSize > 0 && dwSize <= 256)
{
BYTE rawBuffer[256];
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, rawBuffer, &dwSize, sizeof(RAWINPUTHEADER)) == dwSize)
{
- RAWINPUT* raw = (RAWINPUT*)rawBuffer;
+ const RAWINPUT* raw = (RAWINPUT*)rawBuffer;
if (raw->header.dwType == RIM_TYPEMOUSE)
{
g_KBMInput.OnRawMouseDelta(raw->data.mouse.lLastX, raw->data.mouse.lLastY);
@@ -644,9 +624,40 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
}
}
break;
+ case WM_ENTERSIZEMOVE:
+ g_bInSizeMove = true;
+ break;
+
+ case WM_EXITSIZEMOVE:
+ g_bInSizeMove = false;
+ if (g_pendingResizeW > 0 && g_pendingResizeH > 0)
+ {
+ // g_rScreenWidth/Height updated inside ResizeD3D to backbuffer dims
+ ResizeD3D(g_pendingResizeW, g_pendingResizeH);
+ g_pendingResizeW = 0;
+ g_pendingResizeH = 0;
+ }
+ break;
+
case WM_SIZE:
{
- UpdateAspectRatio(LOWORD(lParam), HIWORD(lParam));
+ int newW = LOWORD(lParam);
+ int newH = HIWORD(lParam);
+ if (newW > 0 && newH > 0)
+ {
+ if (g_bInSizeMove)
+ {
+ // Just store the latest size, resize when dragging ends
+ g_pendingResizeW = newW;
+ g_pendingResizeH = newH;
+ }
+ else
+ {
+ // Immediate resize (maximize, programmatic resize, etc.)
+ // g_rScreenWidth/Height updated inside ResizeD3D to backbuffer dims
+ ResizeD3D(newW, newH);
+ }
+ }
}
break;
default:
@@ -672,7 +683,7 @@ ATOM MyRegisterClass(HINSTANCE hInstance)
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, "Minecraft");
- wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = "Minecraft";
wcex.lpszClassName = "MinecraftClass";
@@ -695,7 +706,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
g_hInst = hInstance; // Store instance handle in our global variable
- RECT wr = {0, 0, g_iScreenWidth, g_iScreenHeight}; // set the size, but not the position
+ RECT wr = {0, 0, g_rScreenWidth, g_rScreenHeight}; // set the size, but not the position
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
g_hWnd = CreateWindow( "MinecraftClass",
@@ -705,10 +716,10 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
0,
wr.right - wr.left, // width of the window
wr.bottom - wr.top, // height of the window
- NULL,
- NULL,
+ nullptr,
+ nullptr,
hInstance,
- NULL);
+ nullptr);
if (!g_hWnd)
{
@@ -781,8 +792,8 @@ HRESULT InitDevice()
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
//app.DebugPrintf("width: %d, height: %d\n", width, height);
- width = g_iScreenWidth;
- height = g_iScreenHeight;
+ width = g_rScreenWidth;
+ height = g_rScreenHeight;
//app.DebugPrintf("width: %d, height: %d\n", width, height);
UINT createDeviceFlags = 0;
@@ -814,7 +825,7 @@ HRESULT InitDevice()
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
- sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
@@ -823,7 +834,7 @@ HRESULT InitDevice()
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
g_driverType = driverTypes[driverTypeIndex];
- hr = D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
+ hr = D3D11CreateDeviceAndSwapChain( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
if( HRESULT_SUCCEEDED( hr ) )
break;
@@ -832,7 +843,7 @@ HRESULT InitDevice()
return hr;
// Create a render target view
- ID3D11Texture2D* pBackBuffer = NULL;
+ ID3D11Texture2D* pBackBuffer = nullptr;
hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );
if( FAILED( hr ) )
return hr;
@@ -852,7 +863,7 @@ HRESULT InitDevice()
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
- hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer);
+ hr = g_pd3dDevice->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencilBuffer);
D3D11_DEPTH_STENCIL_VIEW_DESC descDSView;
ZeroMemory(&descDSView, sizeof(descDSView));
@@ -862,7 +873,7 @@ HRESULT InitDevice()
hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &descDSView, &g_pDepthStencilView);
- hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );
+ hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView );
pBackBuffer->Release();
if( FAILED( hr ) )
return hr;
@@ -871,8 +882,8 @@ HRESULT InitDevice()
// Setup the viewport
D3D11_VIEWPORT vp;
- vp.Width = (FLOAT)width;
- vp.Height = (FLOAT)height;
+ vp.Width = static_cast<FLOAT>(width);
+ vp.Height = static_cast<FLOAT>(height);
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
@@ -892,18 +903,293 @@ HRESULT InitDevice()
void Render()
{
// Just clear the backbuffer
- float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
+ const float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
g_pSwapChain->Present( 0, 0 );
}
//--------------------------------------------------------------------------------------
+// Rebuild D3D11 resources after a window resize
+//--------------------------------------------------------------------------------------
+static bool ResizeD3D(int newW, int newH)
+{
+ if (newW <= 0 || newH <= 0) return false;
+ if (!g_pSwapChain) return false;
+ if (!g_bResizeReady) return false;
+
+ int bbW = newW;
+ int bbH = newH;
+
+ // InternalRenderManager member offsets (from decompiled Renderer.h):
+ // 0x10 m_pDevice (ID3D11Device*)
+ // 0x18 m_pDeviceContext (ID3D11DeviceContext*)
+ // 0x20 m_pSwapChain (IDXGISwapChain*)
+ // 0x28 renderTargetView (ID3D11RenderTargetView*) — backbuffer RTV
+ // 0x50 renderTargetShaderResourceView (ID3D11ShaderResourceView*)
+ // 0x98 depthStencilView (ID3D11DepthStencilView*)
+ // 0x5138 backBufferWidth (DWORD) — used by StartFrame() for viewport
+ // 0x513C backBufferHeight (DWORD) — used by StartFrame() for viewport
+ //
+ // Strategy: destroy old swap chain, create new one, patch Renderer's internal
+ // pointers directly. This avoids both ResizeBuffers (outstanding ref issues)
+ // and Initialise() (which wipes the texture table via memset).
+ // The Renderer's old RTV/SRV/DSV are intentionally NOT released — they become
+ // orphaned with the old swap chain. Tiny leak, but avoids fighting unknown refs.
+ char* pRM = (char*)&InternalRenderManager;
+ ID3D11RenderTargetView** ppRM_RTV = (ID3D11RenderTargetView**)(pRM + 0x28);
+ ID3D11ShaderResourceView** ppRM_SRV = (ID3D11ShaderResourceView**)(pRM + 0x50);
+ ID3D11DepthStencilView** ppRM_DSV = (ID3D11DepthStencilView**)(pRM + 0x98);
+ IDXGISwapChain** ppRM_SC = (IDXGISwapChain**)(pRM + 0x20);
+ DWORD* pRM_BBWidth = (DWORD*)(pRM + 0x5138);
+ DWORD* pRM_BBHeight = (DWORD*)(pRM + 0x513C);
+
+ // Verify offsets by checking device and swap chain pointers
+ ID3D11Device** ppRM_Device = (ID3D11Device**)(pRM + 0x10);
+ if (*ppRM_Device != g_pd3dDevice || *ppRM_SC != g_pSwapChain)
+ {
+ app.DebugPrintf("[RESIZE] ERROR: RenderManager offset verification failed! "
+ "device=%p (expected %p) swapchain=%p (expected %p)\n",
+ *ppRM_Device, g_pd3dDevice, *ppRM_SC, g_pSwapChain);
+ return false;
+ }
+
+ // Cross-check backbuffer dimension offsets against swap chain desc
+ DXGI_SWAP_CHAIN_DESC oldScDesc;
+ g_pSwapChain->GetDesc(&oldScDesc);
+ bool bbDimsValid = (*pRM_BBWidth == oldScDesc.BufferDesc.Width &&
+ *pRM_BBHeight == oldScDesc.BufferDesc.Height);
+ if (!bbDimsValid)
+ {
+ app.DebugPrintf("[RESIZE] WARNING: backBuffer dim offsets wrong: "
+ "stored=%ux%u, swapchain=%ux%u\n",
+ *pRM_BBWidth, *pRM_BBHeight, oldScDesc.BufferDesc.Width, oldScDesc.BufferDesc.Height);
+ }
+
+ RenderManager.Suspend();
+ while (!RenderManager.Suspended()) { Sleep(1); }
+
+ PostProcesser::GetInstance().Cleanup();
+
+ g_pImmediateContext->ClearState();
+ g_pImmediateContext->Flush();
+
+ // Release OUR views and depth buffer
+ if (g_pRenderTargetView) { g_pRenderTargetView->Release(); g_pRenderTargetView = NULL; }
+ if (g_pDepthStencilView) { g_pDepthStencilView->Release(); g_pDepthStencilView = NULL; }
+ if (g_pDepthStencilBuffer) { g_pDepthStencilBuffer->Release(); g_pDepthStencilBuffer = NULL; }
+
+ gdraw_D3D11_PreReset();
+
+ // Get IDXGIFactory from the existing device BEFORE destroying the old swap chain.
+ // If anything fails before we have a new swap chain, we abort without destroying
+ // the old one — leaving the Renderer in a valid (old-size) state.
+ IDXGISwapChain* pOldSwapChain = g_pSwapChain;
+ bool success = false;
+ HRESULT hr;
+
+ IDXGIDevice* dxgiDevice = NULL;
+ IDXGIAdapter* dxgiAdapter = NULL;
+ IDXGIFactory* dxgiFactory = NULL;
+ hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
+ if (FAILED(hr)) goto postReset;
+ hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter);
+ if (FAILED(hr)) { dxgiDevice->Release(); goto postReset; }
+ hr = dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory);
+ dxgiAdapter->Release();
+ dxgiDevice->Release();
+ if (FAILED(hr)) goto postReset;
+
+ // Create new swap chain at backbuffer size
+ {
+ DXGI_SWAP_CHAIN_DESC sd = {};
+ sd.BufferCount = 1;
+ sd.BufferDesc.Width = bbW;
+ sd.BufferDesc.Height = bbH;
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.BufferDesc.RefreshRate.Numerator = 60;
+ sd.BufferDesc.RefreshRate.Denominator = 1;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
+ sd.OutputWindow = g_hWnd;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = 0;
+ sd.Windowed = TRUE;
+
+ IDXGISwapChain* pNewSwapChain = NULL;
+ hr = dxgiFactory->CreateSwapChain(g_pd3dDevice, &sd, &pNewSwapChain);
+ dxgiFactory->Release();
+ if (FAILED(hr) || pNewSwapChain == NULL)
+ {
+ app.DebugPrintf("[RESIZE] CreateSwapChain FAILED hr=0x%08X — keeping old swap chain\n", (unsigned)hr);
+ goto postReset;
+ }
+
+ // New swap chain created successfully — NOW destroy the old one.
+ // The Renderer's internal RTV/SRV still reference the old backbuffer —
+ // those COM objects become orphaned (tiny leak, harmless). We DON'T
+ // release them because unknown code may also hold refs.
+ pOldSwapChain->Release();
+ g_pSwapChain = pNewSwapChain;
+ }
+
+ // Patch Renderer's swap chain pointer
+ *ppRM_SC = g_pSwapChain;
+
+ // Create render target views from new backbuffer
+ {
+ ID3D11Texture2D* pBackBuffer = NULL;
+ hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
+ if (FAILED(hr)) goto postReset;
+
+ // Our RTV
+ hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
+ if (FAILED(hr)) { pBackBuffer->Release(); goto postReset; }
+
+ // Renderer's internal RTV (offset 0x28)
+ hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, ppRM_RTV);
+ if (FAILED(hr)) { pBackBuffer->Release(); goto postReset; }
+
+ // Renderer's SRV: separate texture matching backbuffer dims (used by CaptureThumbnail)
+ D3D11_TEXTURE2D_DESC backDesc = {};
+ pBackBuffer->GetDesc(&backDesc);
+ pBackBuffer->Release();
+
+ D3D11_TEXTURE2D_DESC srvDesc = backDesc;
+ srvDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+ ID3D11Texture2D* srvTexture = NULL;
+ hr = g_pd3dDevice->CreateTexture2D(&srvDesc, NULL, &srvTexture);
+ if (SUCCEEDED(hr))
+ {
+ hr = g_pd3dDevice->CreateShaderResourceView(srvTexture, NULL, ppRM_SRV);
+ srvTexture->Release();
+ }
+ if (FAILED(hr)) goto postReset;
+ }
+
+ // Recreate depth stencil at backbuffer size
+ {
+ D3D11_TEXTURE2D_DESC descDepth = {};
+ descDepth.Width = bbW;
+ descDepth.Height = bbH;
+ descDepth.MipLevels = 1;
+ descDepth.ArraySize = 1;
+ descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ descDepth.SampleDesc.Count = 1;
+ descDepth.SampleDesc.Quality = 0;
+ descDepth.Usage = D3D11_USAGE_DEFAULT;
+ descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ hr = g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer);
+ if (FAILED(hr)) goto postReset;
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC descDSView = {};
+ descDSView.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ descDSView.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &descDSView, &g_pDepthStencilView);
+ if (FAILED(hr)) goto postReset;
+ }
+
+ // Patch Renderer's DSV (AddRef because both we and the Renderer reference it)
+ g_pDepthStencilView->AddRef();
+ *ppRM_DSV = g_pDepthStencilView;
+
+ // Update Renderer's cached backbuffer dimensions (StartFrame uses these for viewport)
+ if (bbDimsValid)
+ {
+ *pRM_BBWidth = (DWORD)bbW;
+ *pRM_BBHeight = (DWORD)bbH;
+ }
+
+ // Rebind render targets and viewport
+ g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
+ {
+ D3D11_VIEWPORT vp = {};
+ vp.Width = (FLOAT)bbW;
+ vp.Height = (FLOAT)bbH;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ g_pImmediateContext->RSSetViewports(1, &vp);
+ }
+
+ ui.updateRenderTargets(g_pRenderTargetView, g_pDepthStencilView);
+ ui.updateScreenSize(bbW, bbH);
+
+ // Track actual backbuffer dimensions for the rest of the engine
+ g_rScreenWidth = bbW;
+ g_rScreenHeight = bbH;
+
+ success = true;
+
+postReset:
+ if (!success && g_pSwapChain != NULL)
+ {
+ // Failure recovery: recreate our views from whatever swap chain survived
+ // so ui.m_pRenderTargetView / m_pDepthStencilView don't dangle.
+ DXGI_SWAP_CHAIN_DESC recoveryDesc;
+ g_pSwapChain->GetDesc(&recoveryDesc);
+ int recW = (int)recoveryDesc.BufferDesc.Width;
+ int recH = (int)recoveryDesc.BufferDesc.Height;
+
+ if (g_pRenderTargetView == NULL)
+ {
+ ID3D11Texture2D* pBB = NULL;
+ if (SUCCEEDED(g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBB)))
+ {
+ g_pd3dDevice->CreateRenderTargetView(pBB, NULL, &g_pRenderTargetView);
+ pBB->Release();
+ }
+ }
+ if (g_pDepthStencilView == NULL)
+ {
+ D3D11_TEXTURE2D_DESC dd = {};
+ dd.Width = recW; dd.Height = recH; dd.MipLevels = 1; dd.ArraySize = 1;
+ dd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ dd.SampleDesc.Count = 1; dd.Usage = D3D11_USAGE_DEFAULT;
+ dd.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ if (g_pDepthStencilBuffer == NULL)
+ g_pd3dDevice->CreateTexture2D(&dd, NULL, &g_pDepthStencilBuffer);
+ if (g_pDepthStencilBuffer != NULL)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvd = {};
+ dsvd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, &dsvd, &g_pDepthStencilView);
+ }
+ }
+ if (g_pRenderTargetView != NULL)
+ g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
+
+ ui.updateRenderTargets(g_pRenderTargetView, g_pDepthStencilView);
+
+ // If the surviving swap chain is the OLD one, dims are unchanged.
+ // If it's the NEW one (partial failure after swap), update to new dims.
+ if (g_pSwapChain != pOldSwapChain)
+ {
+ g_rScreenWidth = recW;
+ g_rScreenHeight = recH;
+ ui.updateScreenSize(recW, recH);
+ }
+
+ app.DebugPrintf("[RESIZE] FAILED but recovered views at %dx%d\n", g_rScreenWidth, g_rScreenHeight);
+ }
+
+ gdraw_D3D11_PostReset();
+ gdraw_D3D11_SetRendertargetSize(g_rScreenWidth, g_rScreenHeight);
+ if (success)
+ IggyFlushInstalledFonts();
+ RenderManager.Resume();
+
+ if (success)
+ PostProcesser::GetInstance().Init();
+
+ return success;
+}
+
+//--------------------------------------------------------------------------------------
// Toggle borderless fullscreen
//--------------------------------------------------------------------------------------
void ToggleFullscreen()
{
- DWORD dwStyle = GetWindowLong(g_hWnd, GWL_STYLE);
+ const DWORD dwStyle = GetWindowLong(g_hWnd, GWL_STYLE);
if (!g_isFullscreen)
{
MONITORINFO mi = { sizeof(mi) };
@@ -922,7 +1208,7 @@ void ToggleFullscreen()
{
SetWindowLong(g_hWnd, GWL_STYLE, dwStyle | WS_OVERLAPPEDWINDOW);
SetWindowPlacement(g_hWnd, &g_wpPrev);
- SetWindowPos(g_hWnd, NULL, 0, 0, 0, 0,
+ SetWindowPos(g_hWnd, nullptr, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
}
g_isFullscreen = !g_isFullscreen;
@@ -939,6 +1225,8 @@ void CleanupDevice()
{
if( g_pImmediateContext ) g_pImmediateContext->ClearState();
+ if( g_pDepthStencilView ) g_pDepthStencilView->Release();
+ if( g_pDepthStencilBuffer ) g_pDepthStencilBuffer->Release();
if( g_pRenderTargetView ) g_pRenderTargetView->Release();
if( g_pSwapChain ) g_pSwapChain->Release();
if( g_pImmediateContext ) g_pImmediateContext->Release();
@@ -952,7 +1240,7 @@ static Minecraft* InitialiseMinecraftRuntime()
RenderManager.Initialise(g_pd3dDevice, g_pSwapChain);
app.loadStringTable();
- ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_iScreenWidth, g_iScreenHeight);
+ ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_rScreenWidth, g_rScreenHeight);
InputManager.Initialise(1, 3, MINECRAFT_ACTION_MAX, ACTION_MAX_MENU);
g_KBMInput.Init();
@@ -975,7 +1263,7 @@ static Minecraft* InitialiseMinecraftRuntime()
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++)
{
- IQNet::m_player[i].m_smallId = (BYTE)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);
@@ -997,8 +1285,8 @@ static Minecraft* InitialiseMinecraftRuntime()
Minecraft::main();
Minecraft* pMinecraft = Minecraft::GetInstance();
- if (pMinecraft == NULL)
- return NULL;
+ if (pMinecraft == nullptr)
+ return nullptr;
app.InitGameSettings();
app.InitialiseTips();
@@ -1006,161 +1294,6 @@ static Minecraft* InitialiseMinecraftRuntime()
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 != NULL)
- {
- server->handleConsoleInput(command, server);
- }
- }
-
- return 0;
-}
-
-static int RunHeadlessServer()
-{
- SetupHeadlessServerConsole();
-
- Settings serverSettings(new File(L"server.properties"));
- wstring configuredBindIp = serverSettings.getString(L"server-ip", L"");
-
- const char* bindIp = "*";
- 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);
-
- printf("Starting headless server on %s:%d\n", bindIp, port);
- fflush(stdout);
-
- Minecraft* pMinecraft = InitialiseMinecraftRuntime();
- if (pMinecraft == NULL)
- {
- fprintf(stderr, "Failed to initialise the Minecraft runtime.\n");
- return 1;
- }
-
- app.SetGameHostOption(eGameHostOption_Difficulty, serverSettings.getInt(L"difficulty", 1));
- app.SetGameHostOption(eGameHostOption_Gamertags, 1);
- app.SetGameHostOption(eGameHostOption_GameType, serverSettings.getInt(L"gamemode", 0));
- app.SetGameHostOption(eGameHostOption_LevelType, 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, 1);
- app.SetGameHostOption(eGameHostOption_KeepInventory, 0);
- app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1);
- app.SetGameHostOption(eGameHostOption_DoMobLoot, 1);
- app.SetGameHostOption(eGameHostOption_DoTileDrops, 1);
- app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1);
- app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1);
-
- MinecraftServer::resetFlags();
- g_NetworkManager.HostGame(0, false, true, MINECRAFT_NET_MAX_PLAYERS, 0);
-
- if (!WinsockNetLayer::IsActive())
- {
- fprintf(stderr, "Failed to bind the server socket on %s:%d.\n", bindIp, port);
- return 1;
- }
-
- g_NetworkManager.FakeLocalPlayerJoined();
-
- NetworkGameInitData* param = new NetworkGameInitData();
- param->seed = 0;
- 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())
- {
- fprintf(stderr, "The server halted during startup.\n");
- g_NetworkManager.LeaveGame(false);
- return 1;
- }
-
- app.SetGameStarted(true);
- g_NetworkManager.DoWork();
-
- printf("Server ready on %s:%d\n", bindIp, port);
- printf("Type 'help' for server commands.\n");
- fflush(stdout);
-
- C4JThread* consoleThread = new C4JThread(&HeadlessServerConsoleThreadProc, NULL, "Server console", 128 * 1024);
- consoleThread->Run();
-
- MSG msg = { 0 };
- while (WM_QUIT != msg.message && !app.m_bShutdown && !MinecraftServer::serverHalted())
- {
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- continue;
- }
-
- app.UpdateTime();
- ProfileManager.Tick();
- StorageManager.Tick();
- RenderManager.Tick();
- ui.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 0;
-}
-
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
@@ -1172,19 +1305,23 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
// 4J-Win64: set CWD to exe dir so asset paths resolve correctly
{
char szExeDir[MAX_PATH] = {};
- GetModuleFileNameA(NULL, szExeDir, MAX_PATH);
+ GetModuleFileNameA(nullptr, szExeDir, MAX_PATH);
char *pSlash = strrchr(szExeDir, '\\');
if (pSlash) { *(pSlash + 1) = '\0'; SetCurrentDirectoryA(szExeDir); }
}
// Declare DPI awareness so GetSystemMetrics returns physical pixels
SetProcessDPIAware();
- g_iScreenWidth = GetSystemMetrics(SM_CXSCREEN);
- g_iScreenHeight = GetSystemMetrics(SM_CYSCREEN);
+ // Use the native monitor resolution for the window and swap chain,
+ // but keep g_iScreenWidth/Height at 1920x1080 for logical resolution
+ // (SWF selection, ortho projection, game logic). The real window
+ // dimensions are tracked by g_rScreenWidth/g_rScreenHeight.
+ g_rScreenWidth = GetSystemMetrics(SM_CXSCREEN);
+ g_rScreenHeight = GetSystemMetrics(SM_CYSCREEN);
// Load username from username.txt
char exePath[MAX_PATH] = {};
- GetModuleFileNameA(NULL, exePath, MAX_PATH);
+ GetModuleFileNameA(nullptr, exePath, MAX_PATH);
char *lastSlash = strrchr(exePath, '\\');
if (lastSlash)
{
@@ -1200,7 +1337,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
char buf[128] = {};
if (fgets(buf, sizeof(buf), f))
{
- int len = (int)strlen(buf);
+ int len = static_cast<int>(strlen(buf));
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r' || buf[len - 1] == ' '))
{
buf[--len] = '\0';
@@ -1215,9 +1352,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
// Load stuff from launch options, including username
- Win64LaunchOptions launchOptions = ParseLaunchOptions();
+ const Win64LaunchOptions launchOptions = ParseLaunchOptions();
ApplyScreenMode(launchOptions.screenMode);
+ // Ensure uid.dat exists from startup (before any multiplayer/login path).
+ Win64Xuid::ResolvePersistentXuid();
+
// If no username, let's fall back
if (g_Win64Username[0] == 0)
{
@@ -1227,11 +1367,77 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
MultiByteToWideChar(CP_ACP, 0, g_Win64Username, -1, g_Win64UsernameW, 17);
+ // convert servers.txt to servers.db
+ if (GetFileAttributesA("servers.txt") != INVALID_FILE_ATTRIBUTES &&
+ GetFileAttributesA("servers.db") == INVALID_FILE_ATTRIBUTES)
+ {
+ FILE* txtFile = nullptr;
+ if (fopen_s(&txtFile, "servers.txt", "r") == 0 && txtFile)
+ {
+ struct MigEntry { std::string ip; uint16_t port; std::string name; };
+ std::vector<MigEntry> migEntries;
+ char line[512];
+
+ while (fgets(line, sizeof(line), txtFile))
+ {
+ int l = (int)strlen(line);
+ while (l > 0 && (line[l - 1] == '\n' || line[l - 1] == '\r' || line[l - 1] == ' '))
+ line[--l] = '\0';
+ if (l == 0) continue;
+
+ std::string srvIP = line;
+
+ if (!fgets(line, sizeof(line), txtFile)) break;
+ l = (int)strlen(line);
+ while (l > 0 && (line[l - 1] == '\n' || line[l - 1] == '\r' || line[l - 1] == ' '))
+ line[--l] = '\0';
+ uint16_t srvPort = (uint16_t)atoi(line);
+
+ std::string srvName;
+ if (fgets(line, sizeof(line), txtFile))
+ {
+ l = (int)strlen(line);
+ while (l > 0 && (line[l - 1] == '\n' || line[l - 1] == '\r' || line[l - 1] == ' '))
+ line[--l] = '\0';
+ srvName = line;
+ }
+
+ if (!srvIP.empty() && srvPort > 0)
+ migEntries.push_back({srvIP, srvPort, srvName});
+ }
+ fclose(txtFile);
+
+ if (!migEntries.empty())
+ {
+ FILE* dbFile = nullptr;
+ if (fopen_s(&dbFile, "servers.db", "wb") == 0 && dbFile)
+ {
+ fwrite("MCSV", 1, 4, dbFile);
+ uint32_t ver = 1;
+ uint32_t cnt = (uint32_t)migEntries.size();
+ fwrite(&ver, sizeof(uint32_t), 1, dbFile);
+ fwrite(&cnt, sizeof(uint32_t), 1, dbFile);
+ for (size_t i = 0; i < migEntries.size(); i++)
+ {
+ uint16_t ipLen = (uint16_t)migEntries[i].ip.length();
+ fwrite(&ipLen, sizeof(uint16_t), 1, dbFile);
+ fwrite(migEntries[i].ip.c_str(), 1, ipLen, dbFile);
+ fwrite(&migEntries[i].port, sizeof(uint16_t), 1, dbFile);
+ uint16_t nameLen = (uint16_t)migEntries[i].name.length();
+ fwrite(&nameLen, sizeof(uint16_t), 1, dbFile);
+ fwrite(migEntries[i].name.c_str(), 1, nameLen, dbFile);
+ }
+ fclose(dbFile);
+ }
+ }
+ }
+ }
+
// Initialize global strings
MyRegisterClass(hInstance);
// Perform application initialization:
- if (!InitInstance (hInstance, launchOptions.serverMode ? SW_HIDE : nCmdShow))
+ if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
@@ -1245,24 +1451,17 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
// Restore fullscreen state from previous session
- if (LoadFullscreenOption() && !g_isFullscreen)
+ if (LoadFullscreenOption() && !g_isFullscreen || launchOptions.fullscreen)
{
ToggleFullscreen();
}
- if (launchOptions.serverMode)
- {
- int serverResult = RunHeadlessServer();
- CleanupDevice();
- return serverResult;
- }
-
#if 0
// Main message loop
MSG msg = {0};
while( WM_QUIT != msg.message )
{
- if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
+ if( PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
@@ -1310,11 +1509,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
#endif
Minecraft *pMinecraft = InitialiseMinecraftRuntime();
- if (pMinecraft == NULL)
+ if (pMinecraft == nullptr)
{
CleanupDevice();
return 1;
}
+ g_bResizeReady = true;
//app.TemporaryCreateGameStart();
@@ -1346,7 +1546,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
{
g_KBMInput.Tick();
- while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
+ while( PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
@@ -1354,6 +1554,14 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
if (msg.message == WM_QUIT) break;
+ // When the window is minimized (e.g. "Show Desktop"), skip rendering entirely
+ // to avoid pegging the GPU at 100% presenting to a non-visible swap chain.
+ if (IsIconic(g_hWnd))
+ {
+ Sleep(100);
+ continue;
+ }
+
RenderManager.StartFrame();
#if 0
if(pMinecraft->soundEngine->isStreamingWavebankReady() &&
@@ -1379,7 +1587,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
// Detect KBM vs controller input mode
if (InputManager.IsPadConnected(0))
{
- bool controllerUsed = InputManager.ButtonPressed(0) ||
+ const bool controllerUsed = InputManager.ButtonPressed(0) ||
InputManager.GetJoypadStick_LX(0, false) != 0.0f ||
InputManager.GetJoypadStick_LY(0, false) != 0.0f ||
InputManager.GetJoypadStick_RX(0, false) != 0.0f ||
@@ -1441,7 +1649,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
else
{
MemSect(28);
- pMinecraft->soundEngine->tick(NULL, 0.0f);
+ pMinecraft->soundEngine->tick(nullptr, 0.0f);
MemSect(0);
pMinecraft->textures->tick(true,false);
IntCache::Reset();
@@ -1488,6 +1696,9 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
#endif
ui.tick();
ui.render();
+
+ pMinecraft->gameRenderer->ApplyGammaPostProcess();
+
#if 0
app.HandleButtonPresses();
@@ -1535,7 +1746,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
// Update mouse grab: grab when in-game and no menu is open
{
static bool altToggleSuppressCapture = false;
- bool shouldCapture = app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL;
+ const bool shouldCapture = app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == nullptr;
// Left Alt key toggles capture on/off for debugging
if (g_KBMInput.IsKeyPressed(VK_LMENU) || g_KBMInput.IsKeyPressed(VK_RMENU))
{
@@ -1554,18 +1765,18 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
// F1 toggles the HUD
- if (g_KBMInput.IsKeyPressed(VK_F1))
+ if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_TOGGLE_HUD))
{
- int primaryPad = ProfileManager.GetPrimaryPad();
- unsigned char displayHud = app.GetGameSettings(primaryPad, eGameSetting_DisplayHUD);
+ const int primaryPad = ProfileManager.GetPrimaryPad();
+ const unsigned char displayHud = app.GetGameSettings(primaryPad, eGameSetting_DisplayHUD);
app.SetGameSettings(primaryPad, eGameSetting_DisplayHUD, displayHud ? 0 : 1);
app.SetGameSettings(primaryPad, eGameSetting_DisplayHand, displayHud ? 0 : 1);
}
// F3 toggles onscreen debug info
- if (g_KBMInput.IsKeyPressed(VK_F3))
+ if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_INFO))
{
- if (Minecraft* pMinecraft = Minecraft::GetInstance())
+ if (const Minecraft* pMinecraft = Minecraft::GetInstance())
{
if (pMinecraft->options)
{
@@ -1576,7 +1787,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
#ifdef _DEBUG_MENUS_ENABLED
// F6 Open debug console
- if (g_KBMInput.IsKeyPressed(VK_F6))
+ if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_CONSOLE))
{
static bool s_debugConsole = false;
s_debugConsole = !s_debugConsole;
@@ -1584,14 +1795,14 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
#endif
- // F11 Toggle fullscreen
- if (g_KBMInput.IsKeyPressed(VK_F11))
+ // toggle fullscreen
+ if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_FULLSCREEN))
{
ToggleFullscreen();
}
// TAB opens game info menu. - Vvis :3 - Updated by detectiveren
- if (g_KBMInput.IsKeyPressed(VK_TAB) && !ui.GetMenuDisplayed(0))
+ if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_HOST_SETTINGS) && !ui.GetMenuDisplayed(0))
{
if (Minecraft* pMinecraft = Minecraft::GetInstance())
{
@@ -1602,6 +1813,14 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
}
+ // Open chat
+ if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_CHAT) && app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL)
+ {
+ g_KBMInput.ClearCharBuffer();
+ pMinecraft->setScreen(new ChatScreen());
+ SetFocus(g_hWnd);
+ }
+
#if 0
// has the game defined profile data been changed (by a profile load)
if(app.uiGameDefinedDataChangedBitmask!=0)