diff options
| author | qwasdrizzel <145519042+qwasdrizzel@users.noreply.github.com> | 2026-03-16 21:44:26 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-16 21:44:26 -0500 |
| commit | ce739f6045ec72127491286ea3f3f21e537c1b55 (patch) | |
| tree | f33bd42a47c1b4a7b2153a7fb77127ee3b407db9 /Minecraft.Client/Windows64/Windows64_Minecraft.cpp | |
| parent | 255a18fe8e9b57377975f82e2b227afe2a12eda0 (diff) | |
| parent | 5a59f5d146b43811dde6a5a0245ee9875d7b5cd1 (diff) | |
Merge branch 'smartcmd:main' into main
Diffstat (limited to 'Minecraft.Client/Windows64/Windows64_Minecraft.cpp')
| -rw-r--r-- | Minecraft.Client/Windows64/Windows64_Minecraft.cpp | 813 |
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) |
