From acb2569e1987bd70db25efd6e55b106c4e361f50 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 8 Apr 2026 23:38:15 -0700 Subject: [PATCH 1/3] Add render distance (disabled) and fov option Render distance being high causes issues with fog, 360 fog levels are not built for high render distance. When fog is fixed in future PR, render distance should be re-enabled. --- .gitignore | 3 + Minecraft.Client/Options.h | 6 +- .../Windows64/Windows64_Minecraft.cpp | 218 ++++++++++++++---- 3 files changed, 180 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index 10e49ddb55..b31fff1346 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +#clion annoying +.idea + # Mono auto generated files mono_crash.* diff --git a/Minecraft.Client/Options.h b/Minecraft.Client/Options.h index 25f4e406c9..ad1daa33b7 100644 --- a/Minecraft.Client/Options.h +++ b/Minecraft.Client/Options.h @@ -57,9 +57,9 @@ class Options static const wstring PARTICLES[]; public: - // Xbox 360 immutable fields - static constexpr int viewDistance = 1; - static constexpr float fov = 0; + // Xbox 360 defaults + int viewDistance = 1; + float fov = 0.0f; float music; float sound; diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index bee49df0ec..0a62eeb857 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -50,6 +50,9 @@ #include "Windows64_Xuid.h" #include "Common/UI/UI.h" +#include +#include + // 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; @@ -120,11 +123,29 @@ wchar_t g_Win64UsernameW[17] = { 0 }; static bool g_isFullscreen = false; static WINDOWPLACEMENT g_wpPrev = { sizeof(g_wpPrev) }; -struct Win64LaunchOptions +// Render Constants +constexpr static int VALID_RENDER_DISTANCES[] = {2, 4, 8, 16, 32, 64}; +constexpr static int RENDER_DISTANCE_MIN = 2; +constexpr static int RENDER_DISTANCE_MAX = 64; +constexpr static int FOV_SLIDER_MAX = 110; +constexpr static int FOV_MIN = 70; +constexpr static int FOV_MAX = 110; +constexpr static int DEFAULT_FOV = 70; +constexpr static int DEFAULT_RENDER_DISTANCE = 8; + +typedef struct _Win64Options { - int screenMode; - bool fullscreen; -}; + uint16_t screenMode; + std::optional fov; + std::optional renderDistance; + std::optional fullscreen; + + bool modified() const + { + return screenMode != 0 || fov.has_value() || renderDistance.has_value() || fullscreen.has_value(); + } +} Win64Options, *PWin64Options; +Win64Options savedOptions = Win64Options{0}; static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize) { @@ -148,38 +169,97 @@ static void GetOptionsFilePath(char *out, size_t outSize) strncat_s(out, outSize, "options.txt", _TRUNCATE); } -static void SaveFullscreenOption(bool fullscreen) +static Win64Options LoadOptions() { - char path[MAX_PATH]; - GetOptionsFilePath(path, sizeof(path)); - FILE *f = nullptr; - if (fopen_s(&f, path, "w") == 0 && f) - { - fprintf(f, "fullscreen=%d\n", fullscreen ? 1 : 0); - fclose(f); - } + Win64Options options = {0}; + char path[MAX_PATH]; + GetOptionsFilePath(path, sizeof(path)); + FILE *f = nullptr; + + if (fopen_s(&f, path, "r") == 0 && f) + { + char line[256]; + while (fgets(line, sizeof(line), f)) + { + int val = 0; + + if (sscanf_s(line, "fullscreen=%d", &val) == 1) + { + options.fullscreen = val != 0; + } + + if (sscanf_s(line, "fov=%d", &val) == 1 + && val >= FOV_MIN && val <= FOV_MAX) + { + options.fov = static_cast(val); + } + + if (sscanf_s(line, "renderDistance=%d", &val) == 1 + && val >= RENDER_DISTANCE_MIN && val <= RENDER_DISTANCE_MAX) + { + options.renderDistance = static_cast(val); + } + } + fclose(f); + } + + return options; } -static bool LoadFullscreenOption() +static void SaveAllOptions(const Win64Options options) { - char path[MAX_PATH]; - GetOptionsFilePath(path, sizeof(path)); - FILE *f = nullptr; - if (fopen_s(&f, path, "r") == 0 && f) - { - char line[256]; - while (fgets(line, sizeof(line), f)) - { - int val = 0; - if (sscanf_s(line, "fullscreen=%d", &val) == 1) - { - fclose(f); - return val != 0; - } - } - fclose(f); - } - return false; + bool flagUpdate = false; + + if (options.renderDistance.has_value() && options.renderDistance != savedOptions.renderDistance) + { + savedOptions.renderDistance = options.renderDistance; + flagUpdate = true; + } + + if (options.fullscreen.has_value() && options.fullscreen != savedOptions.fullscreen) + { + savedOptions.fullscreen = options.fullscreen; + flagUpdate = true; + } + + if (options.fov.has_value() && options.fov != savedOptions.fov) + { + savedOptions.fov = options.fov; + flagUpdate = true; + } + + if (flagUpdate) + { + char path[MAX_PATH]; + GetOptionsFilePath(path, sizeof(path)); + FILE *f = nullptr; + + if (fopen_s(&f, path, "w") == 0 && f) + { + fprintf(f, "renderDistance=%d\n", savedOptions.renderDistance.value_or(DEFAULT_RENDER_DISTANCE)); + fprintf(f, "fov=%d\n", savedOptions.fov.value_or(DEFAULT_FOV)); + fprintf(f, "fullscreen=%d\n", savedOptions.fullscreen.value_or(false)); + fclose(f); + } + } +} + +static void SaveFullscreenOption(const bool fullscreen) +{ + char path[MAX_PATH]; + GetOptionsFilePath(path, sizeof(path)); + if (GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES) { + SaveAllOptions(Win64Options{savedOptions.screenMode, savedOptions.fov, savedOptions.renderDistance, fullscreen}); + } +} + +int FovToSliderValue(const float fov) +{ + int clampedFov = static_cast(fov + 0.5f); + if (clampedFov < FOV_MIN) clampedFov = FOV_MIN; + if (clampedFov > FOV_MAX) clampedFov = FOV_MAX; + + return ((clampedFov - FOV_MIN) * FOV_SLIDER_MAX) / (FOV_MAX - FOV_MIN); } // ------------------------------------------------------------------ @@ -204,10 +284,9 @@ static void ApplyScreenMode(int screenMode) } } -static Win64LaunchOptions ParseLaunchOptions() +static Win64Options ParseLaunchOptions() { - Win64LaunchOptions options = {}; - options.screenMode = 0; + Win64Options options = Win64Options{0}; g_Win64MultiplayerJoin = false; g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT; @@ -245,8 +324,28 @@ static Win64LaunchOptions ParseLaunchOptions() g_Win64MultiplayerPort = static_cast(port); } } + else if (_wcsicmp(argv[i], L"-renderDistance") == 0 && (i + 1) < argc) { + wchar_t* endPtr = nullptr; + const long renderDistance = wcstol(argv[++i], &endPtr, 10); + + if (endPtr != argv[i] && *endPtr == 0 && renderDistance >= RENDER_DISTANCE_MIN && renderDistance <= RENDER_DISTANCE_MAX) + { + options.renderDistance = static_cast(renderDistance); + } + } + else if (_wcsicmp(argv[i], L"-fov") == 0 && (i + 1) < argc) { + wchar_t* endPtr = nullptr; + const long fov = wcstol(argv[++i], &endPtr, 10); + + if (endPtr != argv[i] && *endPtr == 0 && fov >= FOV_MIN && fov <= FOV_MAX) + { + options.fov = static_cast(fov); + } + } else if (_wcsicmp(argv[i], L"-fullscreen") == 0) - options.fullscreen = true; + { + options.fullscreen = true; + } } LocalFree(argv); @@ -1356,7 +1455,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, } // Load stuff from launch options, including username - const Win64LaunchOptions launchOptions = ParseLaunchOptions(); + const Win64Options launchOptions = ParseLaunchOptions(); ApplyScreenMode(launchOptions.screenMode); // Ensure uid.dat exists from startup (before any multiplayer/login path). @@ -1453,13 +1552,6 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, CleanupDevice(); return 0; } - - // Restore fullscreen state from previous session - if (LoadFullscreenOption() && !g_isFullscreen || launchOptions.fullscreen) - { - ToggleFullscreen(); - } - #if 0 // Main message loop MSG msg = {0}; @@ -1523,6 +1615,44 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, //app.TemporaryCreateGameStart(); //Sleep(10000); + + // Restore previous properties + savedOptions = LoadOptions(); + + if (launchOptions.modified()) + { + SaveAllOptions(launchOptions); + } + + if (savedOptions.modified()) + { + if (savedOptions.fullscreen.value_or(false) && !g_isFullscreen) + { + ToggleFullscreen(); + } + + if (savedOptions.renderDistance.has_value()) + { +#if 0 + for (size_t i = 0; i < std::size(VALID_RENDER_DISTANCES); i++) + { + if (VALID_RENDER_DISTANCES[i] != savedOptions.renderDistance.value()) + { + continue; + } + + pMinecraft->options->viewDistance = static_cast(3 - i); + app.SetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_RenderDistance, savedOptions.renderDistance.value()); + } +#endif + } + + if (savedOptions.fov.has_value()) + { + pMinecraft->gameRenderer->SetFovVal(savedOptions.fov.value()); + app.SetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_FOV, FovToSliderValue(savedOptions.fov.value())); + } + } #if 0 // Intro loop ? while(app.IntroRunning()) From a4cbd094f35ee25bd465360cfda5e3e9da56a7e3 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 8 Apr 2026 23:50:28 -0700 Subject: [PATCH 2/3] Update README.md --- .gitignore | 3 --- README.md | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index b31fff1346..10e49ddb55 100644 --- a/.gitignore +++ b/.gitignore @@ -17,9 +17,6 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs -#clion annoying -.idea - # Mono auto generated files mono_crash.* diff --git a/README.md b/README.md index a149fb159b..cecbc6a982 100644 --- a/README.md +++ b/README.md @@ -75,10 +75,11 @@ Would you like to contribute to this project? Please read our [Contributor's Gui |--------------------|-----------------------------------------------------------------------------------------------------| | `-name ` | Overrides your in-game username. | | `-fullscreen` | Launches the game in Fullscreen mode | +| `-fov ` | Sets a custom FOV in the range (70-110) | Example: ``` -Minecraft.Client.exe -name Steve -fullscreen +Minecraft.Client.exe -name Steve -fullscreen -fov 70 ``` ## LAN Multiplayer From 02310317542fa843d0918665bb44fd5716d86218 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 9 Apr 2026 01:48:55 -0700 Subject: [PATCH 3/3] Allow modification of FOV externally --- Minecraft.Client/Options.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Minecraft.Client/Options.cpp b/Minecraft.Client/Options.cpp index 9ad1ad26d3..9d5ab568d9 100644 --- a/Minecraft.Client/Options.cpp +++ b/Minecraft.Client/Options.cpp @@ -233,7 +233,7 @@ void Options::set(const Options::Option *item, float fVal) } if (item == Option::FOV) { -// fov = fVal; + fov = fVal; } if (item == Option::GAMMA) { @@ -241,7 +241,7 @@ void Options::set(const Options::Option *item, float fVal) } if (item == Option::RENDER_DISTANCE) { -// viewDistance = fVal; + viewDistance = fVal; } }