A comma between "item.armor.equip_generic6" and "damage.critical" was
accidentally dropped during an upstream merge, causing the two entries
to be concatenated into a single string literal at compile time.
This produced an invalid sound key and led to crashes when:
- equipping armor
- triggering critical hits
The string identifier for the Elder Guardian entity was set
to `IDS_GUARDIAN_ELDER`. This has been changed to the
consistent identifier `IDS_ELDER_GUARDIAN`.
Additionally, the localization file has been updated to include the
missing string definitions for both `IDS_GUARDIAN` and
`IDS_ELDER_GUARDIAN`
The hardcore difficulty label was using the raw string ID `IDS_HARDCORE` (oops)
instead of a localized string, which caused a crash in the UI.
Replaced `IDS_HARDCORE` with `app.GetString(IDS_HARDCORE)`
Add virtual `canMoveSlider` method to UIScene base class and override it
in both LoadMenu and CreateWorldMenu scenes. The method returns false
when attempting to move the gamemode slider while hardcore mode is active,
effectively locking the slider in that state.
The UIController now checks `canMoveSlider` before initiating a slider
drag and during ongoing drag updates.
* f3 menu text scaling
* Reduce overscaling above 1080p
Restores original scaling for 1440p to try and keep the text size more
sane on high DPI monitors
---------
Co-authored-by: Loki Rautio <lokirautio@gmail.com>
Replace the hardcoded string literal "Hardcore" in the difficulty slider
label with the localization resource identifier `IDS_HARDCORE` in both
the load menu and create world menu scenes.
The previous implementation only indexed files in the root directory,
ignoring files in subdirectories. This change adds recursive traversal
to index all files within the folder hierarchy while maintaining
relative paths for compatibility.
Replace the ArchiveFile-based media asset loading system with a new
FolderFile implementation that reads files directly from a folder
structure instead of from compressed .arc archives. This change
simplifies asset management and eliminates the need for pre-packaged
media archives.
Key changes:
- Added FolderFile class that indexes and reads files from a folder
- Updated Consoles_App to use FolderFile instead of ArchiveFile
- Modified CMake asset copy configuration to exclude platform-specific
media folders instead of .arc files
- Updated platform-specific media path references to point to folders
instead of .arc files
This enables easier development and debugging by allowing direct access
to media files without requiring archive extraction or repackaging.
When a new player was whitelisted while they were sitting on the join screen, their next attempt would insta-kick before the world ever loaded, and the retry after that would let them in for roughly 20 seconds before booting them with "connection closed". Two separate bugs were colliding.
The first kick was a stale cancel flag on the client. When the server rejects a join, the "Connecting to host..." screen tears down, and its teardown path fires the cancel callback defensively. That flag would latch on without ever being consumed, so the very first tick of the next join attempt saw it and immediately closed the fresh connection. Clearing the flag when a new join starts prevents this.
The second kick was an orphan on the server. When the first failed join's TCP dropped, its slot got recycled for the next successful join, but the half-built login object from the broken attempt was still in the pending queue. 30 seconds later its "login took too long" timer fired, and the disconnect packet it tried to send was routed to whoever currently held that slot, which was now the new in-world player. It landed on their live socket and kicked them. Telling the game's Socket layer about the TCP drop lets the orphan clean itself up, and refusing to write on an already-closing socket stops any late packet from leaking into the recycled slot.
Before this change, turning VSync off did not actually uncap your frame rate. The game ran in borderless fullscreen, where Windows' desktop compositor owns the display pipeline and applies its own VSync regardless of what the game asks for. So on a 240Hz monitor with a GPU that could draw 800fps, you still only saw 240 frames per second and the other 560 were thrown away. Worse, the frames you did see were up to a refresh cycle stale by the time they hit your eyes, which is input latency you can feel when moving the camera or aiming.
Fullscreen now uses true DXGI exclusive mode, where the compositor is out of the way and the swap chain writes directly to the display. Every frame the GPU produces lands on screen as soon as it is ready, so "VSync off" actually does something. Expect FPS to climb well past your monitor's refresh rate and the mouse to feel noticeably more responsive.
Exclusive fullscreen also displays at your monitor's native resolution with no driver-side scaling or filtering. The backbuffer is grown to match the monitor exactly before the transition, and the display mode is pinned to the backbuffer size so nothing in the output pipeline resamples your pixels on the way to the screen. The result is a crisp 1:1 image with none of the softening or greyish filter that stretched output can introduce.
Yes, this is the mode where screen tearing can happen. Tearing gets a bad reputation but it is a visual tradeoff, not a bug, and many players prefer it over the latency VSync causes. If you want to avoid tearing, just turn VSync on in the settings and the game will cap cleanly to your refresh rate. You now have a real choice between the two instead of "off" quietly being broken.
Under the hood, F11 and the saved fullscreen preference both route through a new ApplyExclusiveFullscreen path that does Microsoft's recommended transition: grow the window to cover the monitor, ResizeTarget with no scaling so the display mode is pinned to the backbuffer size, SetFullscreenState(TRUE), SetColorSpace1(sRGB), then a second ResizeTarget so picky drivers actually apply the mode. Exit forces a real decorated windowed state so F11 cycles cleanly between windowed and exclusive fullscreen. ResizeD3D skips its swap-chain-recreate path while in exclusive mode so it does not fight DXGI for ownership.
The swap chain's RefreshRate changes from a hardcoded 60Hz to 0/0 so DXGI matches the current display mode. Fixes an "input signal out of range" error that could happen on high-refresh monitors after entering fullscreen, where the monitor was being asked to renegotiate timing off of 240Hz down to 60Hz on every launch.
The previous FLIP_DISCARD swap chain configuration was producing broken rendering and a stretched aspect ratio on startup and after window resize, because the closed-source 4J Renderer library holds hidden backbuffer references that prevent ResizeBuffers from succeeding in flip mode. Switches the swap chain to the legacy bitblt DISCARD model with BufferCount=1, which lets the "destroy old, create new" resize path in ResizeD3D work cleanly. In-world rendering and aspect ratio are now correct at launch and across window resizes.
Known regression from this change: screen tearing no longer works when VSync is off. On Windows 10 and 11, bitblt swap chains always go through the DWM compositor, which locks presentation to the monitor refresh rate regardless of the SyncInterval parameter we pass to Present. Every frame the renderer produces above the refresh rate is silently dropped by DWM, which hurts input latency compared to a true uncapped-fps presentation path. The next iteration will reverse-engineer the 4J Renderer struct layout to find where those hidden backbuffer references are stored, release them before ResizeBuffers, and switch back to FLIP_DISCARD with ALLOW_TEARING so real tearing is possible again.
Also removes the dead SwapChainVSyncProxy COM wrapper. The proxy was originally intended to intercept Present calls from the Renderer library for VSync control, but the library hardcodes SyncInterval=1 and does not dispatch Present through the proxy vtable, so it was never actually doing anything useful.
The upstream project (formerly smartcmd/MinecraftConsoles, now MCLCE/MinecraftConsoles) reorganized their in-game credits screen. This pulls in that restructure so our credits accurately reflect who the current and former upstream maintainers are, and points the attribution URL at the right place. codeHusky and mattsumi stay as Project Maintainers, and itsRevela is added alongside them. smartcmd, Patoke, and rtm516 move to a new Former Maintainers section. The contributor count ticks up from 100+ to 120+, and the credit URL at the bottom now reads github.com/MCLCE/MinecraftConsoles with a "(formerly smartcmd/MinecraftConsoles)" line underneath it.
On the README side, only the Star History chart URL was updated from smartcmd to MCLCE. The Nightly client and dedicated server download links stay pointed at itsRevela/LCE-Revelations since our fork has its own release pipeline.
Upstream attribution: d0786f95 by Loki Rautio. Applied as a partial cherry-pick with the two Nightly download URL hunks dropped and itsRevela added to the maintainer list.
The personal repo was renamed from itsRevela/MinecraftConsoles to itsRevela/LCE-Revelations, so this sweeps the rest of the codebase to match. In-game, the credits screen now shows "LCE-Revelations" instead of "MinecraftConsoles" as the project heading. In the README, the Nightly client and dedicated server download links point at the new repo URL, and the Docker image reference is now ghcr.io/itsrevela/lce-revelations-dedicated-server. The dedicated server's generated server.properties file also picks up a new header comment reflecting the rename.
For folks building from source: the CMake project name was renamed, so when you configure the build the generated solution file is now LCE-Revelations.sln instead of MinecraftConsoles.sln. The Nix flake description and the Nightly release uploader script were updated to match, and a historical FourKit port reconnaissance document was removed since that port is already complete.
Also restored the Fluxer server link at the top of the README, which was lost when the repo was fast-forwarded from the upstream that got griefed.
When framerate was uncapped (vsync off, high-end hardware), the controller cursor in the inventory and creative menus moved way too fast. Basically unusable unless you switched to the dpad. The cursor update was tied to how often the screen redraws, so the faster the game ran, the faster the cursor flew.
Now the cursor moves a smaller distance per frame at higher framerates, so the actual on-screen speed stays the same whether you're at 60 FPS or 600 FPS.
While fixing this I also found an old workaround that was rounding the cursor position to whole pixels every frame and nudging it by 1 pixel to keep it from getting stuck. That nudge was pointing the wrong way on the vertical axis, which made up/down movement feel broken once the per-frame distance got small. Removed the rounding and the nudge. The cursor can now hold a fractional position between frames, and the part of the code that actually draws the cursor still snaps it to whole pixels on screen.
Fixes#3
Add missing GuardianModel.cpp and GuardianRenderer.cpp to the
Minecraft.Server build configuration to fix compilation errors in
the debug GitHub PR workflow.
Also fix inconsistent indentation in Minecraft.Client's Common.cmake
for the GuardianModel.cpp and GuardianRenderer.cpp entries (styling only).