Author SHA1 Message Date
Byte 475f5ac496 fix: Sword Blocking crashes the game when achievements enabled 2026-07-09 07:09:45 +02:00
Byte ef7d4658dc performance boost 2026-07-08 18:40:09 +02:00
Byte 2bc24119cf restore: discord rpc 2026-07-07 17:17:27 +02:00
Byte b32e298a18 Add 2026-06-14 10:23:25 +02:00
itsRevela 3c154f858d Merge pull request 'Old swing animations from the Minecraft Console Editions' (#2) from calcomcolt/LCE-Revelations:old-swing-animations into main
Reviewed-on: https://git.revela.dev/itsRevela/LCE-Revelations/pulls/2
2026-05-23 09:49:06 -05:00
calcomcolt dfcfbd6ca6 Update Minecraft.Client/ItemInHandRenderer.cpp
Old swing animations before they got modified in the MinecraftConsoles repo
2026-05-20 01:33:59 -05:00
itsRevela 5079622a6f ci: revert chunked-upload and full-history workarounds 2026-05-17 06:39:57 -05:00
itsRevela 6e31a8c0b8 ci: point workflow at git.revela.dev 2026-05-17 06:36:52 -05:00
itsRevela 61a8a13245 ci: enable buildx docker-container driver for OCI export 2026-05-17 02:01:49 -05:00
itsRevela c0cb7b7809 ci: push docker images via crane with chunked uploads 2026-05-17 01:30:12 -05:00
itsRevela 289225e07d ci: use REGISTRY_TOKEN for Forgejo container registry push 2026-05-15 03:04:29 -05:00
itsRevela ea02b5ee36 ci: full-history checkout for release tag push 2026-05-15 01:09:30 -05:00
itsRevela 59c39428fa ci: log file sizes and HTTP status on release asset upload 2026-05-14 16:44:10 -05:00
itsRevela 8ad207368b ci: pin artifact actions to v3 for Forgejo compatibility 2026-05-14 15:37:04 -05:00
itsRevela 07f0eb95dd ci: port nightly release pipeline to Forgejo 2026-05-14 15:24:32 -05:00
itsRevela 9c9238c6c4 ci: pin action uses to full GitHub URLs 2026-05-14 14:28:27 -05:00
itsRevela cf22f5f5f4 ci: switch workflows to self-hosted runner labels 2026-05-14 14:22:28 -05:00
itsRevela 386b9c430b Revert "chore(server): re-enable console QuickEdit mode"
This reverts commit 99120e5323.
2026-05-02 14:47:46 -05:00
itsRevela 68c2994523 chore: sync upstream MinecraftConsoles through d3df5350 2026-04-30 15:49:27 -05:00
itsRevela 1d9e79b9b3 docs: add submodule clone hint to compile instructions 2026-04-30 15:49:12 -05:00
itsRevela 50746cd3de revert(server): empty-dim entity tick gate 2026-04-30 15:46:26 -05:00
LokiandGitHub d3df53503a Update COMPILE.md 2026-04-30 13:21:31 -05:00
LokiandGitHub 5bccf89fe2 Update COMPILE.md 2026-04-30 13:21:25 -05:00
itsRevela 99120e5323 chore(server): re-enable console QuickEdit mode 2026-04-30 11:19:58 -05:00
itsRevela ca0619939c chore: sync upstream MinecraftConsoles through 5f931d74 2026-04-30 10:51:06 -05:00
itsRevela e4005d6b76 docs: add submodule clone hint to build instructions 2026-04-30 10:50:45 -05:00
itsRevela bddcc13bff chore(server): raise perf log thresholds to reduce noise 2026-04-30 10:47:08 -05:00
Loki Rautio 5f931d74fc Update 4JLibs, adjust README 2026-04-29 17:02:40 -05:00
itsRevela 5c90744677 docs: document fourkit docker image alongside vanilla in readme 2026-04-29 13:35:30 -05:00
itsRevela 750c4696ae chore: rewrite code comments 2026-04-29 13:33:19 -05:00
itsRevela ff3241cfee fix: server save-on-exit reliability and logging 2026-04-29 13:28:20 -05:00
itsRevela 17fdc78567 chore: bump 4JLibs to include PNG text section fix 2026-04-29 12:06:26 -05:00
itsRevela 3064afc9b2 chore: point 4JLibs submodule to itsRevela fork 2026-04-29 11:47:18 -05:00
itsRevela 3c1a7c174a feat: wire docker job into nightly workflow and update Dockerfile for both flavours 2026-04-28 17:31:58 -05:00
itsRevela 54b60867d4 feat: build vanilla and fourkit dedicated server docker images in nightly 2026-04-28 17:31:34 -05:00
itsRevela 8495baf83e fix: remove 30-second sprint auto-stop 2026-04-28 17:12:50 -05:00
itsRevela cc68899cec fix: iron door no longer blocks held-item use on right-click 2026-04-28 15:33:14 -05:00
itsRevela 89ed116fe0 fix: beacon outer halo washed out behind water 2026-04-28 14:19:22 -05:00
itsRevela 0df5cd865b chore: sync upstream MinecraftConsoles through 585455ce 2026-04-26 15:40:23 -05:00
ModMaker101anditsRevela cbdb92d045 Replace MSVC __debugbreak with cross-compiler DEBUG_BREAK macro. (#1540) 2026-04-26 15:38:13 -05:00
ModMaker101anditsRevela 0625db38f5 Fix autosave thread compression TLS crash. (#1544) 2026-04-26 15:38:13 -05:00
Loki RautioanditsRevela fc0e32f346 Fix PR workflow
Per patoke
2026-04-26 15:38:13 -05:00
Loki RautioanditsRevela 3cef7f17dc fix: Control mappings wrong (update 4JLibs)
fixes #1531 and #1528
2026-04-26 15:38:13 -05:00
Loki RautioanditsRevela d467b10e39 Remove redundant gitignore line 2026-04-26 15:38:13 -05:00
gsdsanditsRevela 54ecbed263 Include 4JLibs as a submodule (#1535)
* feat: 4JLibs as a submodule

* fix: forgot submodule

* fix: actions didn't recurse submodules on checkout

* fix: oops, using old commit
2026-04-26 15:38:13 -05:00
dtentiionanditsRevela 7f18fe1236 fix: Nether portal trigger and travel sounds not playing (#1523) 2026-04-26 15:38:13 -05:00
RevelaandGitHub f583495958 Merge pull request #2 from Firebladedoge229/main
fix: paper doll transformations on non-16:9 aspect ratios
2026-04-26 15:10:39 -05:00
itsRevela 6b7d81a92b revert: /ping command and kernel TCP RTT plumbing 2026-04-26 14:52:46 -05:00
ModMaker101andGitHub 585455cef0 Replace MSVC __debugbreak with cross-compiler DEBUG_BREAK macro. (#1540) 2026-04-26 12:23:52 -05:00
ModMaker101andGitHub 3ab29ec26e Remove HTML escape for apostrophe in chat (#1541)
Fixes #1537
2026-04-26 12:22:51 -05:00
ModMaker101andGitHub e5351b51c0 Fix autosave thread compression TLS crash. (#1544) 2026-04-26 12:21:33 -05:00
itsRevela 44283e5971 fix(server): empty-dim tick gate broke block updates 2026-04-26 00:00:24 -05:00
itsRevela 70a610fd2c feat(server): kernel TCP RTT for Player.getPing() 2026-04-25 23:26:13 -05:00
itsRevela 0708120ae8 feat: add TpsPlugin sample with /tps and /ping 2026-04-25 22:45:35 -05:00
itsRevela f105952140 docs: README entry for TPS recovery at scale 2026-04-25 13:46:01 -05:00
itsRevela ce9ffefba6 perf(server): hold 20 TPS at 50-player scale 2026-04-25 13:42:29 -05:00
FirebladeandGitHub da91372804 chore: clean up paper doll code for redundancy 2026-04-25 12:09:30 -04:00
FirebladeandGitHub 1672dbab05 fix: paper doll viewmodel on non-16:9 window aspect ratios 2026-04-24 22:54:06 -04:00
itsRevela 18a08ec693 docs: README entry for FourKit dispatch performance fix 2026-04-24 21:35:34 -05:00
itsRevela b64b1f17db perf(fourkit): server gc, fast-path event dispatch, tps probe 2026-04-24 21:31:06 -05:00
Loki Rautio 42e75876f2 Fix PR workflow
Per patoke
2026-04-24 07:11:34 -05:00
Loki Rautio 5e5b685c72 fix: Control mappings wrong (update 4JLibs)
fixes #1531 and #1528
2026-04-21 19:55:46 -05:00
Loki Rautio d4ac3cd645 Remove redundant gitignore line 2026-04-21 18:57:30 -05:00
gsdsandGitHub 1b8a14357c Include 4JLibs as a submodule (#1535)
* feat: 4JLibs as a submodule

* fix: forgot submodule

* fix: actions didn't recurse submodules on checkout

* fix: oops, using old commit
2026-04-21 18:32:02 -05:00
itsRevela 6db68bda06 test(fourkit): add setblock and chatcolor subcommands to test plugin 2026-04-18 20:22:26 -05:00
sylvessaanditsRevela cb941db3ad i forgot to add chunk events to the docs 2026-04-18 19:57:20 -05:00
sylvessaanditsRevela b441998732 new funcs in Block, chatcolor enum 2026-04-18 19:57:14 -05:00
itsRevela 8dd9d92ad6 feat: add FourKit test plugin for chunk/inventory/disenchant verification 2026-04-18 19:15:56 -05:00
SylvessaandGitHub 7c1606837f fix: worlds without worlds won't open (#1529) 2026-04-18 19:14:42 -05:00
sylvessaanditsRevela 2e0f4f91d6 fix disenchant bugs from setdurability etc 2026-04-18 18:16:29 -05:00
sylvessaanditsRevela f9cac6395b fill in old stubs regaridng chunk stuff & another inv fix 2026-04-18 18:16:24 -05:00
sylvessaanditsRevela a9c735e7aa fix bugs found regarding inventories 2026-04-18 18:15:03 -05:00
sylvessaanditsRevela a3221c9e14 chunk additions 2026-04-18 18:14:58 -05:00
dtentiionandGitHub 4a7b34f4c2 fix: Display save thumbnail in world detail view on Windows64 (#1519) 2026-04-18 17:49:43 -05:00
dtentiionandGitHub 9167454767 fix: Nether portal trigger and travel sounds not playing (#1523) 2026-04-18 17:47:18 -05:00
itsRevela 84e4a77409 fix: exit save sometimes dropped during shutdown race 2026-04-18 10:56:54 -05:00
itsRevela 68c3440394 docs: note breeding/spawn-egg scaling with mob cap config 2026-04-18 10:19:27 -05:00
itsRevela 7e586e0d49 fix: scale breeding and spawn-egg caps with configured mob caps 2026-04-18 10:15:33 -05:00
itsRevela defd9ebd00 docs: update readme with recent fixes and mob cap config 2026-04-18 09:39:09 -05:00
itsRevela ffdad03aca feat: configurable mob spawn caps via server.properties 2026-04-18 09:31:45 -05:00
itsRevela c297b26f36 fix: duplicate join message on FourKit servers 2026-04-18 09:10:47 -05:00
itsRevela b4a34df1a9 fix: apostrophes rendering as ' in Iggy HTML chat labels 2026-04-17 16:55:56 -05:00
itsRevela ee3cf5117b chore: exclude .exp and .lib build artifacts from release zips 2026-04-17 15:31:53 -05:00
itsRevela afa3e22715 fix: force backbuffer clear alpha to 1.0 to prevent DWM window transparency 2026-04-17 12:43:46 -05:00
itsRevela cf81dd9d13 fix: apostrophes and quotes displaying as HTML entities in chat 2026-04-17 12:20:58 -05:00
itsRevela fde5fbe6f4 fix: force VSync on main menu to prevent GPU coil whine 2026-04-17 11:55:04 -05:00
itsRevela af39797303 chore: add PDB to nightly release, update readme
- Enable /Zi and /DEBUG for Release builds to generate PDB files
- Stage Minecraft.Client.pdb as standalone release asset
- Exclude .pdb from the zip release (dev-only artifact)
- Update release notes to separate player and developer instructions
- Update readme Latest section with recent bug fixes
2026-04-17 07:21:29 -05:00
itsRevela ce2efc1a4d fix: crash when opening UI scenes at sub-720p window size
SWF movie loading crashed with __debugbreak when the window height was
below 720px (e.g. after leaving exclusive fullscreen). The fallback
chain only tried 720.swf which doesn't exist. Now falls back through
720 -> 1080 so scenes always find a valid SWF.
2026-04-17 07:07:02 -05:00
itsRevela eb5aa9fa8f fix: chat color codes not rendering in singleplayer
PlayerConnection::handleChat called FormatChatMessage with
applyStyling=false before broadcasting, which stripped all color codes
from the message. The client then had nothing left to format. Send the
raw message and let the client handle formatting on receive.
2026-04-17 07:06:39 -05:00
itsRevela 59f9dbc8c6 fix: hardcore mode UI not locking difficulty/gamemode on world load
Three issues fixed:

- Save file path used hardcoded saveData.ms but new 4JLibs names files
  as <title>.ms. ReadLevelNameFromSaveFile now constructs the correct
  path with fallback to saveData.ms for old saves.
- The level.dat code path for reading the hardcore flag (sidecar rename)
  returned early without ever parsing level.dat. Now stores the sidecar
  name and continues to read the hardcore flag from NBT.
- The thumbnail host options path could overwrite m_bHardcore to false.
  Now only upgrades to true, never downgrades.
- Load menu constructor and tick handler both lock difficulty slider to
  Hardcore and gamemode to Survival when hardcore is detected.
- Hide title logo on load menu to match create world menu.
2026-04-17 07:06:26 -05:00
itsRevela bc6e445f0c fix: capture save thumbnails directly from D3D11 backbuffer
The new 4JLibs CaptureThumbnail produces all-black 64x64 PNGs because
its internal m_backBufferTexture copy fails silently. Bypass it entirely
and capture from the swap chain backbuffer using the same proven approach
as our F2 screenshot, with center-crop and downsample to 64x64 PNG.
2026-04-17 07:06:02 -05:00
itsRevela ec5ec84407 feat: add 4JLibs comparison tooling
Tools for comparing 4JLibs binary changes between git refs:
- compare-4jlibs.py: Extracts libs, parses symbol tables via dumpbin,
  demangles with undname, generates structured diff reports
- extract_lib.py: Extracts .obj members from COFF .lib archives
- ExportLibInfo.java: Ghidra headless script for non-LTCG object files
- list-lib-symbols.sh / compare-4jlibs.sh: Shell wrappers
2026-04-17 05:55:25 -05:00
itsRevela 019b790fb3 chore: sync upstream MinecraftConsoles through 1a552fbd 2026-04-17 05:53:46 -05:00
DrPerkyLegitanditsRevela 9ddb95e7ad Fix broken Chat Formatting behavior (#1520)
- Remove shadowcolor from font tags (Iggy doesn't support multiple)
- Enforce HTML text mode on chat labels and jukebox
- Move IDS translatable pattern matching into FormatChatMessage
- Add §r (reset) color code support
- Fix message truncation to count visible characters, skipping HTML tags
- Fix CJK truncation using raw index instead of visible char count
2026-04-17 05:52:26 -05:00
dtentiionanditsRevela 8464bfd448 fix: Skin pack names showing only first letter after 4JLibs update (#1518) 2026-04-17 05:49:22 -05:00
Loki RautioanditsRevela 0e0f8f696d feat: Upgrade to 4JLibs libraries
Includes fixes and some modernizations compared to the original 4J
library binaries. Also introduces functionality to support stuff like
F2 screenshots, etc. This is basically the beginning of modernizing the
codebase.
2026-04-17 05:40:38 -05:00
LokianditsRevela 6ef535d53e Add new Discord invite to issue config 2026-04-17 05:39:51 -05:00
Alisa VulpesanditsRevela 004cd72ba5 Add .DS_Store to .gitignore (#1509) 2026-04-17 05:38:39 -05:00
DrPerkyLegitandGitHub 1a552fbd0c Fix broken Chat Formatting behavior (#1520)
* fix formatting in chat

iggy doesnt like multiple shadow colors

* enforce html labels

* dont format before sending packet, client formats anyway

* move translateables to chat format, restore original empty message results

* fix crappy string cutoff

* forgot a line on last commit, reset color support

* restore function to strip styling from player messages
2026-04-16 22:41:50 -05:00
dtentiionandGitHub cccfd860b9 fix: Skin pack names showing only first letter after 4JLibs update (#1518) 2026-04-16 22:35:14 -05:00
RevelaandGitHub d0094a6409 Add F2 screenshot functionality (#1262)
- Updated `EControllerActions` to include `MINECRAFT_ACTION_SCREENSHOT`.
- Added conditional compilation for `stb_image_write.h` in `Minecraft.cpp`.
- Modified `run_middle()` to handle screenshot key press.
- Updated `tick()` to capture and save screenshots as PNG files.
- Introduced `KEY_SCREENSHOT` in `KeyboardMouseInput.h` mapped to F2.
- Added `stb_image_write.h` for image writing capabilities.
2026-04-16 22:33:30 -05:00
Loki Rautio 78d4bc80cf feat: Upgrade to 4JLibs libraries
Includes fixes and some modernizations compared to the original 4J
library binaries. Also introduces functionality to support stuff like
F2 screenshots, etc. This is basically the beginning of modernizing the
codebase.
2026-04-15 19:07:15 -05:00
LokiandGitHub 6595b3820d Add new Discord invite to issue config 2026-04-15 18:22:01 -05:00
Alisa VulpesandGitHub 7f0237a286 Add .DS_Store to .gitignore (#1509)
macOS automatically creates a .DS_Store file if any custom macOS attributes are set to files (like visual position in Finder). It's redundant for this repo and to avoid that to be accidentally committed/pushed, I added it to .gitignore.
2026-04-15 17:26:27 -05:00
itsRevela d694cd1c9d chore: sync upstream MinecraftConsoles through 2fba264c 2026-04-15 05:25:33 -05:00
Loki RautioanditsRevela 9d92d5eb9b Swap critical.mp3 for critical.ogg (#1503) 2026-04-15 05:22:37 -05:00
LokiandGitHub 2fba264c08 Revert "Prevent contextually wrong music from playing (#1138)"
This reverts commit 2d41711055.
2026-04-14 17:00:35 -05:00
Loki Rautio 1533b2138f Swap critical.mp3 for critical.ogg (#1503) 2026-04-14 16:59:58 -05:00
c0da06e4ee major: Switch to forward slashes(+more) to fix compilation on Linux (#1403)
Notably also adds some metadata files for NixOS 

* add support for linux clang cross compiles

* add linux clang instructions

* un-capitalize Mob.horse.*

* update the description in flake.nix

---------

Co-authored-by: Loki <lokirautio@gmail.com>
2026-04-14 16:47:37 -05:00
itsRevela 5133925be0 chore: sync upstream MinecraftConsoles through f78dec6e 2026-04-13 03:16:34 -05:00
itsRevela 0544add4e2 chore: remove redundant/unused 4JLibs files 2026-04-13 03:15:58 -05:00
Loki Rautio f78dec6e00 Remove redundant/unused 4JLibs files
also adds some countermeasures against, yknow.
2026-04-13 01:26:36 -05:00
itsRevela 0d102b167f docs: add Latest entries for upstream sync through 78afb091 2026-04-13 01:00:03 -05:00
itsRevela 8c34855343 chore: sync upstream MinecraftConsoles through 78afb091 2026-04-13 00:54:24 -05:00
Tyler ReeseanditsRevela 6913ce5323 fix: Implement missing critical hit sound (#1141) 2026-04-13 00:51:16 -05:00
DrPerkyLegitanditsRevela 71707fbb8c Add Chat Formatting Support For Servers (#1483) 2026-04-13 00:49:49 -05:00
GabsPuNsanditsRevela ae9dbd837d Exclude more files, reduce build .zip size (#1374) 2026-04-13 00:48:43 -05:00
Toru the Red FoxanditsRevela 825e96da54 Request dedicated GPU (#850) 2026-04-13 00:47:00 -05:00
BotchanditsRevela dea2bad0c4 fix: Disable font mipmapping (#1410) 2026-04-13 00:46:32 -05:00
DrPerkyLegitanditsRevela ae3c843ee5 fix: Increase entity network limit to 16k entities (#1492) 2026-04-13 00:43:18 -05:00
DrPerkyLegitanditsRevela 6c572d4940 feat: Scrollable chat (#1493) 2026-04-13 00:42:04 -05:00
5e7ad7333e Better Text Scaling (#1494)
* 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>
2026-04-13 00:37:54 -05:00
78afb091a4 fix: Implement missing critical hit sound (#1141)
* Fix

* Crit Sound Now Plays On Death

* Revert BuildVer.h

---------

Co-authored-by: Loki <lokio.casebstv@gmail.com>
2026-04-12 23:24:29 -05:00
Tyler ReeseandGitHub 2d41711055 fix: Prevent contextually wrong music from playing (#1138) 2026-04-12 23:22:14 -05:00
DrPerkyLegitandGitHub 14f8d793dd Add Chat Formatting Support For Servers (#1483)
* add chat support for html formatting

* html character serialization, normal color format support

* change for chat input handling on color

has a bug where the text after the cursor gets stripped of its color, need to make a function to backstep on a string and find the last used color codes, or get all color codes used before the string is split, and apply them to the start of the next string

* expose jukebox label as action bar like java

* prevent players from sending chat color

* restore non styled chat size check
2026-04-12 23:17:45 -05:00
GabsPuNsandGitHub bfcb621808 Exclude more files, reduce build .zip size (#1374)
* Fix Sign

* Exclude more files from the compilation.

* Remove Trial and Tutorial folder in Common, Tutorial world is in windows64media
2026-04-12 23:17:21 -05:00
Toru the Red FoxandGitHub 050c501786 Request dedicated GPU (#850) 2026-04-12 22:56:24 -05:00
BotchandGitHub e5ce9a06cd fix: Disable font mipmapping (#1410)
Fixes visual artifacts with signs, improving legibility at distances
2026-04-12 22:55:07 -05:00
Us3ful"-DevandGitHub e730033bcc fix: Prevent end poem crash (#1489)
Removed player name check that always fails to work on non host instances
2026-04-12 22:53:39 -05:00
rtm516andGitHub 9e6e3de338 Improve actions file ignore rules (#1491)
* Add clang-format workflow for pull request checks

* Modify push paths in nightly workflow

Updated paths for push event to include all files except specified ones.

* Update paths for nightly-server workflow triggers

* Modify paths for pull request triggers

Update pull request workflow to include specific paths.

* Remove formatting check workflow
2026-04-12 22:52:34 -05:00
DrPerkyLegitandGitHub 82c1ae1968 fix: Increase entity network limit to 16k entities (#1492) 2026-04-12 22:50:46 -05:00
DrPerkyLegitandGitHub c7014f6b18 feat: Scrollable chat (#1493)
* chat scrolling

* allow escape to close chat instead of opening pause
2026-04-12 22:50:16 -05:00
744048f455 Better Text Scaling (#1494)
* 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>
2026-04-12 22:48:08 -05:00
itsRevela 33bec8a93c docs: add Latest entries for recent client fixes
Covers the join-flow kick bug, the fullscreen and frame rate work, and the controller cursor speed fix.
2026-04-11 08:13:58 -05:00
itsRevela abb18e3e12 fix: new players kicked when joining right after being whitelisted
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.
2026-04-11 08:13:46 -05:00
itsRevela f189234614 feat: uncap fps in fullscreen for lower input latency
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.
2026-04-11 06:19:22 -05:00
itsRevela 6c8f463707 fix: restore in-world rendering and aspect ratio via bitblt swap chain
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.
2026-04-11 02:49:53 -05:00
RevelaandGitHub b67889485f Remove Discord link from README
Removed Discord badge from README.
2026-04-11 02:09:48 -05:00
itsRevela 17eae2b41e chore: sync upstream MinecraftConsoles through d25b762c
Reviewed 8 upstream commits from smartcmd/MCLCE/MinecraftConsoles and recorded the result as a merge so GitHub stops reporting "behind upstream". All accepted changes were cherry-picked earlier in this branch, and this commit only absorbs the upstream commit SHAs as reachable ancestors using the "ours" merge strategy, so no tree changes come in from this commit itself.

Applied:
- 98a86fc6 feat: set intro scene background to white (#1474)
- 413baace fix: reorder autosave tick to account for weak hardware (#1482)
- d25b762c Fix _jeb easter egg on sheep (#1488)

Partially applied:
- d0786f95 Update more references to old smartcmd repo (credits reorganization and Star History URL applied, Nightly download URLs dropped since our fork has its own release pipeline, itsRevela added to Project Maintainers on top of upstream's restructure)

Already present:
- b928351e Update Windows64_Minecraft.cpp (#1468). Unicode WinAPI conversion was already applied during our Linux cross-compile work, so this was a no-op cherry-pick.
2026-04-11 02:06:01 -05:00
Tyler ReeseanditsRevela 7ea30d026c Fix _jeb easter egg on sheep (#1488)
Fixed the original jeb sheep behavior.

For some reason the later code (now commented out) just completely overrid it
2026-04-11 02:02:23 -05:00
itsRevela a07bc651b3 chore: sync credits screen and Star History with upstream org rename
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.
2026-04-11 02:01:26 -05:00
SylvessaanditsRevela aedb6125b6 fix: reorder autosave tick to account for weak hardware (#1482) 2026-04-11 01:52:58 -05:00
FirebladeanditsRevela 37ee04356b feat. set intro scene background to white (#1474) 2026-04-11 01:52:01 -05:00
itsRevela 28d997a8d0 chore: rename project from MinecraftConsoles to LCE-Revelations
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.
2026-04-11 01:38:35 -05:00
itsRevela a191df1f2e fix: controller cursor speed no longer scales with framerate
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
2026-04-10 21:38:43 -05:00
itsRevela 8f41d34325 fix: redirect AppContext.BaseDirectory to server root for FourKit plugins
AppContext.BaseDirectory pointed to the runtime/ subfolder where the
self-contained .NET payload lives, causing plugins that use it for file
paths to write to the wrong directory. Now set to the server exe
directory at startup via AppContext.SetData.

Also adds serverDirectory and dataDirectory properties to ServerPlugin
so plugin authors have convenient access to the server root and a
per-plugin data folder (plugins/<PluginName>/) without needing to
resolve paths manually.
2026-04-10 02:03:44 -05:00
itsRevela d14e46701c feat: add stress testing tool for dedicated server stability validation
Python-based bot tool that rapidly connects/disconnects to the server
using the full LCE protocol (PreLogin, Login, cipher handshake, identity
tokens, keepalive). Configurable concurrent bots, hold times, burst
joins, movement packets, and duration. Includes batch files for common
test scenarios (basic, aggressive, movement, burst, endurance).
2026-04-10 02:03:20 -05:00
itsRevela 20229fc07b fix: dedicated server thread safety, disconnect deadlock, and console freeze
- Protect PlayerList and ServerConnection players vectors with critical
  sections; all iterations use copy-on-read snapshots to prevent iterator
  invalidation during concurrent join/leave
- Add null check on player bounding box in movement validation to prevent
  crash when player is removed mid-tick
- Re-validate socket player pointer immediately before SendData to narrow
  the TOCTOU race window on disconnect
- Replace inline disconnect cleanup with a queued system drained on the
  main tick thread, eliminating the done_cs -> m_playersCS lock inversion
  that caused deadlocks under load
- Disable Windows QuickEdit mode at server startup to prevent console
  input selection from freezing the process
- Move chunk priority sort behind ServerConnection::sortPlayersByChunkPriority()
  to keep the players vector lock-protected
2026-04-10 01:12:59 -05:00
itsRevela 055bce517d docs: add Beacon Menu Fixes to Latest section in README 2026-04-09 21:58:29 -05:00
itsRevela 9c9df615a1 fix: beacon menu item consumption, data sync, and button state issues
- Prevent payment item from being consumed when submitting unchanged powers
- Reorder ServerPlayer::openBeacon to send ContainerOpenPacket before
  addSlotListener so beacon data packets arrive after the client menu is ready
- Add BeaconMenu::broadcastChanges() to continuously sync levels and powers
  to clients, matching the pattern FurnaceMenu already uses
- Initialize UIControl_BeaconEffectButton::m_lastState to prevent stale
  heap memory from suppressing Iggy ChangeState calls on menu re-entry
2026-04-09 21:34:48 -05:00
Tyler ReeseandGitHub d25b762ca5 Fix _jeb easter egg on sheep (#1488)
Fixed the original jeb sheep behavior.

For some reason the later code (now commented out) just completely overrid it
2026-04-08 22:34:48 -05:00
Revela 657fdd7108 Update Discord invite link in README 2026-04-08 14:00:53 -05:00
itsRevela d3b4713f00 docs: add feature summary blurb and Latest entries for Linux cross-compile and FourKit plugin support 2026-04-08 13:54:38 -05:00
RevelaandGitHub 1e1550a1b8 Update project description in README.md 2026-04-08 13:13:55 -05:00
RevelaandGitHub 1a98bc6a19 Update project title in README.md 2026-04-08 13:12:40 -05:00
itsRevela 71b1bf92b8 Revert "fix: tutorial world"
This reverts commit 222852c11b.
2026-04-08 13:00:44 -05:00
neoapps-dev 6fb106984a fix(build-linux): fourkit installation 2026-04-08 13:36:01 +03:00
neoapps-dev 6b63a808bb fix(build-linux): fourkit installation 2026-04-08 13:32:02 +03:00
neoapps-dev 25595fba71 fix(build-linux): silly me 2026-04-08 13:21:06 +03:00
neoapps-dev 0ddac15fad fix: linux cross-compiling 2026-04-08 13:07:04 +03:00
neoapps-dev 9babdac928 fix: linux cross-compiling 2026-04-08 12:44:56 +03:00
neoapps-dev 222852c11b fix: tutorial world 2026-04-08 12:21:09 +03:00
neoapps-dev de0ea474b1 chore: ignore .xwin 2026-04-08 12:19:12 +03:00
neoapps-dev ed18e26e85 feat: script for building 2026-04-08 12:09:32 +03:00
ryleuandneoapps-dev d449a582e4 add linux clang instructions 2026-04-08 12:05:43 +03:00
ryleuandneoapps-dev 5eab358dde add support for linux clang cross compiles 2026-04-08 12:03:15 +03:00
neoapps-dev b2f00d16e6 feat: cancel join 2026-04-08 11:47:25 +03:00
irice7andneoapps-dev d191bee468 Add cancel join
Adds the Cancel Join tooltip to the "Connecting to host"
progress bar
2026-04-08 11:47:01 +03:00
itsRevela 42a582fb9f feat: add FourKit plugin host with dual server build
Adds the FourKit .NET 10 plugin host as a second dedicated server
build flavour alongside the existing vanilla server. Both flavours
build from the same source tree, with FourKit gated by the
MINECRAFT_SERVER_FOURKIT_BUILD preprocessor define.

Build layout:

  Minecraft.Server         vanilla, no plugin support, no .NET dep
  Minecraft.Server.FourKit FourKit-enabled, ships with bundled
                           .NET 10 self-contained runtime in runtime/
                           and an empty plugins/ folder

Both produce a Minecraft.Server.exe in their own per-target output
dir. The variant identity lives in the directory name, not the
binary name, so either flavour can be shipped as a drop-in.

Native bridge (Minecraft.Server/FourKit*.{cpp,h}):

* FourKitRuntime: hosts CoreCLR via hostfxr's command-line init API
  (the runtime-config API does not support self-contained components)
* FourKitBridge: ~50 Fire* event entry points, with inline no-op
  stubs for the standalone build so gameplay code can call them
  unconditionally
* FourKitNatives: ~80 native callbacks the managed side invokes
  for player/world/inventory mutations
* FourKitMappers: type and enum mapping helpers

Managed plugin host (Minecraft.Server.FourKit/):

* Bukkit-style API: Player, World, Block, Inventory, Command,
  Listener, EventHandler attribute, ~54 event classes
* PluginLoader with per-plugin AssemblyLoadContext
* FourKitHost as the [UnmanagedCallersOnly] entry point table
* Runtime resolves plugins relative to the host process so they
  always live next to Minecraft.Server.exe regardless of where the
  managed assembly itself is loaded from

Engine hooks (Minecraft.Client/, Minecraft.World/):

* Player lifecycle (PreLogin, Login, Join, Quit, Kick, Move,
  Teleport, Portal, Death) wired into PendingConnection and
  PlayerConnection without disturbing the cipher handshake or
  identity-token security flow
* Inventory open/click/drop hooks across every container menu type
* Block place/break/grow/burn/spread/from-to hooks across the
  full tile family
* Bed enter/leave, sign change, entity damage/death, ender pearl
  teleport hooks

Regression fixes preserved while applying donor diffs:

* ServerPlayer::die() retains the LCE-Revelations hardcore branch
  (setGameMode(ADVENTURE) + banPlayerForHardcoreDeath) in both the
  FourKit and non-FourKit code paths
* ServerLevel::entityAdded() retains the sub-entity ID reassignment
  loop required by the client's handleAddMob offset, fixing Ender
  Dragon and Wither boss multi-part hit detection
* LivingEntity::travel() retains the raw Player* cast and the
  cached frictionTile, both Revelations perf wins that the donor
  silently reverted
* ServerLogger.cpp keeps the file-logging code donor stripped
* PlayerList.cpp end portal transition fix and UIScene_EndPoem
  bounds-check are intact

Build system:

* Top-level CMakeLists.txt adds the Minecraft.Server.FourKit
  subdirectory and pulls in the new shared cmake/ServerTarget.cmake
  helper
* Minecraft.Server/cmake/sources/Common.cmake is now location
  independent (uses CMAKE_CURRENT_LIST_DIR) so the source list
  can be consumed from either server target's CMakeLists.txt
* The seven FourKit*.cpp/h files live in their own
  _MINECRAFT_SERVER_COMMON_SERVER_FOURKIT variable so the
  standalone target omits them
* configure-time .NET 10 SDK check fails fast with a clear
  download link if the SDK is missing
* global.json pins the SDK to 10.0.100 with latestFeature
  rollforward

Sample plugin (samples/HelloPlugin/) demonstrates the loader and
the PlayerJoinEvent listener pattern.

CI:

* nightly.yml builds both server flavours, ships
  LCE-Revelations-Server-Win64.zip and
  LCE-Revelations-Server-Win64-FourKit.zip, attests both, and
  updates release notes for the dual-flavour layout
* pull-request.yml pulls in actions/setup-dotnet so the FourKit
  publish step works in PR validation
* All zip artifacts and the client zip are renamed from
  LCREWindows64 to LCE-Revelations-{Client,Server}-Win64

Documentation:

* COMPILE.md gets a VS 2022 quick start, .NET 10 prereq section,
  server flavours explanation, and a troubleshooting section
* docs/FOURKIT_PORT_RECON.md captures the file-by-file recon that
  drove the port
* docs/FOURKIT_PARITY.md is the canonical reference for which
  events FourKit fires

Docker:

* docker-compose.dedicated-server.yml MC_RUNTIME_DIR default points
  at the vanilla CMake output. The FourKit Docker image is
  intentionally NOT shipped yet because hosting .NET 10 self
  contained inside Wine has not been smoke-tested
2026-04-08 03:02:48 -05:00
itsRevela 5d56f5080f chore: rename LCRE branding to LCE-Revelations
Renames release artifacts, Docker image, container/service names,
and shell wrappers from the legacy LCRE prefix to LCE-Revelations.

* Banner asset: LCRE-banner.png to LCE-Revelations-banner.png
* Docker compose service and container: minecraft-lce-dedicated-server
  to lce-revelations-dedicated-server
* ghcr image: ghcr.io/itsrevela/minecraft-lce-dedicated-server to
  ghcr.io/lce-hub/lce-revelations-dedicated-server
* Dockerfile MC_RUNTIME_DIR default points at the CMake build output
  path now that the legacy x64/ MSBuild path is no longer produced
* README and helper shell scripts updated to match

Workflow rename for nightly.yml release notes is folded into the
FourKit commit because the FourKit CI changes overwhelm the diff.
2026-04-08 02:30:58 -05:00
Loki Rautio d0786f956d Update more references to old smartcmd repo 2026-04-07 20:29:32 -05:00
LokiandGitHub 126943e06e Add details about org change to README 2026-04-07 17:44:00 -05:00
LokiandGitHub 108e3dc233 Whitespace adjustment to test GitHub webhook 2026-04-07 15:52:48 -05:00
/home/neoandGitHub 29ebc01ea9 feat: TU19 tutorial world (#1) 2026-04-07 22:42:22 +03:00
LokiandGitHub 29edc4aff0 Link to new Discord 2026-04-07 14:31:30 -05:00
/home/neoandGitHub 7149e696f2 docs: discord server link 2026-04-07 22:04:22 +03:00
RevelaandGitHub 078e661b91 Update README to include Unity-LCE Discord server link
Removed Fluxer server link and added Discord badge.
2026-04-07 13:43:05 -05:00
RevelaandGitHub a07d791683 Update project name in README.md
temporary
2026-04-07 13:37:38 -05:00
itsRevela 77fbf36f54 chore: remove 'why this fork exists' section from release notes 2026-04-07 13:35:32 -05:00
rucheykovandGitHub b928351e0b Update Windows64_Minecraft.cpp (#1468) 2026-04-06 12:34:25 -05:00
SylvessaandGitHub 413baaceed fix: reorder autosave tick to account for weak hardware (#1482) 2026-04-06 12:34:02 -05:00
FirebladeandGitHub 98a86fc69b feat. set intro scene background to white (#1474) 2026-04-06 12:33:45 -05:00
itsRevela 37d1942033 chore: remove nightly server release workflow 2026-04-05 18:37:50 -05:00
itsRevela 6728ecb141 fix: increase max packet size to 4MB for cross-fork compatibility
Matches the packet size limit used by the plugin-api fork. Our 512KB
limit caused "Connection lost" when their server sent large packets
(e.g. chunk data) that exceeded our cap.
2026-04-05 18:35:28 -05:00
itsRevela ca5dbe1c9c revert: remove skipped upstream changes brought in by merge
Reverts workflow revert (#c4c4c08b), BACKPORTING.md (#5e584910),
and CONTRIBUTING.md backporting link (#7dfe46aa) that were
unintentionally included via the upstream merge commit.
2026-04-05 16:25:49 -05:00
itsRevela e52565f9a3 Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	.github/workflows/nightly-server.yml
#	Minecraft.Server/Windows64/ServerMain.cpp
#	Minecraft.World/ConsoleSaveFileOriginal.cpp
2026-04-05 16:23:28 -05:00
itsRevela 38250cc51b docs: update README for upstream merges and chunk loading optimization 2026-04-05 16:20:30 -05:00
SylvessaanditsRevela 207a1b309f optimization: async dedicated server autosaving (#1473) 2026-04-05 16:17:01 -05:00
SylvessaanditsRevela 2f3cf58c3c optimization: remove redundant lastTime setter (#1479) 2026-04-05 16:14:13 -05:00
SylvessaanditsRevela d758eb887f fix: wither and ender dragon custom names (#1472) 2026-04-05 16:11:56 -05:00
Us3ful"-DevanditsRevela 931b5e9dcb Quality of life netherportal fix (#1337)
* Working New portal checks

fixed x axis portal with obsidian on z axis

* Removed Debug code

* Remove unnecessary code

removed PortalTile:: from PortalTile::validPortalFrame

* Remove more debug code
2026-04-05 16:08:57 -05:00
SylvessaanditsRevela 4e6c695899 fix: boat plr height & sneak height (#1459) 2026-04-05 16:08:17 -05:00
Logan GibsonanditsRevela c0a2e82223 Replace instances of hard-coded port in ports variable with SERVER_PORT variable in yml files (#1457) 2026-04-05 16:07:06 -05:00
SneexyanditsRevela 446df4a6dc Minor docker/container fixes and edits (#1454) 2026-04-05 16:05:40 -05:00
itsRevela 207d90de28 perf: process 16 chunks/player/tick on dedicated server, revert async save
Chunk loading now batches up to 16 nearest-first requests per player per
tick on dedicated server (client stays at 1), improving tick recovery
time after player join.

Reverts the async save system -- the background thread snapshot/compress
path added complexity without measurable benefit. Autosave on Windows64
server now uses the standard synchronous flush like client, in
preparation for a proper async implementation from upstream.
2026-04-05 15:56:39 -05:00
itsRevela be17d4028f feat: add performance monitor tool
DLL injector + Python GUI for real-time server metrics.
Hooks into tick loop, chunk generation, and player chunk map
to collect timing data over TCP, displayed in a tkinter dashboard.
Includes bot spawner for load testing.
2026-04-05 15:49:52 -05:00
SylvessaandGitHub 034c313ddf optimization: async dedicated server autosaving (#1473) 2026-04-05 12:57:43 -05:00
SylvessaandGitHub c2ea1fa62b optimization: remove redundant lastTime setter (#1479) 2026-04-05 12:51:37 -05:00
SylvessaandGitHub a4e689095c fix: wither and ender dragon custom names (#1472) 2026-04-04 22:04:02 -05:00
LokiandGitHub 7dfe46aa5d Add backporting link to Contributor's Guide 2026-04-03 16:56:05 -05:00
LokiandGitHub 5e5849102f Add info about backports we will accept. 2026-04-03 16:55:20 -05:00
Us3ful"-DevandGitHub 103f38859a Quality of life netherportal fix (#1337)
* Working New portal checks

fixed x axis portal with obsidian on z axis

* Removed Debug code

* Remove unnecessary code

removed PortalTile:: from PortalTile::validPortalFrame

* Remove more debug code
2026-04-03 15:01:48 -05:00
SylvessaandGitHub 8bf0343544 fix: boat plr height & sneak height (#1459) 2026-04-02 17:16:31 -05:00
Logan GibsonandGitHub e4c08b8414 Replace instances of hard-coded port in ports variable with SERVER_PORT variable in yml files (#1457) 2026-04-02 02:43:33 -05:00
SylvessaandGitHub c4c4c08b96 Revert "Update actions workflows and add clang format check for PRs (#1418)"
This reverts commit 38d58f2d8b due to it causing spam and other problems with pull requests.
2026-04-02 00:01:27 -05:00
SneexyandGitHub c2356bf29e Minor docker/container fixes and edits (#1454) 2026-04-01 19:10:47 -05:00
itsRevela 463bf2b93f fix: player list no longer limited by render distance
The previous IQNet cleanup in handleRemoveEntity fired on every entity
despawn, which happens both when a player goes out of tracking range
and when they disconnect.  This caused players to vanish from the Tab
list whenever they moved beyond render distance.

Introduce two custom payload channels (MC|ForkHello, MC|ForkPLeave) so
the client can distinguish "out of range" from "actually left":

- Server sends MC|ForkHello during login to identify itself as a fork
- Server sends MC|ForkPLeave with the player's gamertag on disconnect
- Client skips IQNet cleanup in handleRemoveEntity on fork servers
- Client cleans up IQNet only when MC|ForkPLeave arrives

Fully backwards-compatible: no existing packet wire formats changed.
Upstream clients ignore the unknown channels, fork clients on upstream
servers fall back to the old entity-tracking-based cleanup.
2026-04-01 16:01:56 -05:00
itsRevela 8e2b475317 removed backup arc file 2026-04-01 03:50:21 -05:00
itsRevela a017579bc3 fix: graphics menu navigation, layout, render distance cap, skin anim speed
Rewire the SWF focus chain via Iggy so VSync, Fullscreen, and Render
Distance are reachable with keyboard/gamepad navigation.

Cap render distance slider at 16 chunks. Shift graphics menu layout
up 60px for better centering.

Fix skin preview walk/attack animations running too fast with VSync
off by scaling per-frame increments by delta time relative to 60fps.
2026-04-01 03:43:28 -05:00
itsRevela 2cc03476b3 fix: skin preview animations too fast with VSync off
The walking and attack animations in the Change Skin menu were
frame-rate-dependent, advancing per render call with no delta time
scaling. With uncapped FPS they ran proportionally too fast.

Add time-based scaling relative to a 60fps baseline. The scale is
computed once per frame (cached for 0.5ms) so multiple skin previews
rendered in the same frame all animate at the correct speed.
2026-04-01 02:24:45 -05:00
itsRevela 9372b2d2ea fix: move async save commit off game thread to prevent disk I/O stall
StorageManager.SaveSaveData() blocks until the disk write completes.
Calling it from the game thread caused 2.5s freezes. Now it only runs
from TickCoreSystems() on the ServerMain thread, which operates
independently of the game tick loop.
2026-04-01 01:49:58 -05:00
itsRevela 68521f8c92 fix: async autosave thread safety and commit path
Move StorageManager.AllocateSaveData() back under the save lock (called
on the game thread before releasing). Background thread now only does
pure zlib compression with no StorageManager calls.

Add CommitPendingAsyncSave() to both the game thread tick and
TickCoreSystems() to ensure saves commit during bootstrap, normal
gameplay, and shutdown.
2026-04-01 01:23:50 -05:00
itsRevela 073a511217 perf: async autosave for dedicated server
Autosave previously froze the main thread for 2-6 seconds while
compressing the entire save file with zlib. Now the save buffer is
snapshotted under the lock (~18ms), then compression runs on a
background thread. The compressed data is committed to StorageManager
on the next main-thread tick via CommitPendingAsyncSave().

Also skip redundant full chunk saves during autosave on the dedicated
server -- chunks are already persisted by the per-tick trickle save.
Only entity data is flushed, matching Xbox/Orbis behavior.

Added per-step timing to the autosave handler for diagnostics.
2026-03-31 23:33:21 -05:00
itsRevela 450891d8c4 docs: add entity tracker optimization to README 2026-03-31 22:12:18 -05:00
itsRevela ea15409bb9 perf: skip split-screen system-mate checks on dedicated server
The EntityTracker and TrackedEntity classes have O(players^2 * entities)
loops that check IsSameSystem() for split-screen couch co-op visibility
expansion. On the dedicated server, all players are remote so
IsSameSystem() always returns false, making these loops pure overhead.

Skip them entirely when g_Win64DedicatedServer is true. The original
split-screen logic is preserved for game client LAN hosting.
2026-03-31 22:07:41 -05:00
itsRevela aecef7f10d fix: move security gate close after login sequence to prevent high-latency crashes
The security gate was closed before LoginPacket was sent in placeNewPlayer,
causing all login setup packets to be buffered behind the cipher handshake.
Under high-latency connections, the flushed data arrived before the player
object was initialized, causing a null pointer crash. The gate now closes
after the login sequence and MC|CKey are sent.
2026-03-31 17:28:03 -05:00
RevelaandGitHub d5fafb74e8 Fix typo in graphics settings section of README
Corrected a typo in the README regarding spacing error.
2026-03-30 17:01:30 -05:00
itsRevela 383c710833 feat: uncapped FPS when VSync off, fix graphics settings bitmask collision
Bypass the 4J RenderManager's hardcoded SyncInterval=1 by calling
the DXGI swap chain directly with Present(0, ALLOW_TEARING) when
VSync is disabled. Falls back to the library's Present on failure.

Relocate VSync/Fullscreen setting flags from bits 18-19 to bits 24-25
to eliminate overlap with the render distance byte (bits 16-23).

Sync the Fullscreen game setting when F11 is pressed so the graphics
menu checkbox stays accurate.

Remove tracked DumpSwf.class (already covered by tools/*.class gitignore).
2026-03-30 15:36:08 -05:00
itsRevela 9f08612f25 fix: graphics settings layout broken by removeControl on Windows64
BedrockFog removal via removeControl with centreScene=true triggered
Flash-side repositioning that didn't account for the tool-added VSync
and Fullscreen checkboxes, creating a gap after CustomSkinAnim and
causing RenderDistance to render behind Gamma.

On Windows64 (single player per client), the console splitscreen
host-check that removed BedrockFog/CustomSkinAnim is unnecessary.
Gate it behind #ifndef _WINDOWS64 so all controls stay visible.
2026-03-30 14:10:50 -05:00
itsRevela 4e323c8365 merge: upstream fix for world seeds not saving correctly (#1119) 2026-03-30 13:53:17 -05:00
itsRevela 3aa2d23fa9 feat: implement hardcore hearts with game mode lock
Display hardcore heart textures when a world is in hardcore mode,
matching Java Edition behavior. Hearts switch between normal/hardcore
across all states (poison, wither, flash) and all HUD resolutions.

C++ changes:
- IUIScene_HUD: check isHardcore() and call SetHardcoreMode() each tick
- UIScene_HUD: send hardcore boolean to Flash via Iggy, invalidate
  SetHealth dirty check on state change to force heart redraw
- CreateWorldMenu/LoadMenu: lock game mode to Survival when hardcore
- MinecraftServer: gate server.properties hardcore override behind
  MINECRAFT_SERVER_BUILD so offline worlds preserve their saved flag

SWF changes (via new Java tools):
- AddHardcoreBitmaps: adds 10 hardcore heart bitmaps to graphics SWFs
- AddHardcoreHearts: adds 10 new frames (15-24) to health sprite
- PatchHudABC: patches HUD ActionScript bytecode with SetHardcore
  method and frame offset logic (+14 normal/poison, +6 wither)

Also updates README changelog styling with consistent ### headings.
2026-03-30 13:50:29 -05:00
blongmandGitHub d3412aaae7 Fixed issue with world seeds not saving correctly (#1119)
## Description
Fix issue where typing in a short seed on world creation doesn't save the seed correctly

## Changes

### Previous Behavior
Typing in a seed on the world creation menu that's less than 8 characters long will result in garbage data being saved as the seed. Happens with controller and KBM.
You can see this in-game - if you exit the world options menu and go back in, the seed will show up as boxes □□□.
Weirdly, if you type a seed again, it behaves as expected.

### Root Cause
For some reason, assigning `m_params->seed` to the seed text points it to garbage data, when it's 7 characters or less.

### New Behavior
Seed entry behaves as expected.

### Fix Implementation
- Added `static_cast<wstring>` before assignment to `m_params->seed`.
- Also replaced `(wchar_t *)` with `reinterpret_cast<wchar_t*>` in the functions.

### AI Use Disclosure
No AI was used
2026-03-30 06:05:32 -05:00
itsRevela a4f55dde16 chore: add LCRE banner, SWF/ARC tools, ignore build artifacts
Replace README banner with LCRE-banner.png. Add SWF inspection
and ARC archive tools. Ignore compiled .class, .swf intermediates,
and staging directory in tools/.
2026-03-29 21:14:34 -05:00
itsRevela 967adf1e54 feat: make F2 screenshot work in any context
Move screenshot capture from Minecraft::tick() (which requires an
active player) to the Windows64 main loop alongside other global
key handlers (F1/F3/F11). F2 now works from the main menu, pause
menu, settings, inventory, crafting, and all other screens. Chat
message still shown when in-game.
2026-03-29 19:30:00 -05:00
itsRevela f2434a8ea8 feat: use full-size LCRE logo shifted up 10px
Replace the 80% scaled approach with full-size logo bitmaps and
shift the ComponentLogo SWF placements up by 10px (proportionally
scaled for lower resolutions) to avoid occlusion by the load/join
menu. Add ShiftLogo.java tool for adjusting SWF placement offsets.
2026-03-29 19:10:14 -05:00
itsRevela 4a8291f6cc feat: replace Minecraft logo with LCRE logo at 80% scale
Replace MenuTitle and MenuTitleSmall bitmaps in skinHDWin.swf and
skinWin.swf with the custom LCRE (Legacy Console Edition Revelations)
logo, scaled to 80% within the original bitmap canvas to avoid
occlusion by the load/join menu.

Add ReplaceLogo.java and ExtractFromArc.java tools for SWF bitmap
replacement and arc file extraction. Keep original arc as .bak.
2026-03-29 19:00:50 -05:00
itsRevela b8cfd62cdf fix: sign correct tag for dedicated server release 2026-03-29 17:14:43 -05:00
itsRevela 97a1459929 feat: GPG-sign release tags for verified badge
Use crazy-max/ghaction-import-gpg to sign Nightly and
Nightly-Dedicated-Server tags with a GPG key so releases
show the green Verified badge on GitHub.
2026-03-29 14:47:53 -05:00
itsRevela 45987849b8 fix: add checkout to release jobs for gh cli 2026-03-29 14:29:06 -05:00
itsRevela 91e8b9cef4 fix: heredoc indentation and cleanup-tag without checkout
Remove --cleanup-tag (requires local git repo). Delete tags via API
instead. Fix heredoc terminators for release notes.
2026-03-29 14:21:05 -05:00
itsRevela cf7cd32116 feat: use GitHub API for signed release tags
Replace andelf/nightly-release with gh CLI commands that create tags
via the GitHub API, which auto-signs them with the github-actions bot
key for the green Verified badge.
2026-03-29 14:13:19 -05:00
itsRevela b3db1da8cb fix: set prerelease to false for nightly releases 2026-03-29 13:57:36 -05:00
itsRevela c405ee9036 fix: use correct release tags and client description
Use capitalized tags (Nightly, Nightly-Dedicated-Server) to match
existing releases. Restore full client release body with instructions,
multiplayer setup, and fork explanation.
2026-03-29 13:56:29 -05:00
itsRevela 0fd15d360f feat: consolidate nightly workflows with signed builds
Merge client and server nightly releases into a single workflow.
Add artifact attestation for signed builds. Use CMake instead of
MSBuild. Preserve LCRE naming, top-level zip folders, and commit
hash release titles.
2026-03-29 13:46:18 -05:00
itsRevela 59fd7266b6 Merge upstream/main (skip CI workflow changes) 2026-03-29 01:03:35 -05:00
rtm516andGitHub 38d58f2d8b Update actions workflows and add clang format check for PRs (#1418)
* Add clang-format workflow for pull request checks

* Modify push paths in nightly workflow

Updated paths for push event to include all files except specified ones.

* Update paths for nightly-server workflow triggers

* Modify paths for pull request triggers

Update pull request workflow to include specific paths.

* Tidy up clang-format installation in workflow
2026-03-28 23:35:25 -05:00
itsRevela 245da783b3 feat: upgrade stream cipher from XOR to AES-128-CTR
Replace the XOR obfuscation cipher with AES-128-CTR using the Windows
BCrypt API. Key material grows from 16 to 32 bytes (16 AES key + 16 IV).
All callers auto-adjust via StreamCipher::KEY_SIZE. No handshake or
protocol changes needed beyond the larger MC|CKey payload.
2026-03-28 21:03:45 -05:00
RevelaandGitHub 1036c360dc Merge branch 'smartcmd:main' into main 2026-03-28 19:19:42 -05:00
itsRevela ba3ebe666c feat: dedicated server security hardening
Comprehensive security system to protect against packet-sniffing attacks,
XUID harvesting, privilege escalation, bot flooding, and XUID impersonation.

- Stream cipher: per-session XOR cipher with 4-message handshake via
  CustomPayloadPacket (MC|CKey, MC|CAck, MC|COn). Negotiated per-connection,
  backwards compatible (old clients/servers fall back to plaintext).
- Security gate: buffers all game data until cipher handshake completes,
  preventing unsecured clients from receiving any XUIDs or game state.
- Cipher handshake enforcer: kicks clients that don't complete the handshake
  within 5 seconds (configurable via require-secure-client).
- Identity tokens: persistent per-XUID tokens in identity-tokens.json,
  issued over the encrypted channel, verified on reconnect. Prevents XUID
  replay attacks. Client stores server-specific tokens.
- PROXY protocol v1: parses real client IPs from playit.gg tunnel headers
  so rate limiting, IP bans, and XUID spoof detection work per-player.
- Rate limiting: per-IP sliding window (default 5 connections/30s) with
  pending connection cap (default 10).
- Privilege hardening: OP requires ops.json, live checks on every command
  and privilege packet. Host-only server settings changes.
- XUID stripping: PreLoginPacket response sends INVALID_XUID placeholders.
- Packet validation: readUtf global string cap, reduced max packet size,
  stream desync protection on oversized strings.
- OpManager: persistent ops.json with XUID-based OP list.
- Whitelist improvements: whitelist add accepts player names with ambiguity
  detection, XUID cache from login attempts.
- revoketoken command: revoke identity tokens for players who lost theirs.
- server.log: persistent log file written alongside console output with
  flush-per-write to survive crashes.
- CLI security logging: consolidated per-join security summary with cipher
  status, token status, XUID, and real IP. Security warnings for kicks,
  spoofing, and unauthorized commands.
2026-03-28 19:18:06 -05:00
BotchandGitHub 277d74716e Render custom skin boxes on viewmodel (#1415)
* Update PlayerRenderer.cpp

* Fix fatal bug where skins with no additional boxes would crash the game
2026-03-28 14:44:27 -05:00
RevelaandGitHub ed3fffcc6a Merge branch 'smartcmd:main' into main 2026-03-27 16:42:40 -05:00
SestainandGitHub 7447fabe0d Fix game crashing if DLC has XMLVERSION paramater (#1285)
* Fix game crashing if DLC has XMLVERSION paramater

* Better implementation of XMLVersion check

* Forgot to add type name to the list

* Removed extra newline
2026-03-27 15:11:27 -05:00
SestainandGitHub 3c1166c45e Added support for Big-Endian DLCs (#1291)
* Added support for Big-Endian DLCs

* Remove unused variable

* Remove the things made for other PR
2026-03-27 15:59:35 -04:00
RevelaandGitHub 4e678fbf6b Merge branch 'smartcmd:main' into main 2026-03-27 00:55:24 -05:00
LokiandGitHub 0d4874dea5 Clarify Android support in README 2026-03-27 00:29:08 -05:00
itsRevela f1ec7a0d20 Send AddPlayerPacket for all players on join and RemoveEntitiesPacket on disconnect
Players now appear in each other's Tab list immediately on join,
regardless of render distance. Previously, players only appeared when
they entered entity tracking range because AddPlayerPacket was only
sent through the TrackedEntity system.

On disconnect, a RemoveEntitiesPacket is broadcast to all clients so
players added via the join broadcast are properly cleaned up, not just
those within tracking range.
2026-03-26 23:55:02 -05:00
itsRevela 1b423e48d3 Fix player list map icon colors to match map markers
The tab player list and teleport menu now show the correct map marker
color for each player. The icon is computed using the same hash as the
map renderer (getRandomPlayerMapIcon) and stored by player name,
bypassing the unreliable small-ID lookup that produced wrong colors
on dedicated servers.
2026-03-26 22:22:13 -05:00
itsRevela 35fbc7af17 Fix Ender Dragon damage, End portal transition, and End Poem crash
Dragon melee damage: reassign sub-entity IDs to be sequential from
the parent entity ID in ServerLevel::entityAdded(), so the client's
offset-based ID calculation matches the server. Previously the server's
smallId pool allocated non-sequential IDs, causing melee attacks to
target entity IDs the server didn't recognize.

End portal transition: ensure the player entity is always added to the
new level when transitioning from The End, not just for non-End
dimensions. The addEntity call was previously gated behind a
lastDimension != 1 check that also excluded it from End exits.

End Poem crash: bounds-check the WIN_GAME event's player index before
accessing localplayers[], with a fallback to prevent null dereference
when the server sends an out-of-range index.
2026-03-26 19:46:58 -05:00
itsRevela 2e75441355 Merge upstream: fix redstone tick persistence on chunk unload 2026-03-26 18:22:04 -05:00
itsRevela 6a21637e75 Fix player list not showing all players on dedicated servers
Register remote players in the client's IQNet array when their
AddPlayerPacket arrives, so they appear in the Tab player list.
Previously only the host and local player were registered.

Also filter the dedicated server's phantom host entry (slot 0, empty
gamertag) from the UI, fix tick() to update entries by smallId instead
of sequential index, and fix player removal to use gamertag matching
since XUIDs are 0 on dedicated servers.
2026-03-26 18:20:01 -05:00
666uvuandGitHub 73d713878c fix redstone tick persistence on chunk unload (#1423) 2026-03-26 16:55:56 -05:00
itsRevela d292190aae Skip upstream piston fix #1420 (already applied in this fork) 2026-03-26 15:49:50 -05:00
itsRevela fbe14e7755 Add SRV record support for server connections
Resolve _minecraft._tcp.<hostname> SRV records before connecting,
matching Java Edition behavior. Players can connect using just a domain
name and the client will look up the actual server address and port
from DNS. Falls back to the original hostname/port if no SRV record
exists or the address is a numeric IP.
2026-03-26 15:45:24 -05:00
RevelaandGitHub 4f370c45e3 Fix pistons permanently breaking server-wide on dedicated servers (#1420)
triggerEvent() set ignoreUpdate to true at the start but three early
return paths skipped the reset at the end. Once any of these paths was
hit, the TLS flag stayed true permanently, blocking all piston neighbor
updates for the rest of the server session.
2026-03-26 15:16:15 -05:00
itsRevela f1310abe08 Refactor async server joining with eJoinState enum and dedicated progress UI
Replace the boolean-flag-based async join system with a clean state machine
(eJoinState enum) and move connection progress handling from UIScene_JoinMenu
into UIScene_ConnectingProgress as a dedicated UI class.

Combines the best of two approaches: non-blocking sockets with select()
timeout and SO_RCVTIMEO clearing (prevents random disconnects) with the
upstream's state enum, FinalizeJoin separation, and ConnectingProgress UI.

JoinGame() now returns JOINGAME_PENDING on Win64, and
PlatformNetworkManagerStub::DoWork() polls the join state to finalize
the connection when the background thread succeeds.
2026-03-26 11:51:17 -05:00
itsRevela 39b0ad1cb4 Merge upstream: skip async joining #1408 (already implemented), splitscreen XUID fix cherry-picked 2026-03-26 11:07:35 -05:00
SylvessaanditsRevela 1ae70176d4 fix splitscreen xuids (#1413) 2026-03-26 11:07:30 -05:00
itsRevela f2fb995c84 Fix pistons permanently breaking server-wide on dedicated servers
triggerEvent() set ignoreUpdate to true at the start but three early
return paths (lines 221, 225, 250) skipped the reset at the end. Once
any of these paths was hit (common with fast redstone clocks where the
signal state changes between event queuing and processing), the TLS
flag stayed true permanently, blocking all piston neighbor updates for
the rest of the server session.
2026-03-26 10:40:43 -05:00
SylvessaandGitHub c96a8ee524 fix splitscreen xuids (#1413) 2026-03-26 10:19:20 -04:00
SylvessaandGitHub 1a50770647 Add asynchronous server joining (#1408) 2026-03-26 10:15:11 -04:00
RevelaandGitHub deb10de463 Update README for fork title change
MinecraftConsoles (Legacy Console Revelations Edition)
LCRE
2026-03-26 02:46:08 -05:00
itsRevela c0085a8336 Skip upstream revert of chunk unload commit (already fixed properly in this fork) 2026-03-26 02:33:32 -05:00
Loki Rautio dee559bd16 Revert "Memory leak fix: Make chunks unload properly (#1406)"
This reverts commit a24318eedc.
This fix introduces broken behavior for dedicated servers. It will be
merged back in once the related issue is fixed
2026-03-26 01:37:23 -05:00
itsRevela 13372692d5 change foldernames & filenames (LCRE) in release update script 2026-03-25 23:56:48 -05:00
itsRevela 6d28177e4c Fix client disconnect from leftover socket recv timeout
Clear the 5-second SO_RCVTIMEO that was set during the connection
handshake but never removed. The timeout persisted into the game
session, causing the client to disconnect whenever the server paused
for longer than 5 seconds (e.g. autosave, chunk I/O).

Also update README with chunk unloading and connection stability fixes.
2026-03-25 23:54:52 -05:00
itsRevela c264262b66 Fix chunk unloading regression from upstream merge
Commit a24318ee changed drop() to immediately remove chunks from cache,
bypassing the deferred m_toDrop save/unload pipeline. This caused missing
chunks on dedicated servers, iterator invalidation in dropAll() and
ServerLevel::save(), and entity duplication (item frames) from chunks
being reloaded without their entities first being removed from the level.

- ServerChunkCache::drop(): restore m_toDrop queue instead of immediate
  cache removal, so tick() can save/unload/move to unloadedCache safely
- MultiPlayerChunkCache::drop(): restore soft-unload (keep chunk in cache
  with loaded=true) instead of nulling cache and hasData
- PlayerChunkMap::setRadius(): remove dropAll() call when reducing radius,
  the per-chunk removal loop already handles out-of-range chunks
2026-03-25 19:57:35 -05:00
RevelaandGitHub 3a8106593f Merge branch 'smartcmd:main' into main 2026-03-25 10:58:16 -05:00
ModMaker101andGitHub a24318eedc Memory leak fix: Make chunks unload properly (#1406)
* Fix chunk unload and cleanup logic, fixes #1347

* Applying formatting to code I edited 😝
2026-03-24 23:25:18 -05:00
RevelaandGitHub 4c7f1a6385 Merge branch 'smartcmd:main' into main 2026-03-24 13:59:56 -05:00
itsRevela 2637577a62 Remove emdashes from README 2026-03-24 13:08:11 -05:00
itsRevela 08f14e32ae Add seed validation for server world creation and override-seed property
The dedicated server previously picked a completely random seed with no
biome diversity checks (the client validates but the server skipped it).
On top of that, the client's findSeed() was hardcoded to only check a
54-chunk (Classic) area, so Large worlds had no diversity guarantee
beyond the center.

New server worlds now use findSeed() scaled to the full target world
size. Added override-seed in server.properties to fix existing worlds
without deleting them.
2026-03-24 13:07:04 -05:00
itsRevela 5dad6c24f7 Fix server list refresh and add cancellable non-blocking connection
Server list: edits and deletions now update the UI immediately by
calling SearchForGames() in ForceFriendsSessionRefresh() and
UpdateGamesList() on nav-back to LoadOrJoinMenu.

Connection: moved WinsockNetLayer::JoinGame() to a background thread
with non-blocking sockets (5s timeout, 3 retries). Users can cancel
with B/Escape during the attempt. Failed connections always show an
error dialog.
2026-03-24 11:30:14 -05:00
SylvessaandGitHub 993052409a Fix XUID logging (#1395)
* pass invalid_xuid to other players

* actually more simple fix
2026-03-24 05:04:07 -04:00
Ayush ThorenandGitHub ed9cbae3f7 Fix initial cursor position for in-game UI elements (#1120)
Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-23 21:06:20 -05:00
SylvessaandGitHub daed75b8a1 make handleParticleEvent actually parse the particle type instead of hardcoding hearts (#1399) 2026-03-23 20:11:37 -05:00
rtm516andGitHub 9e715cb3bc Fix render order of F3 debug screen (#1239) 2026-03-23 18:01:40 -05:00
SylvessaandGitHub 127465b0eb add advanced tooltips, F3+H combo, and handle settings (#1389) 2026-03-23 17:54:46 -05:00
itsRevela d4d5ffe403 Fix archive path for new Windows username 2026-03-23 12:34:32 -05:00
itsRevela dd4b76d02a Disable automatic release on push for nightly-server workflow 2026-03-23 12:33:48 -05:00
itsRevela e1446953c4 Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	CMakeLists.txt
#	Minecraft.Client/CMakeLists.txt
#	Minecraft.Client/ClientConnection.cpp
#	Minecraft.Client/Common/Media/MediaWindows64.arc
#	Minecraft.Client/Common/UI/UIControl_TextInput.cpp
#	Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp
#	Minecraft.Client/Gui.cpp
#	Minecraft.Client/PlayerList.cpp
#	Minecraft.Client/ServerPlayerGameMode.cpp
#	Minecraft.Client/Windows64/KeyboardMouseInput.h
#	Minecraft.Client/Windows64Media/strings.h
#	Minecraft.Client/cmake/sources/Windows.cmake
#	Minecraft.Server/CMakeLists.txt
#	Minecraft.Server/ServerProperties.cpp
#	Minecraft.Server/ServerProperties.h
#	Minecraft.Server/Windows64/ServerMain.cpp
#	Minecraft.Server/cmake/sources/Common.cmake
#	Minecraft.World/cmake/sources/Common.cmake
#	README.md
2026-03-23 12:29:00 -05:00
itsRevela cbc0617dcd Update README with upstream merge features 2026-03-23 12:22:03 -05:00
itsRevela 58c73d1052 Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	Minecraft.Client/Common/Media/MediaWindows64.arc
#	Minecraft.Client/Common/UI/UIControl_TextInput.cpp
2026-03-23 12:12:37 -05:00
itsRevela 712ae60a6f Fix unicode glyph color in per-vertex font rendering path
The upstream font color fix (commit be7e2ca9) switched from glColor4f to
per-vertex t->color() but renderUnicodeCharacter() still relied on glColor4f.
Set glColor4f to currentColor before rendering unicode glyphs and restore
white after, and re-apply t->color() when resuming the batched draw.
2026-03-23 12:09:57 -05:00
itsRevela 3ea2eda597 Fix: CMP0057 policy was not set (#1367) 2026-03-23 11:58:13 -05:00
itsRevela 93532ef533 Stained Glass Survival Integration & Crafting UI Fix (#1195) 2026-03-23 11:58:13 -05:00
itsRevela d446985f12 Add clipboard paste support to UIControl_TextInput and UIScene_Keyboard (#1298)
Resolved conflicts with existing fork paste implementation - adopted upstream's
batch sanitize-then-insert approach over char-by-char insertion.
2026-03-23 11:57:59 -05:00
itsRevela 33a3d69fc8 Clicking outside container now drops items (#1306) 2026-03-23 11:57:16 -05:00
itsRevela 8e820975b1 Allow displaying item lore (#1384) 2026-03-23 11:57:16 -05:00
itsRevela dde608b1e9 Fix missing trapped chest textures in Natural Texture Pack (#1381) 2026-03-23 11:57:16 -05:00
itsRevela 1dda62a924 Remove redundant buffer in UIScene_SettingsGraphicsMenu.cpp (#1348) (#1380) 2026-03-23 11:57:16 -05:00
itsRevela a4ca19ff17 Add ifdef debug around handle debug options (#1382) 2026-03-23 11:57:15 -05:00
itsRevela d7c0830eb4 Fix font rendering for color and formatting codes (#1017) 2026-03-23 11:56:36 -05:00
itsRevela 3fa959ab07 Fix Sign (#1369) + re-add VSync/ExclusiveFullscreen checkboxes
Cherry-picked upstream sign fix (SignEntryMenu720 restored) and re-applied
VSync and ExclusiveFullscreen checkbox patches to all SettingsGraphicsMenu SWFs
using the ffdec_lib Java tools.
2026-03-23 11:49:12 -05:00
itsRevela 4adce63f3d Update maximum limits for game entities (#1355) 2026-03-23 11:35:48 -05:00
itsRevela bb16e953a7 Fix CMake build configuration for Windows64 platform
- Add #include <windows.h> to extraX64.h for Windows type definitions
- Remove duplicate byte typedef and suppress std::byte via _HAS_STD_BYTE=0
- Define _WINDOWS64 for correct platform header selection
- Set IGGY_LIBS to iggy_w64.lib for proper Iggy UI library linking
2026-03-23 11:31:51 -05:00
Connor BeardandGitHub 77433dbd86 Fix: CMP0057 policy was not set (#1367) 2026-03-22 23:27:42 -05:00
Connor BeardandGitHub 57f031a7c8 Fix: CMP0057 policy was not set (#1367) 2026-03-22 23:27:42 -05:00
Lord CambionandGitHub 9a6d126ae1 Stained Glass Survival Integration & Crafting UI Fix (#1195)
* Added Stained Glass

i found out that stained glass  was not accessible in survival, then i  saw they disabled it in the code

* Grouping glass correctly in crafting table

I removed the #if/endif from the ClothDyeRecipes.cpp and added a different one in StructureRecipies.cpp
also changed the Tile definition giving it the same
setBaseItemTypeAndMaterial of stained glass to group it correctly inside the crafting table UI.
also aincremented the Vertical Slot for crafting table to include many more craftings in the same group
2026-03-22 21:15:02 -05:00
Lord CambionandGitHub 174eba45c7 Stained Glass Survival Integration & Crafting UI Fix (#1195)
* Added Stained Glass

i found out that stained glass  was not accessible in survival, then i  saw they disabled it in the code

* Grouping glass correctly in crafting table

I removed the #if/endif from the ClothDyeRecipes.cpp and added a different one in StructureRecipies.cpp
also changed the Tile definition giving it the same
setBaseItemTypeAndMaterial of stained glass to group it correctly inside the crafting table UI.
also aincremented the Vertical Slot for crafting table to include many more craftings in the same group
2026-03-22 21:15:02 -05:00
RevelaandGitHub 39e46751bf Add clipboard paste support to UIControl_TextInput and UIScene_Keyboard (#1298)
Previously paste only worked in the chat screen. Wire Screen::getClipboard() into the two remaining text input paths so Ctrl+V works for sign editing, seed entry, server IP/port, and world name fields.
2026-03-22 21:09:10 -05:00
RevelaandGitHub dec26b43d5 Add clipboard paste support to UIControl_TextInput and UIScene_Keyboard (#1298)
Previously paste only worked in the chat screen. Wire Screen::getClipboard() into the two remaining text input paths so Ctrl+V works for sign editing, seed entry, server IP/port, and world name fields.
2026-03-22 21:09:10 -05:00
Alezito2008andGitHub ebab3ec40f Clicking outside container now drops items (#1306)
Java Edition KBM input parity
2026-03-22 21:05:04 -05:00
Alezito2008andGitHub dbee7d398e Clicking outside container now drops items (#1306)
Java Edition KBM input parity
2026-03-22 21:05:04 -05:00
SylvessaandGitHub c1ce97f7be allow displaying item lore (#1384) 2026-03-22 20:50:06 -05:00
SylvessaandGitHub 16d7ecd283 allow displaying item lore (#1384) 2026-03-22 20:50:06 -05:00
603c6ba7cb Fix missing trapped chest textures in Natural Texture Pack (#1381)
Co-authored-by: Iruka-Wolf <17684713+Iruka-Wolf@users.noreply.github.com>
2026-03-22 20:49:14 -05:00
9f19b25a16 Fix missing trapped chest textures in Natural Texture Pack (#1381)
Co-authored-by: Iruka-Wolf <17684713+Iruka-Wolf@users.noreply.github.com>
2026-03-22 20:49:14 -05:00
SylvessaandGitHub b6e25415ca Remove redundant buffer in UIScene_SettingsGraphicsMenu.cpp (#1348) (#1380) 2026-03-22 18:37:59 -04:00
SylvessaandGitHub 1c24421358 Remove redundant buffer in UIScene_SettingsGraphicsMenu.cpp (#1348) (#1380) 2026-03-22 18:37:59 -04:00
SylvessaandGitHub dac073605f add ifdef debug around handle debug options (#1382) 2026-03-22 13:38:35 -04:00
SylvessaandGitHub 9c15309018 add ifdef debug around handle debug options (#1382) 2026-03-22 13:38:35 -04:00
Ayush ThorenandGitHub be7e2ca91d Fix font rendering for color and formatting codes (#1017)
* Fix "Colormatic" splash text rendering as single color

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

* Use per-vertex coloring in a single batch

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

* Fix font rendering for color and formatting codes

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

---------

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-22 00:33:35 -04:00
Ayush ThorenandGitHub f39b44e75e Fix font rendering for color and formatting codes (#1017)
* Fix "Colormatic" splash text rendering as single color

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

* Use per-vertex coloring in a single batch

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

* Fix font rendering for color and formatting codes

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

---------

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-22 00:33:35 -04:00
GabsPuNsandGitHub 250accd40b Fix Sign (#1369)
fix for the sign's interface.

SignEntryMenu720 was being replaced by an older version of SkinWinHD.

SignEntryMenu720 was is now replaced with it's original version.
2026-03-21 17:49:21 -04:00
GabsPuNsandGitHub 4a0f799b02 Fix Sign (#1369)
fix for the sign's interface.

SignEntryMenu720 was being replaced by an older version of SkinWinHD.

SignEntryMenu720 was is now replaced with it's original version.
2026-03-21 17:49:21 -04:00
JazzitchandGitHub 33b008c96a Update maximum limits for game entities (#1355)
* Update maximum limits for game entities

Increased the maximum limits for Xbox boats, console minecarts, dispensable fireballs, and projectiles.

* Update maximum limits for game entities

Increased maximum limits for Xbox boats, console minecarts, dispensable fireballs, and projectiles.
2026-03-21 16:15:47 -04:00
JazzitchandGitHub 1f4dceb89b Update maximum limits for game entities (#1355)
* Update maximum limits for game entities

Increased the maximum limits for Xbox boats, console minecarts, dispensable fireballs, and projectiles.

* Update maximum limits for game entities

Increased maximum limits for Xbox boats, console minecarts, dispensable fireballs, and projectiles.
2026-03-21 16:15:47 -04:00
RevelaandGitHub b406456d13 Update README with music fix info
Added music context fixes
2026-03-21 12:41:20 -05:00
Revela c62d5e6ff4 Fix music selection to match TU19 behavior
Menu music (menu1-4) now plays only on the title screen, creative
music (creative1-6) only plays in creative mode, and survival mode
correctly plays only calm/hal/nuance/piano tracks. Reordered the
eMUSICFILES enum so piano tracks are contiguous with the survival
range, added game-mode-aware track selection via getOverworldMusicID,
and re-enabled the playStreaming call in setLevel to stop menu music
when entering gameplay. Added debug logging for track selection.
2026-03-21 12:33:04 -05:00
RevelaandGitHub cbbac3936c update readme with removing performance optimization detail
Removed lighting optimization details as this change caused issues
2026-03-19 17:06:02 -05:00
Revela 34cb0b10e4 Update swap chain validation in ResizeD3D function
Modified the conditional check in `ResizeD3D` to use
`(IDXGISwapChain*)&g_swapChainProxy` instead of `g_pSwapChain`.
This change ensures the correct proxy is validated. Updated
the debug print statement for clearer output regarding
the render manager's device and swap chain pointers.
2026-03-19 12:07:43 -05:00
Revela 4fffcac6e7 Add VSync and fullscreen settings, fix swap chain resize and revert lighting changes
- Add VSync and Exclusive Fullscreen toggles to the graphics settings menu
- Rewrite D3D11 swap chain to use DXGI flip model with tearing support
- Fix black screen on resize by creating new swap chain instead of ResizeBuffers
- Revert conditional lighting optimization in Level::setTileAndData back to unconditional checkLight
- Revert deferred lightGaps flagging in LevelChunk::recalcHeight back to immediate lightGap calls
- Add SWF/ARC editing tools used to add new UI checkboxes
2026-03-19 11:04:49 -05:00
RevelaandGitHub 0a343d2c8d Merge branch 'smartcmd:main' into main 2026-03-19 03:15:11 -05:00
Matthew ToroandGitHub ecb3f00bd6 Revert "Increase limits for boats, minecarts, fireballs, and height (#1325)" (#1341)
This reverts commit baa9fc058d.
2026-03-18 20:52:48 -04:00
Matthew ToroandGitHub b336e52f91 Revert "Increase limits for boats, minecarts, fireballs, and height (#1325)" (#1341)
This reverts commit baa9fc058d.
2026-03-18 20:52:48 -04:00
Adem KurtandGitHub 71d6fba4b9 Fix: opening the horse's inventory plays sound effects twice (#1336) 2026-03-18 20:11:07 -04:00
Adem KurtandGitHub f537096a21 Fix: opening the horse's inventory plays sound effects twice (#1336) 2026-03-18 20:11:07 -04:00
ButterSwordandGitHub baa9fc058d Increase limits for boats, minecarts, fireballs, and height (#1325) 2026-03-18 20:10:24 -04:00
ButterSwordandGitHub 679d7cf67f Increase limits for boats, minecarts, fireballs, and height (#1325) 2026-03-18 20:10:24 -04:00
XenovyyandGitHub ab80b34c45 Update banner.png to new logo (#1323)
Update banner.png to new logo
2026-03-18 20:08:40 -04:00
XenovyyandGitHub 0b12046f61 Update banner.png to new logo (#1323)
Update banner.png to new logo
2026-03-18 20:08:40 -04:00
Revela e3649573d3 Update Latest section with performance optimization summary 2026-03-18 17:26:02 -05:00
Revela 0ba923f085 Performance optimizations: sound caching, renderer culling, entity and lighting improvements
- Sound engine: cache filesystem probe results to avoid repeated file existence checks; add MA_SOUND_FLAG_DECODE for pre-decoded playback
- Level renderer: column-level frustum culling, compact visible chunk lists to skip empty iteration, lightweight second-pass render path, early-out for non-dirty chunks, scaled recheck period at high render distances
- Entity: cache shared_from_this() to reduce reference counting overhead in move() and checkInsideTiles()
- Level: skip checkLight() when tile light properties unchanged; enable entity locking on all platforms (not just Vita)
- LevelChunk: only rescan min height when the minimum column changes; defer lightGap processing
- LivingEntity: use raw pointer cast instead of dynamic_pointer_cast; cache friction tile lookup
- ServerPlayerGameMode: return whether block was destroyed to avoid redundant tile update packets
2026-03-18 17:22:04 -05:00
Revela 80ba2e0762 Remove Minecraft.Client.pdb from nightly release upload
Updated `Update-NightlyRelease.ps1` to exclude the upload of the `Minecraft.Client.pdb` file. The asset list in the log output has also been adjusted to reflect this change.
2026-03-17 18:47:30 -05:00
Revela b0b358c44e Update Latest section with CMake migration and Arabic text shaping 2026-03-17 18:44:02 -05:00
Revela 00401a5b3a Merge remote-tracking branch 'upstream/main' 2026-03-17 18:35:24 -05:00
Revela b7a33dc82b Add UIUnicodeBitmapFont to CMake source lists and update nightly release paths
The upstream CMake migration missed UIUnicodeBitmapFont in the Windows
client and server source lists, causing linker errors. Also update
nightly release script paths from x64/ to build/ for CMake output.
2026-03-17 18:32:15 -05:00
XenovyyandGitHub a94ee1ca22 Fixed the ear bleeding sound when using a slider with mouse controls (#1296)
* Fixed the ear bleeding sound when using a slider with mouse controls

Now only ticks every 9 "ticks" unless the slider has less than 18 possible values..

* cured rtm516's ocd

title

* rtm516 reaches enlightenment

* rtm516 reaches total enlightenment
2026-03-17 22:44:12 +00:00
XenovyyandGitHub 6dd9eb4890 Fixed the ear bleeding sound when using a slider with mouse controls (#1296)
* Fixed the ear bleeding sound when using a slider with mouse controls

Now only ticks every 9 "ticks" unless the slider has less than 18 possible values..

* cured rtm516's ocd

title

* rtm516 reaches enlightenment

* rtm516 reaches total enlightenment
2026-03-17 22:44:12 +00:00
rtm516 b774d13806 Fix zip command when packaging release 2026-03-17 22:36:52 +00:00
rtm516 2d4c725934 Fix zip command when packaging release 2026-03-17 22:36:52 +00:00
Revela c3ca509b44 Add x64_* build output directories to .gitignore 2026-03-17 17:29:02 -05:00
Revela b58f7c8fdd Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp
#	Minecraft.Client/Minecraft.Client.vcxproj
#	Minecraft.Client/Minecraft.Client.vcxproj.filters
#	Minecraft.Server/Minecraft.Server.vcxproj
#	Minecraft.World/Minecraft.World.vcxproj
#	Minecraft.World/Minecraft.World.vcxproj.filters
#	README.md
2026-03-17 17:26:40 -05:00
Revela e786604228 Add Arabic text shaping support for chat functionality
This commit introduces Arabic text shaping in the chat application by adding `ArabicShaping.cpp` and `ArabicShaping.h` for handling contextual forms and visual reordering.

The rendering logic in `ChatScreen.cpp` is updated to utilize this new functionality, adjusting cursor positions accordingly. Other UI components, including `UIControl_Base.cpp`, `UIControl_Label.cpp`, and `UIControl_SaveList.cpp`, are modified to ensure proper display of Arabic text.

Additionally, `Font.cpp` is enhanced with methods for efficient rendering of pre-shaped text.
2026-03-17 17:08:58 -05:00
Matthew ToroandGitHub 6df8089003 Merge pull request #669 from qwasdrizzel/main
Fix crash when FOV is equal to zero
2026-03-17 18:03:57 -04:00
Matthew ToroandGitHub b1eb9a34a4 Merge pull request #669 from qwasdrizzel/main
Fix crash when FOV is equal to zero
2026-03-17 18:03:57 -04:00
rtm516 76f4832a6b Fix actions and sort docker nightly 2026-03-17 22:02:24 +00:00
rtm516 89d364ec50 Fix actions and sort docker nightly 2026-03-17 22:02:24 +00:00
rtm516andGitHub 02a5961f39 Move project to CMake (#781)
* Move to cmake

* Move sources to source_groups and ditch more old VS files

* Add BuildVer.h generation

* Break out cmake source lists to platforms

* Don't copy swf files

* Revert audio changes from merge

* Add platform defines

* Match MSBuild flags

* Move BuildVer.h to common include and fix rebuild issue

* Seperate projects properly

* Exclude more files and make sure GameHDD exists

* Missing line

* Remove remaining VS project files

* Update readme and actions

* Use incremental LTCG

* Update workflows

* Update build workflows and output folder

* Disable vcpkg checks

* Force MSVC

* Use precompiled headers

* Only use PCH for cpp

* Exclude compat_shims from PCH

* Handle per-platform source includes

* Copy only current platform media

* Define Iggy libs per platform

* Fix EnsureGameHDD check

* Only set WIN32_EXECUTABLE on Windows

* Correct Iggy libs path

* Remove include of terrain_MipmapLevel

* Correct path to xsb/xwb

* Implement copilot suggestions

* Add clang flags (untested)

* Fix robocopy error checking

* Update documentation

* Drop CMakePresets.json version as we dont use v6 features

* Always cleanup artifacts in nightly even if some builds fail

* Re-work compiler target options

* Move newer iggy dll into redist and cleanup

* Fix typos

* Remove 'Source Files' from all source groups

* Remove old ps1 build scripts
2026-03-17 16:39:22 -05:00
rtm516andGitHub df4c9831c4 Move project to CMake (#781)
* Move to cmake

* Move sources to source_groups and ditch more old VS files

* Add BuildVer.h generation

* Break out cmake source lists to platforms

* Don't copy swf files

* Revert audio changes from merge

* Add platform defines

* Match MSBuild flags

* Move BuildVer.h to common include and fix rebuild issue

* Seperate projects properly

* Exclude more files and make sure GameHDD exists

* Missing line

* Remove remaining VS project files

* Update readme and actions

* Use incremental LTCG

* Update workflows

* Update build workflows and output folder

* Disable vcpkg checks

* Force MSVC

* Use precompiled headers

* Only use PCH for cpp

* Exclude compat_shims from PCH

* Handle per-platform source includes

* Copy only current platform media

* Define Iggy libs per platform

* Fix EnsureGameHDD check

* Only set WIN32_EXECUTABLE on Windows

* Correct Iggy libs path

* Remove include of terrain_MipmapLevel

* Correct path to xsb/xwb

* Implement copilot suggestions

* Add clang flags (untested)

* Fix robocopy error checking

* Update documentation

* Drop CMakePresets.json version as we dont use v6 features

* Always cleanup artifacts in nightly even if some builds fail

* Re-work compiler target options

* Move newer iggy dll into redist and cleanup

* Fix typos

* Remove 'Source Files' from all source groups

* Remove old ps1 build scripts
2026-03-17 16:39:22 -05:00
Loki Rautio 1a3fcb5b20 Remove Miles Sound System from credits
we don't use it anymore!
2026-03-17 16:22:49 -05:00
Loki Rautio feb4b3ac8b Remove Miles Sound System from credits
we don't use it anymore!
2026-03-17 16:22:49 -05:00
Loki Rautio a3ca23fdf6 Cleanup project credits and README 2026-03-17 16:15:26 -05:00
Loki Rautio f4626606e4 Cleanup project credits and README 2026-03-17 16:15:26 -05:00
Toru the Red FoxandGitHub c98153bf07 Fix FOV modification so it respects applyEffects (#1297) 2026-03-17 19:47:34 +00:00
Toru the Red FoxandGitHub ab4de7c87e Fix FOV modification so it respects applyEffects (#1297) 2026-03-17 19:47:34 +00:00
Matthew ToroandGitHub a5f5595c63 Merge pull request #1315 from dognews/main
LoadJoinMenu UI Bug Fix: Properly display space indicator, remove label placeholder [BUG: #1004]
2026-03-17 15:45:22 -04:00
Matthew ToroandGitHub d1673536c3 Merge pull request #1315 from dognews/main
LoadJoinMenu UI Bug Fix: Properly display space indicator, remove label placeholder [BUG: #1004]
2026-03-17 15:45:22 -04:00
Matthew ToroandGitHub dc8af13b45 Merge pull request #1321 from rtm516/fix/host-settings
Change KEY_HOST_SETTINGS back to to VK_TAB
2026-03-17 15:41:26 -04:00
Matthew ToroandGitHub 4e408a5b4a Merge pull request #1321 from rtm516/fix/host-settings
Change KEY_HOST_SETTINGS back to to VK_TAB
2026-03-17 15:41:26 -04:00
rtm516andGitHub ab16f3bf45 Change KEY_HOST_SETTINGS back to to VK_TAB 2026-03-17 19:22:24 +00:00
rtm516andGitHub 681dc7cefe Change KEY_HOST_SETTINGS back to to VK_TAB 2026-03-17 19:22:24 +00:00
Alex 994a23f96b Fix save space indicator display
Include space indicator UI element in windows build, logic to handle getting save file sizes on windows
2026-03-17 07:44:52 -07:00
Alex 1c3aeb9f02 Fix save space indicator display
Include space indicator UI element in windows build, logic to handle getting save file sizes on windows
2026-03-17 07:44:52 -07:00
Revela d473ef0dc5 Merge branch 'main' of https://github.com/itsRevela/MinecraftConsoles 2026-03-17 00:32:54 -05:00
Revela 0d269f0c83 Improve Nightly release management process
Enhanced the script to delete and recreate the Nightly-Dedicated-Server release, ensuring the client is always up-to-date. The process now fetches release information, deletes the old release, updates the tag to the latest commit, and creates a new release with an updated title and body. Streamlined asset uploads and clarified title update logic for better reliability and clarity.
2026-03-17 00:32:25 -05:00
RevelaandGitHub f20b0d252c Added to README with multi-language support details
Added support for multi-language font rendering and Unicode text input, along with copy-paste functionality for various fields. Also included security enhancements and fixed a memory leak.
2026-03-16 23:16:46 -05:00
RevelaandGitHub 0644d7da5c Merge branch 'smartcmd:main' into main 2026-03-16 23:12:41 -05:00
Revela d7822ac81e Enable multi-language font rendering and Unicode text input
Goal:
Allow players to type and display text in any language supported by
Unicode, including Chinese, Japanese, Korean, Thai, Arabic, Korean, Hindi, and more. This
covers all text surfaces: chat editor, chat messages, signs (in-world
and editor), world name/seed, server address/port fields, and all
Iggy Flash UI text fields.

Multi-language support:
Two complementary rendering systems were added to handle Unicode text
across the entire client:

1. Iggy UI (Flash-based text fields): A new UIUnicodeBitmapFont class
   serves Java Minecraft's glyph page PNGs (glyph_00.png-glyph_FF.png)
   through Iggy's bitmap font provider API. Registered as the global
   fallback font with metrics matching the Mojangles bitmap font for
   correct baseline alignment. When the primary bitmap font lacks a
   glyph, it returns IGGY_GLYPH_INVALID and Iggy seamlessly falls back
   to the unicode bitmap font.

2. Legacy C++ Font renderer (chat editor, in-world signs): Revived the
   commented-out unicode glyph page system in Font.cpp. Characters not
   in the bitmap font texture are rendered from glyph page PNGs loaded
   on demand, with proper texture switching mid-string.

3. ChatScreen input: Removed the restrictive acceptableLetters filter
   so all printable Unicode characters are accepted in chat.

Languages now supported for text input and rendering:
- Japanese (Hiragana, Katakana, Kanji)
- Chinese (Simplified and Traditional)
- Korean (Hangul)
- Thai
- Arabic
- Hindi (Devanagari)
- Russian (Cyrillic) - already worked via bitmap font
- Greek - already worked via bitmap font
- Polish, Czech, Turkish (Extended Latin) - already worked via bitmap font
- Armenian, Georgian, and other scripts covered by glyph pages

Security fixes:
- Fixed memset under-initialization of Font::charWidths (zeroed 460
  bytes instead of 460*sizeof(int)=1840 bytes, leaving entries 115+
  uninitialized) - pre-existing bug
- Added bounds checks to all UIUnicodeBitmapFont callbacks to reject
  glyph IDs outside [0, 65535], preventing OOB array access
- Added bounds check in Font::width() section-sign fallback path to
  prevent OOB read on charWidths[] with high codepoints
- Blocked Unicode bidirectional override characters (U+202A-202E,
  U+2066-2069) in chat input to prevent message spoofing

Memory leak fix:
- Fixed SignTileEntity::load allocating wchar_t[256] with new[] on
  every sign load without freeing. Replaced with stack allocation.

Debug logging:
- Added [SIGN] prefixed logging for sign save/update operations
- Added [CHAT] prefixed logging for chat send/receive operations

Files changed:
- UIUnicodeBitmapFont.h/.cpp (new) - Iggy bitmap font for glyph pages
- UIBitmapFont.cpp - Return IGGY_GLYPH_INVALID for unknown chars
- UIFontData.h/.cpp - Added hasGlyph() method
- UIController.h/.cpp - Load and register unicode bitmap fallback font
- UITTFFont.h/.cpp - Added registerAsDefaultFonts parameter
- Font.h/.cpp - Revived unicode glyph page rendering system
- ChatScreen.cpp - Accept all Unicode input, block bidi overrides
- Gui.cpp - Chat display debug logging
- ClientConnection.cpp - Sign update debug logging
- SignTileEntity.cpp - Sign save logging, memory leak fix
2026-03-16 23:08:05 -05:00
qwasdrizzelandGitHub d359957727 fix 2026-03-16 21:54:29 -05:00
qwasdrizzelandGitHub a101555fde fix 2026-03-16 21:54:29 -05:00
qwasdrizzelandGitHub ce739f6045 Merge branch 'smartcmd:main' into main 2026-03-16 21:44:26 -05:00
qwasdrizzelandGitHub 9910a1adf4 Merge branch 'smartcmd:main' into main 2026-03-16 21:44:26 -05:00
GabsPuNsandGitHub 5a59f5d146 Update to more accurate logo (#1305)
* Updated Logo

* Updated two old files.
2026-03-16 19:00:51 -05:00
GabsPuNsandGitHub 4d9067dbfb Update to more accurate logo (#1305)
* Updated Logo

* Updated two old files.
2026-03-16 19:00:51 -05:00
RevelaandGitHub a3395329e5 Update README with copy-paste support details
Added copy-paste support for various elements including IP/Port and world names.
2026-03-16 11:05:42 -05:00
Revela 3980cd813a Add Ctrl+V clipboard paste to UIControl_TextInput and UIScene_Keyboard
Previously paste only worked in the chat screen. Wire Screen::getClipboard() into the two remaining text input paths so Ctrl+V works for sign editing, seed entry, server IP/port, and world name fields.
2026-03-16 10:36:46 -05:00
Revela 289f1ccd6a Merge branch 'main' of https://github.com/itsRevela/MinecraftConsoles 2026-03-16 08:10:47 -05:00
Revela 9af36133cc Change default for hardcore-ban-ip to false
Updated the default value of the "hardcore-ban-ip" server property from "true" to "false" in the `kServerPropertyDefaults` array. Adjusted the `LoadServerPropertiesConfig` function to read the "hardcore-ban-ip" property as "false" to ensure consistency with the new default.
2026-03-16 08:10:40 -05:00
Revela 4a3128d32b Add hardcore-ban-ip property for IP banning on hardcore death
This commit introduces a new server property `hardcore-ban-ip` that controls whether players who die in hardcore mode are banned by their IP address. This setting should be set to `false` for playit.gg users!

Key changes include:
- Updated `banPlayerForHardcoreDeath` in `PlayerList.cpp` to check the `hardcoreBanIp` setting and handle IP bans accordingly.
- Added `hardcore-ban-ip` to the default server properties in `ServerProperties.cpp`.
- Declared the `hardcoreBanIp` boolean variable in `ServerProperties.h` to store the property value.

These changes enhance the server's ability to enforce IP bans based on configuration settings.
2026-03-16 08:00:48 -05:00
RevelaandGitHub 9a13ce9856 Update README with Hardcore Mode and server info
Added details about Hardcore Mode support and server downloads.
2026-03-16 04:11:04 -05:00
Revela 090dd49ccd Update workflows and Docker image references
- Modify `.gitattributes` to use "ours" merge strategy for specific workflow and Docker Compose files.
- Update `nightly.yml` to allow manual triggering and set permissions for content writing.
- Change Docker image reference for `minecraft-lce-dedicated-server` service to a new source.
2026-03-16 03:52:25 -05:00
Revela 88274ebad1 Merge branch 'main' of https://github.com/itsRevela/MinecraftConsoles 2026-03-16 03:25:10 -05:00
Revela 091564cdce Enhance nightly release script for client and server
Updated the script to build zips for both client and server, including new variables for server release management. Added functionality to create a server zip, fetch server release info, delete old assets, and upload the new server zip to GitHub. The script now updates the server release title with the latest commit hash and provides clearer output messages for both client and server releases.
2026-03-16 03:25:00 -05:00
RevelaandGitHub 30fd14096e Update Dedicated Server download link in README
Updated the link for Dedicated Server software to fork's build
2026-03-16 03:12:44 -05:00
Revela 8a6934c83c Implement persistent hardcore death bans (XUID + IP) for dedicated server
On the dedicated server, hardcore death now persists XUID and IP bans to
banned-players.json and banned-ips.json via the Access system, and
disconnects the player. Bans survive server restarts. Client-hosted games
retain the existing in-memory XUID ban with force-save behavior.

- Add hardcore property to server.properties (forces Hard difficulty)
- Add LevelData::setHardcore() so loaded worlds respect the server config
- Add PlayerList::banPlayerForHardcoreDeath() with persistent XUID + IP bans
- Reject respawn requests server-side in hardcore mode
- Ensure server-side player ticks run without move packets (fixes
  environmental damage not applying for some clients)
- Restore 0x8 hardcore bit on LoginPacket/RespawnPacket wire format so
  the client-side death screen detects hardcore mode correctly
2026-03-16 02:52:16 -05:00
Revela c92a5ab31a Merge upstream/main into main 2026-03-15 23:38:41 -05:00
ZorpLemonandGitHub 43d520f692 Comment out FOV modification line, since the FOV is stored and doesn't need to be adjusted. (#1248)
I guess this line was just the games way of applying modifications the player made to the FOV. But since whenever ago someone changed the way the FOV stuff is saved, so this line just adds the difference *again* causing issues when the FOV is set above 70. Setting your FOV to 80 actually sets it to 90, and setting it to 110 actually sets it to 150.
2026-03-15 18:14:15 -05:00
ZorpLemonandGitHub 5d19215e60 Comment out FOV modification line, since the FOV is stored and doesn't need to be adjusted. (#1248)
I guess this line was just the games way of applying modifications the player made to the FOV. But since whenever ago someone changed the way the FOV stuff is saved, so this line just adds the difference *again* causing issues when the FOV is set above 70. Setting your FOV to 80 actually sets it to 90, and setting it to 110 actually sets it to 150.
2026-03-15 18:14:15 -05:00
Ananasloll3andGitHub 0b0d74a638 Fix audio volume levels for cows and bats (#1225)
Cow volume 0.4f to 1.f
Bat volume 0.1f to 0.8f
2026-03-15 18:13:11 -05:00
Ananasloll3andGitHub 1fe25a9398 Fix audio volume levels for cows and bats (#1225)
Cow volume 0.4f to 1.f
Bat volume 0.1f to 0.8f
2026-03-15 18:13:11 -05:00
irisandGitHub b27cb536a5 Fix game crashing when crafting fireworks (#1230) (#1240) 2026-03-15 18:13:03 -05:00
irisandGitHub 3810c96d14 Fix game crashing when crafting fireworks (#1230) (#1240) 2026-03-15 18:13:03 -05:00
XenovyyandGitHub 15ea3dc85c Adjusted Exit Game title (#1277)
* Adjusted Exit Game title

Replaced "Return to Xbox Dashboard" with "Exit Minecraft" on the exit game screen.

* Fixed Blending on Intro Sequence

Fixed Blocky, Crappy blending on the ESRB and Mojang Logos in the Intro Sequence.
2026-03-15 18:12:53 -05:00
XenovyyandGitHub 5f76a7cc49 Adjusted Exit Game title (#1277)
* Adjusted Exit Game title

Replaced "Return to Xbox Dashboard" with "Exit Minecraft" on the exit game screen.

* Fixed Blending on Intro Sequence

Fixed Blocky, Crappy blending on the ESRB and Mojang Logos in the Intro Sequence.
2026-03-15 18:12:53 -05:00
retucioandGitHub 9fde19eca0 organized keybinds a lil bit (#1279) 2026-03-15 18:11:55 -05:00
retucioandGitHub ecfdeeb1b5 organized keybinds a lil bit (#1279) 2026-03-15 18:11:55 -05:00
e9f5b4b6f0 Fix server DedicatedServer issues (#1266)
* add: Dedicated Server implementation

- Introduced `ServerMain.cpp` for the dedicated server logic, handling command-line arguments, server initialization, and network management.
- Created `postbuild_server.ps1` script for post-build tasks, including copying necessary resources and DLLs for the dedicated server.
- Added `CopyServerAssets.cmake` to manage the copying of server assets during the build process, ensuring required files are available for the dedicated server.
- Defined project filters in `Minecraft.Server.vcxproj.filters` for better organization of server-related files.

* add: refactor world loader & add server properties

- Introduced ServerLogger for logging startup steps and world I/O operations.
- Implemented ServerProperties for loading and saving server configuration from `server.properties`.
- Added WorldManager to handle world loading and creation based on server properties.
- Updated ServerMain to integrate server properties loading and world management.
- Enhanced project files to include new source and header files for the server components.

* update: implement enhanced logging functionality with configurable log levels

* update: update keyboard and mouse input initialization 1dc8a005ed

* fix: change virtual screen resolution to 1920x1080(HD)

Since 31881af56936aeef38ff322b975fd0 , `skinHud.swf` for 720 is not included in `MediaWindows64.arc`,
the app crashes unless the virtual screen is set to HD.

* fix: dedicated server build settings for miniaudio migration and missing sources

- remove stale Windows64 Miles (mss64) link/copy references from server build
- add Common/Filesystem/Filesystem.cpp to Minecraft.Server.vcxproj
- add Windows64/PostProcesser.cpp to Minecraft.Server.vcxproj
- fix unresolved externals (PostProcesser::*, FileExists) in dedicated server build

* update: changed the virtual screen to 720p

Since the crash caused by the 720p `skinHud.swf` not being included in `MediaWindows64.arc` has been resolved, switching back to 720p to reduce resource usage.

* add: add Docker support for Dedicated Server

add with entrypoint and build scripts

* fix: add initial save for newly created worlds in dedicated server

on the server side, I fixed the behavior introduced after commit aadb511, where newly created worlds are intentionally not saved to disk immediately.

* update: add basically all configuration options that are implemented in the classes to `server.properties`

* update: add LAN advertising configuration for server.properties

LAN-Discovery, which isn’t needed in server mode and could potentially be a security risk, has also been disabled(only server mode).

* add: add implementing interactive command line using linenoise

- Integrated linenoise library for line editing and completion in the server console.
- Updated ServerLogger to handle external writes safely during logging.
- Modified ServerMain to initialize and manage the ServerCli for command input.
- The implementation is separate from everything else, so it doesn't affect anything else.
- The command input section and execution section are separated into threads.

* update: enhance command line completion with predictive hints

Like most command line tools, it highlights predictions in gray.

* add: implement `StringUtils` for string manipulation and refactor usages

Unified the scattered utility functions.

* fix: send DisconnectPacket on shutdown and fix Win64 recv-thread teardown race

Before this change, server/host shutdown closed sockets directly in
ServerConnection::stop(), which bypassed the normal disconnect flow.
As a result, clients could be dropped without receiving a proper
DisconnectPacket during stop/kill/world-close paths.

Also, WinsockNetLayer::Shutdown() could destroy synchronization objects
while host-side recv threads were still exiting, causing a crash in
RecvThreadProc (access violation on world close in host mode).

* fix: return client to menus when Win64 host connection drops

- Add client-side host disconnect handling in CPlatformNetworkManagerStub::DoWork() for _WINDOWS64.
- When in QNET_STATE_GAME_PLAY as a non-host and WinsockNetLayer::IsConnected() becomes false, trigger g_NetworkManager.HandleDisconnect(false) to enter the normal disconnect/UI flow.
- Use m_bLeaveGameOnTick as a one-shot guard to prevent repeated disconnect handling while the link remains down.
- Reset m_bLeaveGameOnTick on LeaveGame(), HostGame(), and JoinGame() to avoid stale state across sessions.

* update: converted Japanese comments to English

* add: create `Minecraft.Server` developer guide in English and Japanese

* update: add note about issue

* add: add `nlohmann/json` json lib

* add: add FileUtils

Moved file operations to `utils`.

* add: Dedicated Server BAN access manager with persistent player and IP bans

- add Access frontend that publishes thread-safe ban manager snapshots for dedicated server use
- add BanManager storage for banned-players.json and banned-ips.json with load/save/update flows
- add persistent player and IP ban checks during dedicated server connection handling
- add UTF-8 BOM-safe JSON parsing and shared file helpers backed by nlohmann/json
- add Unicode-safe ban file read/write and safer atomic replacement behavior on Windows
- add active-ban snapshot APIs and expiry-aware filtering for expires metadata
- add RAII-based dedicated access shutdown handling during server startup and teardown

* update: changed file read/write operations to use `FileUtils`.

- As a side effect, saving has become faster!

* fix: Re-added the source that had somehow disappeared.

* add: significantly improved the dedicated server logging system

- add ServerLogManager to Minecraft.Server as the single entry point for dedicated-server log output
- forward CMinecraftApp logger output to the server logger when running with g_Win64DedicatedServer
- add named network logs for incoming, accepted, rejected, and disconnected connections
- cache connection metadata by smallId so player name and remote IP remain available for disconnect logs
- keep Minecraft.Client changes minimal by using lightweight hook points and handling log orchestration on the server side

* fix: added the updated library source

* add: add `ban` and `pardon` commands for Player and IP

* fix: fix stop command shutdown process

add dedicated server shutdown request handling

* fix: fixed the save logic during server shutdown

Removed redundant repeated saves and eliminated the risks of async writes.

* update: added new sever files to Docker entrypoint

* fix: replace shutdown flag with atomic variable for thread safety

* update: update Dedicated Server developer guide

English is machine translated.
Please forgive me.

* update: check for the existence of `GameHDD` and create

* add: add Whitelist to Dedicated Server

* refactor: clean up and refactor the code

- unify duplicated implementations that were copied repeatedly
- update outdated patterns to more modern ones

* fix: include UI header (new update fix)

* fix: fix the detection range for excessive logging

`getHighestNonEmptyY()` returning `-1` occurs normally when the chunk is entirely air.
The caller (`Minecraft.World/LevelChunk.cpp:2400`) normalizes `-1` to `0`.

* update: add world size config to dedicated server properties

* update: update README add explanation of  `server.properties` & launch arguments

* update: add nightly release workflow for dedicated server and client builds to Actions

* fix: update name for workflow

* add random seed generation

* add: add Docker nightly workflow for Dedicated Server publish to GitHub Container Registry

* fix: ghost player when clients disconnect out of order

#4

* fix: fix 7zip option

* fix: fix Docker workflow for Dedicated Server artifact handling

* add: add no build Dedicated Server startup scripts and Docker Compose

* update: add README for Docker Dedicated Server setup with no local build

* refactor: refactor command path structure

As the number of commands has increased and become harder to navigate, each command has been organized into separate folders.

* update: support stream(file stdin) input mode for server CLI

Support for the stream (file stdin) required when attaching a tty to a Docker container on Linux.

* add: add new CLI Console Commands for Dedicated Server

Most of these commands are executed using the command dispatcher implemented on the `Minecraft.World` side. When registering them with the dispatcher, the sender uses a permission-enabled configuration that treats the CLI as a player.

- default game.
- enchant
- experience.
- give
- kill(currently, getting a permission error for some reason)
- time
- weather.
- update tp & gamemode command

* fix: change player map icon to random select

* update: increase the player limit

* add: restore the basic anti-cheat implementation and add spawn protection

Added the following anti-cheat measures and add spawn protection to `server.properties`.
- instant break
- speed
- reach

* fix: fix Docker image tag

* make chunks delay less for dedi

* fix: prevent overwriting allow-flight value on server startup

* fix: mitigate entity id overflow and crash for max chunk updates

* remove autosave prompt for dedicated server

* fix: fix `Failed to create window instance.`

Wait for Xvfb to be fully ready before starting.

* Revert wrong readme order

---------

Co-authored-by: sylvessa <225480449+sylvessa@users.noreply.github.com>
Co-authored-by: Loki Rautio <lokirautio@gmail.com>
2026-03-15 15:50:12 -05:00
c05b104223 Fix server DedicatedServer issues (#1266)
* add: Dedicated Server implementation

- Introduced `ServerMain.cpp` for the dedicated server logic, handling command-line arguments, server initialization, and network management.
- Created `postbuild_server.ps1` script for post-build tasks, including copying necessary resources and DLLs for the dedicated server.
- Added `CopyServerAssets.cmake` to manage the copying of server assets during the build process, ensuring required files are available for the dedicated server.
- Defined project filters in `Minecraft.Server.vcxproj.filters` for better organization of server-related files.

* add: refactor world loader & add server properties

- Introduced ServerLogger for logging startup steps and world I/O operations.
- Implemented ServerProperties for loading and saving server configuration from `server.properties`.
- Added WorldManager to handle world loading and creation based on server properties.
- Updated ServerMain to integrate server properties loading and world management.
- Enhanced project files to include new source and header files for the server components.

* update: implement enhanced logging functionality with configurable log levels

* update: update keyboard and mouse input initialization 1dc8a005ed

* fix: change virtual screen resolution to 1920x1080(HD)

Since 31881af56936aeef38ff322b975fd0 , `skinHud.swf` for 720 is not included in `MediaWindows64.arc`,
the app crashes unless the virtual screen is set to HD.

* fix: dedicated server build settings for miniaudio migration and missing sources

- remove stale Windows64 Miles (mss64) link/copy references from server build
- add Common/Filesystem/Filesystem.cpp to Minecraft.Server.vcxproj
- add Windows64/PostProcesser.cpp to Minecraft.Server.vcxproj
- fix unresolved externals (PostProcesser::*, FileExists) in dedicated server build

* update: changed the virtual screen to 720p

Since the crash caused by the 720p `skinHud.swf` not being included in `MediaWindows64.arc` has been resolved, switching back to 720p to reduce resource usage.

* add: add Docker support for Dedicated Server

add with entrypoint and build scripts

* fix: add initial save for newly created worlds in dedicated server

on the server side, I fixed the behavior introduced after commit aadb511, where newly created worlds are intentionally not saved to disk immediately.

* update: add basically all configuration options that are implemented in the classes to `server.properties`

* update: add LAN advertising configuration for server.properties

LAN-Discovery, which isn’t needed in server mode and could potentially be a security risk, has also been disabled(only server mode).

* add: add implementing interactive command line using linenoise

- Integrated linenoise library for line editing and completion in the server console.
- Updated ServerLogger to handle external writes safely during logging.
- Modified ServerMain to initialize and manage the ServerCli for command input.
- The implementation is separate from everything else, so it doesn't affect anything else.
- The command input section and execution section are separated into threads.

* update: enhance command line completion with predictive hints

Like most command line tools, it highlights predictions in gray.

* add: implement `StringUtils` for string manipulation and refactor usages

Unified the scattered utility functions.

* fix: send DisconnectPacket on shutdown and fix Win64 recv-thread teardown race

Before this change, server/host shutdown closed sockets directly in
ServerConnection::stop(), which bypassed the normal disconnect flow.
As a result, clients could be dropped without receiving a proper
DisconnectPacket during stop/kill/world-close paths.

Also, WinsockNetLayer::Shutdown() could destroy synchronization objects
while host-side recv threads were still exiting, causing a crash in
RecvThreadProc (access violation on world close in host mode).

* fix: return client to menus when Win64 host connection drops

- Add client-side host disconnect handling in CPlatformNetworkManagerStub::DoWork() for _WINDOWS64.
- When in QNET_STATE_GAME_PLAY as a non-host and WinsockNetLayer::IsConnected() becomes false, trigger g_NetworkManager.HandleDisconnect(false) to enter the normal disconnect/UI flow.
- Use m_bLeaveGameOnTick as a one-shot guard to prevent repeated disconnect handling while the link remains down.
- Reset m_bLeaveGameOnTick on LeaveGame(), HostGame(), and JoinGame() to avoid stale state across sessions.

* update: converted Japanese comments to English

* add: create `Minecraft.Server` developer guide in English and Japanese

* update: add note about issue

* add: add `nlohmann/json` json lib

* add: add FileUtils

Moved file operations to `utils`.

* add: Dedicated Server BAN access manager with persistent player and IP bans

- add Access frontend that publishes thread-safe ban manager snapshots for dedicated server use
- add BanManager storage for banned-players.json and banned-ips.json with load/save/update flows
- add persistent player and IP ban checks during dedicated server connection handling
- add UTF-8 BOM-safe JSON parsing and shared file helpers backed by nlohmann/json
- add Unicode-safe ban file read/write and safer atomic replacement behavior on Windows
- add active-ban snapshot APIs and expiry-aware filtering for expires metadata
- add RAII-based dedicated access shutdown handling during server startup and teardown

* update: changed file read/write operations to use `FileUtils`.

- As a side effect, saving has become faster!

* fix: Re-added the source that had somehow disappeared.

* add: significantly improved the dedicated server logging system

- add ServerLogManager to Minecraft.Server as the single entry point for dedicated-server log output
- forward CMinecraftApp logger output to the server logger when running with g_Win64DedicatedServer
- add named network logs for incoming, accepted, rejected, and disconnected connections
- cache connection metadata by smallId so player name and remote IP remain available for disconnect logs
- keep Minecraft.Client changes minimal by using lightweight hook points and handling log orchestration on the server side

* fix: added the updated library source

* add: add `ban` and `pardon` commands for Player and IP

* fix: fix stop command shutdown process

add dedicated server shutdown request handling

* fix: fixed the save logic during server shutdown

Removed redundant repeated saves and eliminated the risks of async writes.

* update: added new sever files to Docker entrypoint

* fix: replace shutdown flag with atomic variable for thread safety

* update: update Dedicated Server developer guide

English is machine translated.
Please forgive me.

* update: check for the existence of `GameHDD` and create

* add: add Whitelist to Dedicated Server

* refactor: clean up and refactor the code

- unify duplicated implementations that were copied repeatedly
- update outdated patterns to more modern ones

* fix: include UI header (new update fix)

* fix: fix the detection range for excessive logging

`getHighestNonEmptyY()` returning `-1` occurs normally when the chunk is entirely air.
The caller (`Minecraft.World/LevelChunk.cpp:2400`) normalizes `-1` to `0`.

* update: add world size config to dedicated server properties

* update: update README add explanation of  `server.properties` & launch arguments

* update: add nightly release workflow for dedicated server and client builds to Actions

* fix: update name for workflow

* add random seed generation

* add: add Docker nightly workflow for Dedicated Server publish to GitHub Container Registry

* fix: ghost player when clients disconnect out of order

#4

* fix: fix 7zip option

* fix: fix Docker workflow for Dedicated Server artifact handling

* add: add no build Dedicated Server startup scripts and Docker Compose

* update: add README for Docker Dedicated Server setup with no local build

* refactor: refactor command path structure

As the number of commands has increased and become harder to navigate, each command has been organized into separate folders.

* update: support stream(file stdin) input mode for server CLI

Support for the stream (file stdin) required when attaching a tty to a Docker container on Linux.

* add: add new CLI Console Commands for Dedicated Server

Most of these commands are executed using the command dispatcher implemented on the `Minecraft.World` side. When registering them with the dispatcher, the sender uses a permission-enabled configuration that treats the CLI as a player.

- default game.
- enchant
- experience.
- give
- kill(currently, getting a permission error for some reason)
- time
- weather.
- update tp & gamemode command

* fix: change player map icon to random select

* update: increase the player limit

* add: restore the basic anti-cheat implementation and add spawn protection

Added the following anti-cheat measures and add spawn protection to `server.properties`.
- instant break
- speed
- reach

* fix: fix Docker image tag

* make chunks delay less for dedi

* fix: prevent overwriting allow-flight value on server startup

* fix: mitigate entity id overflow and crash for max chunk updates

* remove autosave prompt for dedicated server

* fix: fix `Failed to create window instance.`

Wait for Xvfb to be fully ready before starting.

* Revert wrong readme order

---------

Co-authored-by: sylvessa <225480449+sylvessa@users.noreply.github.com>
Co-authored-by: Loki Rautio <lokirautio@gmail.com>
2026-03-15 15:50:12 -05:00
Matthew ToroandGitHub 7b643cdd75 fix: removed headlesss server logic in favor of the new server exe. (#1265) 2026-03-15 15:43:27 -05:00
Matthew ToroandGitHub 22bce8e1ee fix: removed headlesss server logic in favor of the new server exe. (#1265) 2026-03-15 15:43:27 -05:00
Revela 04329d840a Add support for empty directory entries in ZIP archive
This commit introduces a new block in the `Update-NightlyRelease.ps1` script that creates empty directory entries in the ZIP archive. A `try` block is added to manage the `ZipArchive` object, and a loop iterates through all directories in the specified `$ReleaseDir`, ensuring that empty directories are included in the final archive.
2026-03-15 10:25:53 -05:00
Revela 77ea49440c Remove NDEBUG from preprocessor definitions
Incorrectly assumed that this was causing crashing on Steam deck. Reverting with this commit
2026-03-15 10:07:18 -05:00
Revela 610a1c7aa7 Refactor ZIP creation using System.IO.Compression
Updated the ZIP file creation process to utilize the .NET `System.IO.Compression` library. This change eliminates the need for a temporary ZIP file and directly excludes `.pch` and `.zip` files from the archive. A top-level folder named "LCEWindows64" has been added to the ZIP structure, and resource management has been improved with proper disposal of file streams and ZIP archives.
2026-03-15 10:05:37 -05:00
Revela 20e237dfaf Include base directory in release script
Modified the CreateFromDirectory method to include the base directory in the zip file by changing the parameter from `$false` to `$true`.
2026-03-15 09:03:54 -05:00
Revela 9c01398cd4 Refactor zip creation using .NET Compression library
Updated the zipping process to utilize .NET's `System.IO.Compression` library for improved cross-platform compatibility. The new implementation creates a temporary zip file, removes unwanted entries (e.g., `.pch` and `.zip` files), and then finalizes the zip file, ensuring it only contains the desired files.
2026-03-15 08:50:39 -05:00
Revela 3f24d52ee3 Prepare project for release build
Updated `<PreprocessorDefinitions>` to include `NDEBUG`,
indicating that debugging code will be excluded from the
build. This change is part of the preparation for a
release version of the project.
2026-03-15 07:37:07 -05:00
Revela f66f5f9cd3 Add F2 screenshot functionality and image writing support
- Updated `EControllerActions` to include `MINECRAFT_ACTION_SCREENSHOT`.
- Added conditional compilation for `stb_image_write.h` in `Minecraft.cpp`.
- Modified `run_middle()` to handle screenshot key press.
- Updated `tick()` to capture and save screenshots as PNG files.
- Introduced `KEY_SCREENSHOT` in `KeyboardMouseInput.h` mapped to F2.
- Added `stb_image_write.h` for image writing capabilities.
2026-03-15 07:36:49 -05:00
RevelaandGitHub f612574c67 Update README with new features and functionality
Added details about in-game screenshot functionality
2026-03-15 05:46:51 -05:00
Revela 0f89dea817 Merge branch 'main' of https://github.com/itsRevela/MinecraftConsoles 2026-03-15 04:00:31 -05:00
Revela f0495c546c Merge upstream/main into main
Brings in dedicated server software, README updates, and .vscode cleanup
while preserving hardcore mode, screenshot, and watermark toggle features.
2026-03-15 03:54:37 -05:00
Revela 6aea7c4bb7 Add F2 screenshot functionality and image writing support
- Updated `EControllerActions` to include `MINECRAFT_ACTION_SCREENSHOT`.
- Added conditional compilation for `stb_image_write.h` in `Minecraft.cpp`.
- Modified `run_middle()` to handle screenshot key press.
- Updated `tick()` to capture and save screenshots as PNG files.
- Introduced `KEY_SCREENSHOT` in `KeyboardMouseInput.h` mapped to F2.
- Added `stb_image_write.h` for image writing capabilities.
2026-03-15 03:47:31 -05:00
Loki Rautio f8963326fe Update README.md 2026-03-15 03:10:20 -05:00
Loki Rautio b415a6bf6b Update README.md 2026-03-15 03:10:20 -05:00
Loki Rautio ab9b034c51 Update README.md
fixed up some ordering and made it a little more organized, added new
banner image
2026-03-15 03:09:41 -05:00
Loki Rautio d5320de154 Update README.md
fixed up some ordering and made it a little more organized, added new
banner image
2026-03-15 03:09:41 -05:00
Loki Rautio a80fe2e900 Remove .vscode settings by default
this makes it impossible to search for stuff in the assets with VS Code
which sucks. if you need this you can just copy the file locally
2026-03-15 02:44:59 -05:00
Loki Rautio b739987996 Remove .vscode settings by default
this makes it impossible to search for stuff in the assets with VS Code
which sucks. if you need this you can just copy the file locally
2026-03-15 02:44:59 -05:00
f483074cd2 Dedicated Server Software - Minecraft.Server.exe (#498)
* add: Dedicated Server implementation

- Introduced `ServerMain.cpp` for the dedicated server logic, handling command-line arguments, server initialization, and network management.
- Created `postbuild_server.ps1` script for post-build tasks, including copying necessary resources and DLLs for the dedicated server.
- Added `CopyServerAssets.cmake` to manage the copying of server assets during the build process, ensuring required files are available for the dedicated server.
- Defined project filters in `Minecraft.Server.vcxproj.filters` for better organization of server-related files.

* add: refactor world loader & add server properties

- Introduced ServerLogger for logging startup steps and world I/O operations.
- Implemented ServerProperties for loading and saving server configuration from `server.properties`.
- Added WorldManager to handle world loading and creation based on server properties.
- Updated ServerMain to integrate server properties loading and world management.
- Enhanced project files to include new source and header files for the server components.

* update: implement enhanced logging functionality with configurable log levels

* update: update keyboard and mouse input initialization 1dc8a005ed

* fix: change virtual screen resolution to 1920x1080(HD)

Since 31881af56936aeef38ff322b975fd0 , `skinHud.swf` for 720 is not included in `MediaWindows64.arc`,
the app crashes unless the virtual screen is set to HD.

* fix: dedicated server build settings for miniaudio migration and missing sources

- remove stale Windows64 Miles (mss64) link/copy references from server build
- add Common/Filesystem/Filesystem.cpp to Minecraft.Server.vcxproj
- add Windows64/PostProcesser.cpp to Minecraft.Server.vcxproj
- fix unresolved externals (PostProcesser::*, FileExists) in dedicated server build

* update: changed the virtual screen to 720p

Since the crash caused by the 720p `skinHud.swf` not being included in `MediaWindows64.arc` has been resolved, switching back to 720p to reduce resource usage.

* add: add Docker support for Dedicated Server

add with entrypoint and build scripts

* fix: add initial save for newly created worlds in dedicated server

on the server side, I fixed the behavior introduced after commit aadb511, where newly created worlds are intentionally not saved to disk immediately.

* update: add basically all configuration options that are implemented in the classes to `server.properties`

* update: add LAN advertising configuration for server.properties

LAN-Discovery, which isn’t needed in server mode and could potentially be a security risk, has also been disabled(only server mode).

* add: add implementing interactive command line using linenoise

- Integrated linenoise library for line editing and completion in the server console.
- Updated ServerLogger to handle external writes safely during logging.
- Modified ServerMain to initialize and manage the ServerCli for command input.
- The implementation is separate from everything else, so it doesn't affect anything else.
- The command input section and execution section are separated into threads.

* update: enhance command line completion with predictive hints

Like most command line tools, it highlights predictions in gray.

* add: implement `StringUtils` for string manipulation and refactor usages

Unified the scattered utility functions.

* fix: send DisconnectPacket on shutdown and fix Win64 recv-thread teardown race

Before this change, server/host shutdown closed sockets directly in
ServerConnection::stop(), which bypassed the normal disconnect flow.
As a result, clients could be dropped without receiving a proper
DisconnectPacket during stop/kill/world-close paths.

Also, WinsockNetLayer::Shutdown() could destroy synchronization objects
while host-side recv threads were still exiting, causing a crash in
RecvThreadProc (access violation on world close in host mode).

* fix: return client to menus when Win64 host connection drops

- Add client-side host disconnect handling in CPlatformNetworkManagerStub::DoWork() for _WINDOWS64.
- When in QNET_STATE_GAME_PLAY as a non-host and WinsockNetLayer::IsConnected() becomes false, trigger g_NetworkManager.HandleDisconnect(false) to enter the normal disconnect/UI flow.
- Use m_bLeaveGameOnTick as a one-shot guard to prevent repeated disconnect handling while the link remains down.
- Reset m_bLeaveGameOnTick on LeaveGame(), HostGame(), and JoinGame() to avoid stale state across sessions.

* update: converted Japanese comments to English

* add: create `Minecraft.Server` developer guide in English and Japanese

* update: add note about issue

* add: add `nlohmann/json` json lib

* add: add FileUtils

Moved file operations to `utils`.

* add: Dedicated Server BAN access manager with persistent player and IP bans

- add Access frontend that publishes thread-safe ban manager snapshots for dedicated server use
- add BanManager storage for banned-players.json and banned-ips.json with load/save/update flows
- add persistent player and IP ban checks during dedicated server connection handling
- add UTF-8 BOM-safe JSON parsing and shared file helpers backed by nlohmann/json
- add Unicode-safe ban file read/write and safer atomic replacement behavior on Windows
- add active-ban snapshot APIs and expiry-aware filtering for expires metadata
- add RAII-based dedicated access shutdown handling during server startup and teardown

* update: changed file read/write operations to use `FileUtils`.

- As a side effect, saving has become faster!

* fix: Re-added the source that had somehow disappeared.

* add: significantly improved the dedicated server logging system

- add ServerLogManager to Minecraft.Server as the single entry point for dedicated-server log output
- forward CMinecraftApp logger output to the server logger when running with g_Win64DedicatedServer
- add named network logs for incoming, accepted, rejected, and disconnected connections
- cache connection metadata by smallId so player name and remote IP remain available for disconnect logs
- keep Minecraft.Client changes minimal by using lightweight hook points and handling log orchestration on the server side

* fix: added the updated library source

* add: add `ban` and `pardon` commands for Player and IP

* fix: fix stop command shutdown process

add dedicated server shutdown request handling

* fix: fixed the save logic during server shutdown

Removed redundant repeated saves and eliminated the risks of async writes.

* update: added new sever files to Docker entrypoint

* fix: replace shutdown flag with atomic variable for thread safety

* update: update Dedicated Server developer guide

English is machine translated.
Please forgive me.

* update: check for the existence of `GameHDD` and create

* add: add Whitelist to Dedicated Server

* refactor: clean up and refactor the code

- unify duplicated implementations that were copied repeatedly
- update outdated patterns to more modern ones

* fix: include UI header (new update fix)

* fix: fix the detection range for excessive logging

`getHighestNonEmptyY()` returning `-1` occurs normally when the chunk is entirely air.
The caller (`Minecraft.World/LevelChunk.cpp:2400`) normalizes `-1` to `0`.

* update: add world size config to dedicated server properties

* update: update README add explanation of  `server.properties` & launch arguments

* update: add nightly release workflow for dedicated server and client builds to Actions

* fix: update name for workflow

* add random seed generation

* add: add Docker nightly workflow for Dedicated Server publish to GitHub Container Registry

* fix: ghost player when clients disconnect out of order

#4

* fix: fix 7zip option

* fix: fix Docker workflow for Dedicated Server artifact handling

* add: add no build Dedicated Server startup scripts and Docker Compose

* update: add README for Docker Dedicated Server setup with no local build

* refactor: refactor command path structure

As the number of commands has increased and become harder to navigate, each command has been organized into separate folders.

* update: support stream(file stdin) input mode for server CLI

Support for the stream (file stdin) required when attaching a tty to a Docker container on Linux.

* add: add new CLI Console Commands for Dedicated Server

Most of these commands are executed using the command dispatcher implemented on the `Minecraft.World` side. When registering them with the dispatcher, the sender uses a permission-enabled configuration that treats the CLI as a player.

- default game.
- enchant
- experience.
- give
- kill(currently, getting a permission error for some reason)
- time
- weather.
- update tp & gamemode command

* fix: change player map icon to random select

* update: increase the player limit

* add: restore the basic anti-cheat implementation and add spawn protection

Added the following anti-cheat measures and add spawn protection to `server.properties`.
- instant break
- speed
- reach

* fix: fix Docker image tag

---------

Co-authored-by: sylvessa <225480449+sylvessa@users.noreply.github.com>
2026-03-15 02:32:50 -05:00
9079db0315 Dedicated Server Software - Minecraft.Server.exe (#498)
* add: Dedicated Server implementation

- Introduced `ServerMain.cpp` for the dedicated server logic, handling command-line arguments, server initialization, and network management.
- Created `postbuild_server.ps1` script for post-build tasks, including copying necessary resources and DLLs for the dedicated server.
- Added `CopyServerAssets.cmake` to manage the copying of server assets during the build process, ensuring required files are available for the dedicated server.
- Defined project filters in `Minecraft.Server.vcxproj.filters` for better organization of server-related files.

* add: refactor world loader & add server properties

- Introduced ServerLogger for logging startup steps and world I/O operations.
- Implemented ServerProperties for loading and saving server configuration from `server.properties`.
- Added WorldManager to handle world loading and creation based on server properties.
- Updated ServerMain to integrate server properties loading and world management.
- Enhanced project files to include new source and header files for the server components.

* update: implement enhanced logging functionality with configurable log levels

* update: update keyboard and mouse input initialization 1dc8a005ed

* fix: change virtual screen resolution to 1920x1080(HD)

Since 31881af56936aeef38ff322b975fd0 , `skinHud.swf` for 720 is not included in `MediaWindows64.arc`,
the app crashes unless the virtual screen is set to HD.

* fix: dedicated server build settings for miniaudio migration and missing sources

- remove stale Windows64 Miles (mss64) link/copy references from server build
- add Common/Filesystem/Filesystem.cpp to Minecraft.Server.vcxproj
- add Windows64/PostProcesser.cpp to Minecraft.Server.vcxproj
- fix unresolved externals (PostProcesser::*, FileExists) in dedicated server build

* update: changed the virtual screen to 720p

Since the crash caused by the 720p `skinHud.swf` not being included in `MediaWindows64.arc` has been resolved, switching back to 720p to reduce resource usage.

* add: add Docker support for Dedicated Server

add with entrypoint and build scripts

* fix: add initial save for newly created worlds in dedicated server

on the server side, I fixed the behavior introduced after commit aadb511, where newly created worlds are intentionally not saved to disk immediately.

* update: add basically all configuration options that are implemented in the classes to `server.properties`

* update: add LAN advertising configuration for server.properties

LAN-Discovery, which isn’t needed in server mode and could potentially be a security risk, has also been disabled(only server mode).

* add: add implementing interactive command line using linenoise

- Integrated linenoise library for line editing and completion in the server console.
- Updated ServerLogger to handle external writes safely during logging.
- Modified ServerMain to initialize and manage the ServerCli for command input.
- The implementation is separate from everything else, so it doesn't affect anything else.
- The command input section and execution section are separated into threads.

* update: enhance command line completion with predictive hints

Like most command line tools, it highlights predictions in gray.

* add: implement `StringUtils` for string manipulation and refactor usages

Unified the scattered utility functions.

* fix: send DisconnectPacket on shutdown and fix Win64 recv-thread teardown race

Before this change, server/host shutdown closed sockets directly in
ServerConnection::stop(), which bypassed the normal disconnect flow.
As a result, clients could be dropped without receiving a proper
DisconnectPacket during stop/kill/world-close paths.

Also, WinsockNetLayer::Shutdown() could destroy synchronization objects
while host-side recv threads were still exiting, causing a crash in
RecvThreadProc (access violation on world close in host mode).

* fix: return client to menus when Win64 host connection drops

- Add client-side host disconnect handling in CPlatformNetworkManagerStub::DoWork() for _WINDOWS64.
- When in QNET_STATE_GAME_PLAY as a non-host and WinsockNetLayer::IsConnected() becomes false, trigger g_NetworkManager.HandleDisconnect(false) to enter the normal disconnect/UI flow.
- Use m_bLeaveGameOnTick as a one-shot guard to prevent repeated disconnect handling while the link remains down.
- Reset m_bLeaveGameOnTick on LeaveGame(), HostGame(), and JoinGame() to avoid stale state across sessions.

* update: converted Japanese comments to English

* add: create `Minecraft.Server` developer guide in English and Japanese

* update: add note about issue

* add: add `nlohmann/json` json lib

* add: add FileUtils

Moved file operations to `utils`.

* add: Dedicated Server BAN access manager with persistent player and IP bans

- add Access frontend that publishes thread-safe ban manager snapshots for dedicated server use
- add BanManager storage for banned-players.json and banned-ips.json with load/save/update flows
- add persistent player and IP ban checks during dedicated server connection handling
- add UTF-8 BOM-safe JSON parsing and shared file helpers backed by nlohmann/json
- add Unicode-safe ban file read/write and safer atomic replacement behavior on Windows
- add active-ban snapshot APIs and expiry-aware filtering for expires metadata
- add RAII-based dedicated access shutdown handling during server startup and teardown

* update: changed file read/write operations to use `FileUtils`.

- As a side effect, saving has become faster!

* fix: Re-added the source that had somehow disappeared.

* add: significantly improved the dedicated server logging system

- add ServerLogManager to Minecraft.Server as the single entry point for dedicated-server log output
- forward CMinecraftApp logger output to the server logger when running with g_Win64DedicatedServer
- add named network logs for incoming, accepted, rejected, and disconnected connections
- cache connection metadata by smallId so player name and remote IP remain available for disconnect logs
- keep Minecraft.Client changes minimal by using lightweight hook points and handling log orchestration on the server side

* fix: added the updated library source

* add: add `ban` and `pardon` commands for Player and IP

* fix: fix stop command shutdown process

add dedicated server shutdown request handling

* fix: fixed the save logic during server shutdown

Removed redundant repeated saves and eliminated the risks of async writes.

* update: added new sever files to Docker entrypoint

* fix: replace shutdown flag with atomic variable for thread safety

* update: update Dedicated Server developer guide

English is machine translated.
Please forgive me.

* update: check for the existence of `GameHDD` and create

* add: add Whitelist to Dedicated Server

* refactor: clean up and refactor the code

- unify duplicated implementations that were copied repeatedly
- update outdated patterns to more modern ones

* fix: include UI header (new update fix)

* fix: fix the detection range for excessive logging

`getHighestNonEmptyY()` returning `-1` occurs normally when the chunk is entirely air.
The caller (`Minecraft.World/LevelChunk.cpp:2400`) normalizes `-1` to `0`.

* update: add world size config to dedicated server properties

* update: update README add explanation of  `server.properties` & launch arguments

* update: add nightly release workflow for dedicated server and client builds to Actions

* fix: update name for workflow

* add random seed generation

* add: add Docker nightly workflow for Dedicated Server publish to GitHub Container Registry

* fix: ghost player when clients disconnect out of order

#4

* fix: fix 7zip option

* fix: fix Docker workflow for Dedicated Server artifact handling

* add: add no build Dedicated Server startup scripts and Docker Compose

* update: add README for Docker Dedicated Server setup with no local build

* refactor: refactor command path structure

As the number of commands has increased and become harder to navigate, each command has been organized into separate folders.

* update: support stream(file stdin) input mode for server CLI

Support for the stream (file stdin) required when attaching a tty to a Docker container on Linux.

* add: add new CLI Console Commands for Dedicated Server

Most of these commands are executed using the command dispatcher implemented on the `Minecraft.World` side. When registering them with the dispatcher, the sender uses a permission-enabled configuration that treats the CLI as a player.

- default game.
- enchant
- experience.
- give
- kill(currently, getting a permission error for some reason)
- time
- weather.
- update tp & gamemode command

* fix: change player map icon to random select

* update: increase the player limit

* add: restore the basic anti-cheat implementation and add spawn protection

Added the following anti-cheat measures and add spawn protection to `server.properties`.
- instant break
- speed
- reach

* fix: fix Docker image tag

---------

Co-authored-by: sylvessa <225480449+sylvessa@users.noreply.github.com>
2026-03-15 02:32:50 -05:00
RevelaandGitHub ddf60a573e Readme: Fix multiplayer exit loophole for non-host players
Added multiplayer fix to prevent host exit loophole.
2026-03-15 01:07:54 -05:00
Revela ae006e03f4 Prevent exit-without-saving loophole for hardcore players
Switch player to Adventure mode on death in hardcore mode, ban their XUID, and trigger a save action to prevent quitting without saving.
2026-03-15 00:37:14 -05:00
Revela 52271f05fe Powershell script that updates Nightly release & archives previous versions 2026-03-13 22:46:05 -05:00
RevelaandGitHub 4256a8b43a Merge branch 'smartcmd:main' into main 2026-03-13 21:48:39 -05:00
troglodyte9andGitHub 4d200a589d Fixed dangling pointer issue (#1209) 2026-03-13 20:32:02 +00:00
troglodyte9andGitHub 7e0faa7a66 Fixed dangling pointer issue (#1209) 2026-03-13 20:32:02 +00:00
rtm516andGitHub 4e4e4dff0a Remove all old binka redist files (#1116)
* Remove all old binka redist files

* Delete x64/Debug/Effects.msscmp

* Delete x64/Release/Effects.msscmp
2026-03-13 19:43:37 +00:00
rtm516andGitHub c269fa31f1 Remove all old binka redist files (#1116)
* Remove all old binka redist files

* Delete x64/Debug/Effects.msscmp

* Delete x64/Release/Effects.msscmp
2026-03-13 19:43:37 +00:00
Revela fc544e612e Merge branch 'main' of https://github.com/itsRevela/MinecraftConsoles 2026-03-13 11:11:43 -05:00
Revela c3b204f77b Fix Gui.cpp merge and enhance hardcore mode visuals
This commit adds new `NamedFrame` entries and `KeyFrame` animations in `skin_Minecraft.xui` for various hardcore game modes, improving the UI representation (likely will get rid of this since it's dead code). A new `isHardcore` variable in `XUI_HUD.cpp` allows for conditional health icon animations based on the game mode. Additionally, commented-out code in `Gui.cpp` has been removed to streamline rendering logic. Several new PNG images for health states in hardcore mode have also been added to enhance the user experience.

TL;DR: This commit is basically just prep for adding hardcore heathbar hearts while also fixing some breaking that occurred in Gui.cpp after a merge.
2026-03-13 11:11:21 -05:00
RevelaandGitHub 0bc1f2fc1a Update image in README for Hardcore Mode 2026-03-13 08:51:32 -05:00
Revela 324b116b7d Merge branch 'main' of https://github.com/itsRevela/MinecraftConsoles 2026-03-13 08:50:14 -05:00
Revela 07700eb0b0 added hardcore preview image 2026-03-13 08:50:05 -05:00
RevelaandGitHub 3cc8d7d9f1 Update README with Hardcore Mode features
Added details about the latest Hardcore Mode implementation including features for singleplayer and multiplayer.
2026-03-13 08:46:17 -05:00
Revela b6d19582b6 Merge branch 'smartcmd:main' into main 2026-03-13 07:17:11 -05:00
Revela 514c4cf102 smartcmd/MinecraftConsoles and itsRevela/MinecraftConsoles network packet compatibility fix:
LoginPacket.cpp:
  - read(): Extracts hardcore from bit 3 of gameType (gameType & 0x8), then masks it off (gameType &
  ~0x8)
  - write(): Encodes hardcore into gameType via gameType | (m_isHardcore ? 0x8 : 0)
  - Removed the separate readBoolean()/writeBoolean() for m_isHardcore
  - Removed trailing + sizeof(bool) from getEstimatedSize()

  RespawnPacket.cpp:
  - read(): Extracts hardcore from bit 3 of the playerGameType byte, then masks it off before passing
  to GameType::byId()
  - write(): Encodes hardcore into the playerGameType byte via getId() | (m_isHardcore ? 0x8 : 0)
  - Removed the separate readBoolean()/writeBoolean() for m_isHardcore
  - Reverted getEstimatedSize() from 14+length to 13+length
2026-03-13 07:12:26 -05:00
Revela b28c0026af detailed summary of every changed file:
---
  Minecraft.Client/ClientConnection.cpp

  Purpose: Propagate hardcore flag through network level creation

  - handleLogin() (2 sites): Changed MultiPlayerLevel constructor calls from hardcoded false for the
  hardcore parameter to packet->m_isHardcore, so the client-side level correctly knows it's hardcore
  when joining a server.
  - handleRespawn(): Same change - when creating a new dimension level on respawn, uses
  packet->m_isHardcore instead of querying minecraft->level->getLevelData()->isHardcore() (which could
   be stale/wrong).

  ---
  Minecraft.Client/Common/App_Defines.h

  Purpose: Define bitmask for hardcore host option

  - Added GAME_HOST_OPTION_BITMASK_HARDCORE (0x40000000) - a new bit in the host options bitfield to
  store whether the game is hardcore.

  ---
  Minecraft.Client/Common/App_enums.h

  Purpose: Add hardcore enum value

  - Added eGameHostOption_Hardcore to the eGameHostOption enum so code can get/set the hardcore flag
  via SetGameHostOption/GetGameHostOption.

  ---
  Minecraft.Client/Common/Consoles_App.cpp

  Purpose: Implement hardcore get/set in host options bitfield

  - SetGameHostOption(): Added case eGameHostOption_Hardcore - sets or clears the
  GAME_HOST_OPTION_BITMASK_HARDCORE bit.
  - GetGameHostOption(): Added case eGameHostOption_Hardcore - returns 1 if the hardcore bit is set, 0
   otherwise.

  ---
  Minecraft.Client/Common/Consoles_App.h

  Purpose: Store save folder name for hardcore world deletion

  - Added SetCurrentSaveFolderName() and GetCurrentSaveFolderName() public methods.
  - Added wstring m_currentSaveFolderName private member - stores the save folder name so the hardcore
   death handler can find and delete the world.

  ---
  Minecraft.Client/Common/UI/IUIScene_PauseMenu.cpp

  Purpose: Delete hardcore world's save data on exit

  - Added Win64_DeleteSaveDirectory() - a recursive directory deletion helper (Windows64 only).
  - In _ExitWorld(): Before the server is torn down, captures whether this is a hardcore death exit
  (getDeleteWorldOnExit()). Tries 3 sources for the save folder name: app storage, StorageManager, and
   MinecraftServer.
  - After the server fully stops, if shouldDeleteHardcoreWorld is true, deletes the entire
  Windows64\GameHDD\<savefolder> directory.

  ---
  Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp

  Purpose: Hardcore difficulty slider in Create World menu

  - Added file-scope s_bHardcore flag to track when the slider is at position 4 (Hardcore).
  - Constructor: Extended difficulty slider range from 0-3 to 0-4, resets s_bHardcore to false.
  - handleSliderMove(): When slider value >= 4, sets s_bHardcore = true, stores actual difficulty as 3
   (Hard), and displays "Hardcore" label. Otherwise behaves normally.
  - CreateGame(): Clears the save folder name (new world), and sets eGameHostOption_Hardcore based on
  s_bHardcore.
  - Minor: Changed RequestErrorMessage to RequestAlertMessage for a content restriction dialog.

  ---
  Minecraft.Client/Common/UI/UIScene_DeathMenu.cpp

  Purpose: Hardcore death screen behavior (Iggy UI)

  - Constructor: Checks if current level is hardcore. If so, shows IDS_HARDCORE_DEATH_MESSAGE on the
  respawn button and hides it. Otherwise shows normal "Respawn" button.
  - handlePress() - Respawn: Added safeguard - if hardcore, blocks respawn entirely.
  - handlePress() - Exit Game: If hardcore and host, skips save dialog, disables save-on-exit, enables
   delete-world-on-exit, and triggers immediate world exit.

  ---
  Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp

  Purpose: Show "Difficulty: Hardcore" in Load World menu + persist hardcore through game launch

  - Static array: Expanded m_iDifficultyTitleSettingA from 4 to 5 entries, added IDS_GAMEMODE_HARDCORE
   at index 4.
  - Constructor: Initializes m_bHardcore = false. In Windows64 block: sets up thumbnail name from save
   details, and reads isHardcore from params->saveDetails. If hardcore, immediately initializes the
  difficulty slider to show "Hardcore" locked at position 4.
  - tick(): When host options are read (bHostOptionsRead block), also reads the hardcore flag and
  re-initializes the slider if needed (for console path).
  - handleSliderMove(): If m_bHardcore, locks the slider at position 4 (prevents changing difficulty).
  - StartGameFromSave(): Stores the save folder name in app for later hardcore deletion. Sets
  eGameHostOption_Hardcore from m_bHardcore.

  ---
  Minecraft.Client/Common/UI/UIScene_LoadMenu.h

  Purpose: Declare hardcore member

  - Expanded m_iDifficultyTitleSettingA from [4] to [5].
  - Added bool m_bHardcore private member.

  ---
  Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp

  Purpose: Read hardcore flag from level.dat when building the save list

  - ReadLevelNameFromSaveFile(): Added optional bool *outHardcore parameter. Inside the NBT Data
  compound tag parsing, if outHardcore is non-null, reads dataTag->getBoolean(L"hardcore").
  - Save enumeration block (Windows64): Passes &saveHardcore to ReadLevelNameFromSaveFile and stores
  the result in m_saveDetails[i].isHardcore.

  ---
  Minecraft.Client/Common/UI/UIStructs.h

  Purpose: Add isHardcore to save list details struct

  - Added bool isHardcore field to _SaveListDetails struct.
  - Initialized to false in the constructor.

  ---
  Minecraft.Client/Common/XUI/XUI_Death.cpp

  Purpose: Hardcore death screen behavior (XUI/Xbox UI)

  - Mirror of the Iggy UIScene_DeathMenu.cpp changes but for the XUI rendering path.
  - OnInit(): Checks isHardcore(), hides respawn button and shows death message if true.
  - OnNotifyPressEx() - Exit Game: If hardcore and host, skips save, flags world for deletion, exits
  immediately.
  - OnNotifyPressEx() - Respawn: Safeguard to block respawn in hardcore.

  ---
  Minecraft.Client/Gui.cpp

  Purpose: Syntax fix

  - Fixed lines.push_back(L"" → lines.push_back(L"") - missing closing quote/paren in debug terrain
  feature display.

  ---
  Minecraft.Client/MinecraftServer.cpp

  Purpose: Server-side hardcore support

  - Constructor: Initializes m_deleteWorldOnExit = false.
  - loadLevel(): Captures the save folder name from StorageManager into m_saveFolderName for later use
   in hardcore world deletion.
  - isHardcore(): Changed from always returning false to returning
  app.GetGameHostOption(eGameHostOption_Hardcore) > 0 - this is the key change that makes the server
  actually report hardcore mode.

  ---
  Minecraft.Client/MinecraftServer.h

  Purpose: Declare hardcore-related members

  - Added bool m_deleteWorldOnExit and wstring m_saveFolderName private members.
  - Added setDeleteWorldOnExit(), getDeleteWorldOnExit(), and getSaveFolderName() public methods.

  ---
  Minecraft.Client/PlayerConnection.h

  Purpose: Thread-safety fix for kicked flag

  - Changed m_bWasKicked from bool to std::atomic<bool> (initialized with {false}).
  - Changed setWasKicked()/getWasKicked() to use .store()/.load() - fixes a race condition where the
  kicked flag is set on one thread and read on another.

  ---
  Minecraft.Client/PlayerList.cpp

  Purpose: Hardcore multiplayer - ban, respawn as Adventure, thread-safe bans

  - Constructor/Destructor: Added InitializeCriticalSection/DeleteCriticalSection for m_banCS.
  - placeNewPlayer(): Passes isHardcore() flag to the LoginPacket constructor so clients joining know
  it's hardcore.
  - respawn(): After respawn in hardcore, forces the player into Adventure mode (spectate-like: can
  look around but not interact). Sends GameEventPacket to sync client.
  - respawn() and toggleDimension() (2 sites): Pass isHardcore() to RespawnPacket constructor.
  - isXuidBanned(): Wrapped m_bannedXuids iteration with EnterCriticalSection/LeaveCriticalSection for
   thread safety.
  - banXuid() (new): Thread-safe method to add a player's XUID to the ban list - used when a player
  dies in hardcore multiplayer.

  ---
  Minecraft.Client/PlayerList.h

  Purpose: Declare ban-related additions

  - Added CRITICAL_SECTION m_banCS to protect m_bannedXuids.
  - Added void banXuid(PlayerUID xuid) public method.

  ---
  Minecraft.Client/SelectWorldScreen.cpp

  Purpose: Show [Hardcore] badge in Java-style world list

  - In renderItem(): If levelSummary->isHardcore(), appends  [Hardcore] to the world name display.

  ---
  Minecraft.Client/ServerPlayer.cpp

  Purpose: Hardcore death behavior on server

  - die(): If the level is hardcore, switches the dead player to Adventure mode (so they can't
  interact if somehow respawned).
  - Minor: Two comment lines changed // → /// (no functional change).

  ---
  Minecraft.Client/Windows64Media/strings.h

  Purpose: String IDs for hardcore UI text

  - Added 8 new string IDs (2286-2293): IDS_GAMEMODE_HARDCORE, IDS_HARDCORE, IDS_HARDCORE_TOOLTIP,
  IDS_HARDCORE_WARNING_TITLE, IDS_HARDCORE_WARNING_TEXT, IDS_HARDCORE_DEATH_MESSAGE,
  IDS_LABEL_HARDCORE, IDS_GAMEOPTION_HARDCORE.

  ---
  Minecraft.World/ConsoleSaveFileOriginal.cpp

  Purpose: Capture save folder name after first save (for new worlds)

  - SaveSaveDataCallback() (Windows64 only): After a successful save, if the app doesn't yet know the
  save folder name, attempts to capture it via StorageManager or by scanning Windows64\GameHDD\ for
  the newest folder. This handles the case where a newly-created hardcore world hasn't been saved yet
  when the folder name is needed.

  ---
  Minecraft.World/DisconnectPacket.h

  Purpose: Hardcore disconnect reason

  - Added eDisconnect_HardcoreDeath to the disconnect reason enum - used when kicking a player who
  died in hardcore multiplayer.

  ---
  Minecraft.World/LoginPacket.cpp & LoginPacket.h

  Purpose: Serialize hardcore flag in login packet

  - Added bool m_isHardcore member, initialized to false in both constructors.
  - Server→Client constructor now accepts bool isHardcore = false parameter.
  - read(): Reads m_isHardcore from the stream.
  - write(): Writes m_isHardcore to the stream.
  - getEstimatedSize(): Added sizeof(bool) for the new field.

  ---
  Minecraft.World/RespawnPacket.cpp & RespawnPacket.h

  Purpose: Serialize hardcore flag in respawn packet

  - Added bool m_isHardcore member, initialized to false.
  - Constructor now accepts bool isHardcore = false parameter.
  - read()/write(): Serialize m_isHardcore via readBoolean()/writeBoolean().
  - getEstimatedSize(): Changed from 13 to 14 bytes to account for the new boolean.
2026-03-13 06:56:46 -05:00
Prakhar SharmaandGitHub 379434097a Fix witches' bottle color (#1205)
* fix: witches' bottle is now the right color

* fix: add condition if item has mutiple layers
2026-03-13 11:41:47 +00:00
Prakhar SharmaandGitHub 445567ddf7 Fix witches' bottle color (#1205)
* fix: witches' bottle is now the right color

* fix: add condition if item has mutiple layers
2026-03-13 11:41:47 +00:00
Ayush ThorenandGitHub d131a551bf Fix mounted minecarts not persisting across world reloads (#979)
* Fix mounted minecarts not persisting across world reloads

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

* Apply patch

---------

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-13 11:16:05 +00:00
Ayush ThorenandGitHub 32ddc6d967 Fix mounted minecarts not persisting across world reloads (#979)
* Fix mounted minecarts not persisting across world reloads

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>

* Apply patch

---------

Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-13 11:16:05 +00:00
MrTheShyandGitHub ad74d44300 Fix joining servers in split screen, splitscreen fixes (#1031)
* Fix split-screen join failing when connecting to a remote host via UI

When a non-host client connected to a remote server through the in-game
UI (as opposed to the -ip/-port command line flags), the global variables
g_Win64MultiplayerIP and g_Win64MultiplayerPort were never updated from
their defaults ("127.0.0.1" and the default port). JoinSplitScreen()
relies on these globals to open a second TCP connection for the local
split-screen pad, so it would always attempt to connect to localhost,
failing immediately on any remote session.

Fix: update g_Win64MultiplayerIP and g_Win64MultiplayerPort inside
JoinGame() once the primary connection is established. This ensures
subsequent JoinSplitScreen() calls always reach the correct host
regardless of how the session was joined.

Additionally, guard PushFreeSmallId() against recycling smallIds in the
range [0, XUSER_MAX_COUNT), which are permanently reserved for the
host's local controller slots. Previously, if a host-side local pad
disconnected its smallId could re-enter the free pool and be handed
to an incoming remote client, causing that client's IQNetPlayer slot
to collide with a local pad slot on the non-host machine.

* Fix tutorial popup positioning in split-screen viewports

Replace the manual switch-case that computed viewport origin with the shared GetViewportRect/Fit16x9 helpers (from UISplitScreenHelpers.h). This ensures the tutorial popup is positioned and scaled consistently with the rest of the split-screen UI, fitting a 16:9 box inside each viewport and applying safezone offsets correctly.

Also adds missing default:break to safezone switch statements to silence compiler warnings.

Made-with: Cursor

* Prevent split-screen join when game window is not focused

Add g_KBMInput.IsWindowFocused() guard to the tryJoin condition so that gamepad input from background windows does not accidentally trigger a split-screen player join. This avoids phantom joins when the user is interacting with another application.

* Open debug overlay in fullscreen UI group during split-screen

Pass eUIGroup_Fullscreen to NavigateToScene when opening the debug overlay, so it spans the entire window instead of being confined to a single split-screen viewport. This makes the debug info readable regardless of the current split-screen layout.

* Fix non-host split-screen connections missing world updates

Previously, secondary (non-host) split-screen connections used isPrimaryConnection()
to gate nearly all world update packets, meaning the second local player would never
receive tile updates, entity movement, sounds, particles, explosions, etc.

The fix introduces per-connection tracking of which entities and chunks each
ClientConnection has loaded, and uses that information to decide whether a secondary
connection needs to process a given packet or if the primary connection already
handled it.

New members in ClientConnection:
- m_trackedEntityIds: set of entity IDs this connection has received AddEntity/AddMob/AddPlayer etc. for
- m_visibleChunks: set of chunk coordinates (packed into int64) this connection has marked visible
- Both sets are cleared on close(), respawn (dimension change), and destructor

New helpers:
- findPrimaryConnection(): walks the MultiPlayerLevel connection list to find the connection on the primary pad
- shouldProcessForEntity(id): secondary connection skips the packet only if the primary is already tracking that entity
- shouldProcessForPosition(x, z): secondary connection skips the packet only if the primary already has that chunk visible
- anyOtherConnectionHasChunk(x, z): used when a chunk becomes invisible to avoid hiding it from the level if another connection still needs it
- isTrackingEntity(id): public accessor used by shouldProcessForEntity on the primary connection

Packet handler changes:
- handleMoveEntity, handleMoveEntitySmall, handleSetEntityMotion, handleTakeItemEntity:
  replaced isPrimaryConnection() with shouldProcessForEntity() so secondary
  connections still process movement for entities they know about
- handleExplosion, handleLevelEvent:
  replaced isPrimaryConnection() with shouldProcessForPosition() so block
  destruction and level events fire for the correct connection based on chunks
- handleChunkTilesUpdate, handleBlockRegionUpdate, handleTileUpdate, handleSignUpdate,
  handleTileEntityData, handleTileEvent, handleTileDestruction, handleComplexItemData,
  handleSoundEvent, handleParticleEvent:
  removed the isPrimaryConnection() guard entirely -- these are world-state updates
  that all connections must process regardless of which pad is primary
- handleChunkVisibilityArea / handleChunkVisibility:
  now populate m_visibleChunks; on visibility=false, setChunkVisible(false) is
  only called on the level if no other connection still has that chunk loaded
- handleAddEntity, handleAddExperienceOrb, handleAddPainting, handleAddPlayer,
  handleAddMob: now insert into m_trackedEntityIds on arrival
- handleRemoveEntity: now erases from m_trackedEntityIds on removal
- handleLevelEvent: removed a duplicate levelEvent() call that was always firing
  regardless of the isPrimaryConnection() check above it (latent bug)

MultiPlayerLevel: added friend class ClientConnection to allow access to the
connections list without exposing it publicly.

* Fix fullscreen progress screen swallowing input before load completes

Two issues in UIScene_FullscreenProgress::handleInput:

1. The touchpad/button press that triggers movie skip or input forwarding
   had no guard on m_threadCompleted, so pressing a button during the loading
   phase would fire the skip/send logic before the background thread finished.
   Added the m_threadCompleted check so that path is only reachable once
   the load is actually done.

2. The `handled = true` assignment was missing from that branch, so input
   events were not being consumed and could fall through to other handlers.
   Added it unconditionally at the end of the block.

* Update player count decrement logic in PlatformNetworkManagerStub

Refactor the condition for decrementing the player count in CPlatformNetworkManagerStub::DoWork. The previous check was replaced with a while loop to ensure that the player count is only decremented when there are more than one player and the last player's custom data value is zero. This change improves the handling of player connections in the network manager.

* Refactor safe zone calculations in UI components for consistency

Updated the safe zone calculations across multiple UI components to ensure symmetry in split viewports. Removed unnecessary assignments and added comments for clarity. Modified the repositionHud function to include an additional parameter for better handling of HUD positioning in split-screen scenarios.

* Gui.cpp: fix F3 debug overlay in splitscreen + minor perf cleanup

The F3 debug screen was badly broken in splitscreen: it used the GUI
coordinate space which gets distorted by the splitscreen scaling, so
text appeared stretched, misaligned or completely off-screen depending
on the viewport layout.

Fixed by setting up a dedicated projection matrix using physical pixel
coordinates (g_rScreenWidth / g_rScreenHeight) each time the overlay is
drawn, completely decoupled from whatever transform the HUD is using.
The viewport dimensions are now computed per screen section so the ortho
projection matches the actual pixel area of each player's quadrant.
Version and branch strings are only shown for player 0 (iPad == 0) to
avoid repeating them across every splitscreen pane.

Also removed a few redundant calculations that were being done twice in
the same frame (atan for xRot, health halves, air supply scaled value).
These are minor and have negligible real-world impact; more substantial
per-frame caching work (safe zone calculations etc.) will follow in a
separate commit.
2026-03-13 01:32:18 -05:00
MrTheShyandGitHub 21c5d3d193 Fix joining servers in split screen, splitscreen fixes (#1031)
* Fix split-screen join failing when connecting to a remote host via UI

When a non-host client connected to a remote server through the in-game
UI (as opposed to the -ip/-port command line flags), the global variables
g_Win64MultiplayerIP and g_Win64MultiplayerPort were never updated from
their defaults ("127.0.0.1" and the default port). JoinSplitScreen()
relies on these globals to open a second TCP connection for the local
split-screen pad, so it would always attempt to connect to localhost,
failing immediately on any remote session.

Fix: update g_Win64MultiplayerIP and g_Win64MultiplayerPort inside
JoinGame() once the primary connection is established. This ensures
subsequent JoinSplitScreen() calls always reach the correct host
regardless of how the session was joined.

Additionally, guard PushFreeSmallId() against recycling smallIds in the
range [0, XUSER_MAX_COUNT), which are permanently reserved for the
host's local controller slots. Previously, if a host-side local pad
disconnected its smallId could re-enter the free pool and be handed
to an incoming remote client, causing that client's IQNetPlayer slot
to collide with a local pad slot on the non-host machine.

* Fix tutorial popup positioning in split-screen viewports

Replace the manual switch-case that computed viewport origin with the shared GetViewportRect/Fit16x9 helpers (from UISplitScreenHelpers.h). This ensures the tutorial popup is positioned and scaled consistently with the rest of the split-screen UI, fitting a 16:9 box inside each viewport and applying safezone offsets correctly.

Also adds missing default:break to safezone switch statements to silence compiler warnings.

Made-with: Cursor

* Prevent split-screen join when game window is not focused

Add g_KBMInput.IsWindowFocused() guard to the tryJoin condition so that gamepad input from background windows does not accidentally trigger a split-screen player join. This avoids phantom joins when the user is interacting with another application.

* Open debug overlay in fullscreen UI group during split-screen

Pass eUIGroup_Fullscreen to NavigateToScene when opening the debug overlay, so it spans the entire window instead of being confined to a single split-screen viewport. This makes the debug info readable regardless of the current split-screen layout.

* Fix non-host split-screen connections missing world updates

Previously, secondary (non-host) split-screen connections used isPrimaryConnection()
to gate nearly all world update packets, meaning the second local player would never
receive tile updates, entity movement, sounds, particles, explosions, etc.

The fix introduces per-connection tracking of which entities and chunks each
ClientConnection has loaded, and uses that information to decide whether a secondary
connection needs to process a given packet or if the primary connection already
handled it.

New members in ClientConnection:
- m_trackedEntityIds: set of entity IDs this connection has received AddEntity/AddMob/AddPlayer etc. for
- m_visibleChunks: set of chunk coordinates (packed into int64) this connection has marked visible
- Both sets are cleared on close(), respawn (dimension change), and destructor

New helpers:
- findPrimaryConnection(): walks the MultiPlayerLevel connection list to find the connection on the primary pad
- shouldProcessForEntity(id): secondary connection skips the packet only if the primary is already tracking that entity
- shouldProcessForPosition(x, z): secondary connection skips the packet only if the primary already has that chunk visible
- anyOtherConnectionHasChunk(x, z): used when a chunk becomes invisible to avoid hiding it from the level if another connection still needs it
- isTrackingEntity(id): public accessor used by shouldProcessForEntity on the primary connection

Packet handler changes:
- handleMoveEntity, handleMoveEntitySmall, handleSetEntityMotion, handleTakeItemEntity:
  replaced isPrimaryConnection() with shouldProcessForEntity() so secondary
  connections still process movement for entities they know about
- handleExplosion, handleLevelEvent:
  replaced isPrimaryConnection() with shouldProcessForPosition() so block
  destruction and level events fire for the correct connection based on chunks
- handleChunkTilesUpdate, handleBlockRegionUpdate, handleTileUpdate, handleSignUpdate,
  handleTileEntityData, handleTileEvent, handleTileDestruction, handleComplexItemData,
  handleSoundEvent, handleParticleEvent:
  removed the isPrimaryConnection() guard entirely -- these are world-state updates
  that all connections must process regardless of which pad is primary
- handleChunkVisibilityArea / handleChunkVisibility:
  now populate m_visibleChunks; on visibility=false, setChunkVisible(false) is
  only called on the level if no other connection still has that chunk loaded
- handleAddEntity, handleAddExperienceOrb, handleAddPainting, handleAddPlayer,
  handleAddMob: now insert into m_trackedEntityIds on arrival
- handleRemoveEntity: now erases from m_trackedEntityIds on removal
- handleLevelEvent: removed a duplicate levelEvent() call that was always firing
  regardless of the isPrimaryConnection() check above it (latent bug)

MultiPlayerLevel: added friend class ClientConnection to allow access to the
connections list without exposing it publicly.

* Fix fullscreen progress screen swallowing input before load completes

Two issues in UIScene_FullscreenProgress::handleInput:

1. The touchpad/button press that triggers movie skip or input forwarding
   had no guard on m_threadCompleted, so pressing a button during the loading
   phase would fire the skip/send logic before the background thread finished.
   Added the m_threadCompleted check so that path is only reachable once
   the load is actually done.

2. The `handled = true` assignment was missing from that branch, so input
   events were not being consumed and could fall through to other handlers.
   Added it unconditionally at the end of the block.

* Update player count decrement logic in PlatformNetworkManagerStub

Refactor the condition for decrementing the player count in CPlatformNetworkManagerStub::DoWork. The previous check was replaced with a while loop to ensure that the player count is only decremented when there are more than one player and the last player's custom data value is zero. This change improves the handling of player connections in the network manager.

* Refactor safe zone calculations in UI components for consistency

Updated the safe zone calculations across multiple UI components to ensure symmetry in split viewports. Removed unnecessary assignments and added comments for clarity. Modified the repositionHud function to include an additional parameter for better handling of HUD positioning in split-screen scenarios.

* Gui.cpp: fix F3 debug overlay in splitscreen + minor perf cleanup

The F3 debug screen was badly broken in splitscreen: it used the GUI
coordinate space which gets distorted by the splitscreen scaling, so
text appeared stretched, misaligned or completely off-screen depending
on the viewport layout.

Fixed by setting up a dedicated projection matrix using physical pixel
coordinates (g_rScreenWidth / g_rScreenHeight) each time the overlay is
drawn, completely decoupled from whatever transform the HUD is using.
The viewport dimensions are now computed per screen section so the ortho
projection matches the actual pixel area of each player's quadrant.
Version and branch strings are only shown for player 0 (iPad == 0) to
avoid repeating them across every splitscreen pane.

Also removed a few redundant calculations that were being done twice in
the same frame (atan for xRot, health halves, air supply scaled value).
These are minor and have negligible real-world impact; more substantial
per-frame caching work (safe zone calculations etc.) will follow in a
separate commit.
2026-03-13 01:32:18 -05:00
RevelaandGitHub 176a3db770 Merge branch 'smartcmd:main' into main 2026-03-12 18:42:37 -05:00
ariaandGitHub 714462b130 Fix background stretching in settings>graphics menu (#1092) 2026-03-12 16:01:15 +00:00
RevelaandGitHub c00375b72c Merge branch 'smartcmd:main' into main 2026-03-12 07:59:09 -05:00
1cee2136d3 Added LittleBigPlanet Skin Pack (#793)
Co-authored-by: RatCatcherVr <littlerat111811@gmail.com>
2026-03-12 12:55:50 +00:00
Alezito2008andGitHub e140978daf fix: logo rendering order after closing host options (#907) 2026-03-12 12:52:09 +00:00
Twig6943andGitHub 1c32d7bc5d Remove some leftover files (#881) 2026-03-12 12:48:06 +00:00
Matt.TandGitHub e689562027 Fix SubEntity hitbox hit detection (#1175) 2026-03-12 12:32:27 +00:00
RevelaandGitHub 0b3281d17f Enhance Fluxer server link presentation
Updated Fluxer server link with a centered image.
2026-03-12 06:13:02 -05:00
RevelaandGitHub 857155f3d6 Fix spelling and update Fluxer server link image 2026-03-12 06:09:38 -05:00
RevelaandGitHub e0e3a00a83 Fluxer link in readme
Updated Discord link and added information about Fluxer server.
2026-03-12 05:58:26 -05:00
Revela 812b3ea6af Merge branch 'main' of https://github.com/itsRevela/MinecraftConsoles 2026-03-12 05:20:44 -05:00
RevelaandGitHub b51fb18120 Merge branch 'smartcmd:main' into main 2026-03-12 05:20:21 -05:00
Revela b1c44c33bd set default values 2026-03-12 05:19:39 -05:00
Ayush ThorenandGitHub bb8ffee0d3 Fix mouse being pulled to the bottom right (#1156)
Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-12 01:44:32 -05:00
ModMaker101andGitHub 44fc8a4db2 Fix quiet in-game audio after engine update #897 (#1171) 2026-03-12 01:43:12 -05:00
RevelaandGitHub 330d764972 Update download link for Nightly Build 2026-03-12 00:10:36 -05:00
Revela 3caa5713e5 Gives option to remove the top-left watermark in ClientConstants.cpp:
Watermark on:
const bool ClientConstants::SHOW_VERSION_WATERMARK = true;

Watermark off:
const bool ClientConstants::SHOW_VERSION_WATERMARK = false;
2026-03-11 23:56:22 -05:00
Revela 0631aefec2 Fix portal cache key to use chunk coordinates 2026-03-11 22:12:03 -05:00
MarvelcoandGitHub 1036b7368e Fixed DLC map loading / saving, missing chunks (#1114)
* fixed all DLC maps

* fixed old saves have overlapping chunks with the new system
2026-03-10 22:04:19 -05:00
LokiandGitHub a195ac7172 Only single topic PRs, please - CONTRIBUTING.md 2026-03-10 09:37:52 -05:00
laandGitHub d7596aa28c Fix issue where visually the HUD shows you have 0 hearts when you dont (#1089)
* Fix for issue where player is able to stay alive with zero hearts in their healthbar.

* use static cast over c style cast
2026-03-09 22:30:01 -05:00
eh-KandGitHub c998346312 FIX: Bonus Chests spawn again when loading back in. #982 (#992)
* Fixed bug where Bonus Chests would spawn again when loading back into it.

Fixes #982

Added a check for if the world is new.

Meaning no more additional chests if the world is loaded up again.

* Replace NULL with nullptr for chest check
2026-03-09 22:07:38 -05:00
91ae76f132 Fix tamed horses despawning when player moves away (#1057)
Co-authored-by: MCbabel <MCbabel@users.noreply.github.com>
2026-03-09 22:06:38 -05:00
Us3ful"-DevandGitHub c90a6bf5ab Fixed Enderman, monster aggro in creative (#1051)
Fixed endermans by making a invulnerable check
2026-03-09 22:05:56 -05:00
Alezito2008andGitHub 5f777a7f45 Fix: Prevent clicking disabled checkboxes (#1075) 2026-03-09 22:03:39 -05:00
3bcf588fbe Fix crash when loading saved tutorial worlds (#1001)
writeRuleFile() was missing the schematic file count integer before the schematic entries. The reader in readRuleFile() expected this count, causing a stream misalignment that led to an assertion failure (Unrecognised schematic version) when reloading a saved tutorial world.

The fix writes the count on save and adds backward-compatible reading that detects old saves (without count) via a peek heuristic and falls back to count-less parsing.

Co-authored-by: MCbabel <MCbabel@users.noreply.github.com>
2026-03-09 22:02:39 -05:00
Loki Rautio 58c236ead5 Disable git LFS
It was never even enabled properly to begin with
2026-03-09 20:49:50 -05:00
LokiandGitHub e6eafda90e Remove another servers.txt reference 2026-03-09 18:27:02 -05:00
LokiandGitHub 0fbc8903f3 Update README, remove servers.txt references 2026-03-09 18:26:00 -05:00
laandGitHub e9dba1fa56 Prevent TNT Minecart exploding with TNT disabled (#1067)
This set of changes was made to make the code better mimic TU20 based on its disassembly
2026-03-09 16:01:17 -05:00
Tuff CWCandGitHub fe65ec24f1 Remove dead link from README (#1064) 2026-03-09 15:02:26 -05:00
LokiandGitHub bda3b1078a Port over RCE Patches from LCEMP (#1023)
* LCEMP RCE Fixes WIP

Based on https://github.com/LCEMP/LCEMP/commit/d017bfc30a68888bf5c79b23cf5c4f607cf828bf

* Update to LCEMP's ByteArrayIO version

Fixes compilation since ours was missing some revisions from LCEMP

* Add additional safety checks missed in first pass

* Remove duplicate recipe count check
2026-03-09 06:53:08 -05:00
Loki Rautio a358a3caae Revert accidentally pushed "LCEMP RCE fixes"
This reverts commit d557ca2dfb.
2026-03-09 04:46:56 -05:00
Loki Rautio d557ca2dfb LCEMP RCE fixes
Based on commit d017bfc30a68888bf5c79b23cf5c4f607cf828bf
2026-03-09 04:45:14 -05:00
Loki Rautio 0c4f459904 Always show version overlay, add more info 2026-03-09 03:25:05 -05:00
MrTheShyandGitHub 7a4f57e3e6 Reject duplicate UIDs on login and remove noisy gdraw debug log (#1013)
Players joining a server with a UID already in use are now disconnected
instead of the existing player being force-kicked. The previous behaviour
introduced in #767 allowed two clients with the same UID to coexist,
causing invisible players and undefined behaviour.

Also removes a per-frame debug printf in gdraw_SetViewSizeAndWorldScale
that was left in from earlier resolution-fix work.
2026-03-08 23:10:00 -05:00
MrTheShyandGitHub e2adaa082c Fix split-screen UI wrong positioning on window resize (#989)
* Fix split-screen UI wrong positioning on window resize

In vertical split at window heights below 1080, ComputeTileScale's min-scale clamp (>= 1.0) prevented the SWF from scaling down to fit, cropping the bottom and causing repositionHud to shift HUD elements downward. Chat and Tooltips additionally applied an offset from ComputeSplitContentOffset that only produced correct values at the 1920x1080 design resolution.

Override the scale for vertical split so the SWF fits the full window height when it is shorter than the movie. Remove the broken content offset from Chat and Tooltips -- the tile crop already positions the content correctly.

* Fix gamma post-process in split-screen

The gamma shader sampled the full backbuffer texture (UV 0..1) into each player's viewport, stretching the entire screen into every split region. Extended the shader constant buffer with per-viewport UV offset and scale so each pass samples only its own portion of the backbuffer.

ComputeViewportForPlayer was hardcoded to top/bottom for 2 players, ignoring the vertical split setting. Rewrote it to read each player's m_iScreenSection directly, which already accounts for the split orientation preference.

Secondary players have no Graphics menu and cannot change gamma. CachePlayerGammas now reads the primary player's setting and applies it uniformly to all viewports.
2026-03-08 22:16:58 -05:00
MozzarellaRatandGitHub 42164eeb89 Reimplement boat gravity again. (#988) 2026-03-08 21:12:13 -05:00
rtm516andGitHub 91bf8d44fa Use the correctly sized icons on 720p (#883)
* Use the correctly sized icons on 720p

* Improve check
2026-03-08 21:05:54 -05:00
MrTheShyandGitHub af5d5a06d5 Revert the workaround of loading of hd textures (#999)
The previous crash fix forced HD skins at every resolution which made everything blurry at 720p and below because Iggy was downscaling 1080p assets.

The real problem was that 4J loaded the HD skin libraries (skinHD.swf, skinHDHud.swf etc) unconditionally on Win64 but the HD platform skin was only registered above 720p. At 720p or lower Iggy couldnt find platformskinHD.swf and crashed.

Now on Win64 we load both skin sets at startup, HD and non-HD, each with their own registered name so they dont conflict. loadMovie() picks 1080.swf or 720.swf based on actual screen height, and each scene SWF naturally imports the right skin chain. No crash, no blurriness.

4J already had the eLibraryFallback enum slots for this (including eLibraryFallback_Platform) but it was behind a debug-only guard and the platform skin slot was never actually loaded. Removed the guard and added the missing load.
2026-03-08 21:02:48 -05:00
Loki Rautio c89cfabb44 Remove file added by mistake in PR 2026-03-08 20:14:54 -05:00
MrTheShyandGitHub 3c52436c08 Fix crash when launching at 720p or lower resolutions (#981)
The HD skin libraries (skinHD.swf, skinHDHud.swf, etc.) are loaded
unconditionally on Win64/Durango/Orbis, and they import the Iggy
library "platformskinHD.swf" by name. However, the platform skin
path and registration name were gated behind a runtime resolution
check (m_fScreenHeight > 720.0f), so at exactly 720p the skin was
registered as "platformskin.swf" instead, and below 720p the non-HD
.swf file was loaded entirely. This caused Iggy to fail resolving
the import, which cascaded into a failed scene load and hit a
__debugbreak().

Always use the HD platform skin on these platforms since the HD
libraries that depend on it are always loaded regardless of
resolution. PS3/PSVita are unaffected as they have their own
non-HD skin loading path.
2026-03-08 18:36:56 -05:00
ModMaker101andGitHub 28614b922f Modernize project codebase (#906)
* Fixed boats falling and a TP glitch #266

* Replaced every C-style cast with C++ ones

* Replaced every C-style cast with C++ ones

* Fixed boats falling and a TP glitch #266

* Updated NULL to nullptr and fixing some type issues

* Modernized and fixed a few bugs

- Replaced most instances of `NULL` with `nullptr`.
- Replaced most `shared_ptr(new ...)` with `make_shared`.
- Removed the `nullptr` macro as it was interfering with the actual nullptr keyword in some instances.

* Fixing more conflicts

* Replace int loops with size_t and start work on overrides

* Add safety checks and fix a issue with vector going OOR
2026-03-08 18:08:36 -05:00
MrTheShyandGitHub 88798b501d Split screen, widescreen support, font rendering fixes, ui scaling fixes (#767)
* Sync keyboard text buffer from Flash before processing physical input

The native keyboard scene maintained a separate C++ buffer
(m_win64TextBuffer) for physical keyboard input, which was pushed
to the Flash text field via setLabel(). However, when the user typed
with the on-screen controller buttons, Flash updated its text field
directly through ActionScript without updating the C++ buffer.

This caused a desync: switching back to the physical keyboard would
overwrite any text entered via controller, since m_win64TextBuffer
still held the old value before the controller edits.

Fix: read the current Flash text field into m_win64TextBuffer at the
start of each tick(), before consuming new physical keyboard chars.
This ensures both input methods always operate on the same state.

* Use last active input device to decide keyboard mode instead of connection state

The keyboard UI mode (on-screen virtual keyboard vs direct text input)
was determined by Win64_IsControllerConnected(), which checks if any
XInput controller is physically plugged in. This meant that even if
the player was actively using mouse and keyboard, the virtual keyboard
would still appear as long as a controller was connected.

Replace the connection check with g_KBMInput.IsKBMActive(), which
tracks the actual last-used input device based on per-frame input
detection. Now the keyboard mode is determined by what the player is
currently using, not what hardware happens to be plugged in.

Affected scenes: CreateWorldMenu (world naming) and LoadOrJoinMenu
(world renaming).

* Fix TextInput caret behavior and add proper cursor editing for KBM direct edit

The direct text editing mode introduced for KBM users had several
issues with the TextInput control's caret (blinking cursor) and text
manipulation:

1. Caret visible when not editing:
   When navigating to the world name field with keyboard/mouse, Flash's
   Iggy focus system would show the blinking caret even though the field
   wasn't active for editing yet (Enter not pressed). This was misleading
   since typing had no effect in that state.

   Fix: access the FJ_TextInput's internal m_mcCaret MovieClip and
   force its visibility based on editing state. This is enforced every
   tick because setLabel() and Flash focus transitions continuously
   reset the caret state.

2. No cursor movement during editing:
   The direct edit implementation treated the text as a simple buffer
   with push_back/pop_back — there was no concept of cursor position.
   Backspace only deleted from the end, and arrow keys did nothing.

   Fix: track cursor position (m_iCursorPos) in C++ and use wstring
   insert/erase at that position. Arrow keys (Left/Right), Home, End,
   and Delete now work as expected. The visual caret position is synced
   to Flash via the FJ_TextInput's SetCaretIndex method.

3. setLabel() resetting caret position:
   Every call to setLabel() (when text changes) caused Flash to reset
   the caret to the end of the string, making the cursor jump visually
   even though the C++ position was correct.

   Fix: enforce caret position via setCaretIndex every tick during
   editing, so any Flash-side resets are immediately corrected.

New UIControl_TextInput API:
- setCaretVisible(bool): toggles m_mcCaret.visible in Flash
- setCaretIndex(int): calls FJ_TextInput.SetCaretIndex in Flash

* Fix keyboard/arrow navigation not working when no UI element is focused

On Windows64 with KBM, moving the mouse over empty space (outside any
button) would clear the Iggy focus entirely. After that, pressing arrow
keys did nothing because Flash had no starting element to navigate from.

Two changes here:

- Don't set focus to IGGY_FOCUS_NULL when the mouse hovers over empty
  space. The previous hover target stays focused, so switching back to
  arrows keeps working seamlessly.

- When a navigation key is pressed and nothing is focused at all (e.g.
  mouse was already on empty space when the menu opened), grab the first
  focusable element instead of silently dropping the input. The keypress
  is consumed to avoid jumping two elements at once.

This makes mixed mouse+keyboard navigation feel a lot more natural.
You can point at a button, then continue with arrows, or just start
pressing arrows right away without having to hover first.

* Overhaul mouse support and generalize direct text editing to all UI scenes

This is a large rework of the Windows64 KBM (keyboard+mouse) input layer.
It touches the mouse hover system, the mouse click dispatch, and the direct
text editing infrastructure, then applies all of it to every scene that has
text input fields or non-standard clickable elements.

MOUSE HOVER REWRITE (UIController.cpp tickInput)

The old hover code had two structural problems:

(a) Scene lookup was group-first: it iterated UI groups and checked all
layers within each group. The Tooltips layer on eUIGroup_Fullscreen (which
holds non-interactive overlays like button hints) would be found before
in-game menus on eUIGroup_Player1. The tooltip scene focusable objects
captured mouse input and prevented hover from reaching the actual menu.

Fixed by switching to layer-first lookup across all groups, and skipping
eUILayer_Tooltips entirely since those are never interactive.

(b) On tabbed menus (LaunchMoreOptionsMenu Game vs World tabs), all
controls from all tabs are registered in Flash at the same time. There was
no filtering, so controls from inactive tabs had phantom hitboxes that
overlapped the active tab controls, making certain buttons unhoverable.

Fixed by introducing parent panel tracking: each UIControl now has a
m_pParentPanel pointer, set automatically by the UI_MAP_ELEMENT macro
during mapElementsAndNames(). The hover code checks the control parent
panel against the scene GetMainPanel() and skips mismatches. This is the
same technique the Vita touch code used, but applied to mouse hover.

The coordinate conversion was also simplified. The old code had two separate
scaling paths (window dimensions for hover, display dimensions for sliders).
Now there is one conversion from window pixel coords to SWF coords using
the scene own render dimensions.

REUSING VITA TOUCH APIs FOR MOUSE (ButtonList, UIScene)

Several APIs originally gated behind __PSVITA__ are now enabled for Win64:

- UIControl_ButtonList::SetTouchFocus(x,y) and CanTouchTrigger(x,y): the
  Flash-side ActionScript methods were already registered on all platforms
  in setupControl(), only the C++ wrappers were ifdef-gated. Opening the
  ifdefs to include _WINDOWS64 lets the mouse hover code delegate to Flash
  for list item highlighting, which handles internal scrolling and item
  layout that would be impractical to replicate in C++.

- UIScene::SetFocusToElement(id): programmatic focus-by-control-ID, used as
  a fallback when Iggy focusable objects do not match the C++ hit test.

- UIScene_LaunchMoreOptionsMenu::GetMainPanel(): returns the active tab
  panel control, needed by the hover code to filter inactive tab controls.

MOUSE CLICK DISPATCH (UIScene.cpp handleMouseClick)

Left-clicking previously relied entirely on Iggy ACTION_MENU_OK dispatch,
which routes to whatever Flash considers focused. This broke for custom-
drawn elements that are not Flash buttons (crafting recipe slots), and for
scenes where Iggy focus did not match what the user visually clicked.

Added a virtual handleMouseClick(x, y) on UIScene with a default
implementation that hit-tests C++ controls. When multiple controls report
overlapping bounds (common in debug scenes where TextInputs report full
Flash-width), it picks the one whose left edge X is closest to the click.
Returns true to consume the click and suppress the normal ACTION_MENU_A
dispatch via a m_mouseClickConsumedByScene flag on UIController.

The default implementation handles buttons, text inputs, and checkboxes
(toggling state and calling handleCheckboxToggled directly).

CRAFTING MENU MOUSE CLICK (UIScene_CraftingMenu.cpp)

The crafting menu recipe slots (H slots) are rendered through Iggy custom
draw callback, not as Flash buttons. They have no focusable objects, so
mouse clicking did nothing.

The solution caches SWF-space positions during rendering: inside customDraw,
when H slot 0 and H slot 1 are drawn, the code extracts SWF coordinates
from the D3D11 transform matrix via gdraw_D3D11_CalculateCustomDraw_4J.
The X difference between slot 0 and slot 1 gives the uniform slot spacing.

handleMouseClick then uses these cached bounds to determine which recipe
slot was clicked, resets the vertical slot indices (same pattern as the
constructor), updates the highlight and vertical slots display, and re-shows
the old slot icon. This mirrors the existing controller LEFT/RIGHT
navigation in the base class handleKeyDown.

DIRECT EDIT REFACTORING (UIControl_TextInput)

The direct text editing feature (type directly into text fields instead of
opening the virtual keyboard) was originally implemented inline in
CreateWorldMenu with all the state, character consumption, cursor tracking,
caret visibility, and cooldown logic hardcoded in one scene.

Moved everything into UIControl_TextInput:
- beginDirectEdit(charLimit): captures current label, inits cursor at end
- tickDirectEdit(): consumes chars, handles Backspace/Enter/Escape, arrow
  keys (Left/Right/Home/End/Delete), enforces caret visibility every tick
  (because setLabel and Flash focus transitions continuously reset it),
  returns Confirmed/Cancelled/Continue
- cancelDirectEdit() / confirmDirectEdit(): programmatic control
- isDirectEditing() / getDirectEditCooldown() / getEditBuffer(): state query

For SWFs that lack the m_mcCaret MovieClip child (like AnvilMenu), the
existence check validates by reading a property from the resolved path,
since IggyValuePathMakeNameRef always succeeds even for undefined refs.
When no caret exists, the control inserts a _ character at the cursor
position as a visual fallback.

The caret check result is cached in m_bHasCaret/m_bCaretChecked to avoid
repeated Iggy calls that could corrupt internal state.

SCENES UPDATED WITH DIRECT EDIT + VIRTUAL KEYBOARD

Every scene with text input now supports both input modes: direct editing
when KBM is active, virtual keyboard (via NavigateToScene eUIScene_Keyboard)
when using a controller. The mode is chosen at press time based on
g_KBMInput.IsKBMActive().

- CreateWorldMenu: refactored to use the new UIControl_TextInput API,
  removing ~80 lines of inline editing code.

- AnvilMenu: item renaming now supports direct edit. The keyboard callback
  uses Win64_GetKeyboardText instead of InputManager.GetText (which reads
  from a different buffer on Win64). The virtual keyboard is opened with
  eUILayer_Fullscreen + eUIGroup_Fullscreen so it does not hide the anvil
  container menu underneath. Added null guards on getMovie() in setCostLabel
  and showCross since the AnvilMenu SWF may not fully load on Win64.

- SignEntryMenu: all 4 sign lines support direct edit. Clicking a different
  line while editing confirms the current one. Each line cooldown timer
  is checked independently to prevent Enter from re-opening the edit.

- LaunchMoreOptionsMenu: seed field direct edit with proper input blocking.

- DebugCreateSchematic: all 7 text inputs (name + start/end XYZ coords).
  handleMouseClick is overridden to always consume clicks during edit to
  prevent Iggy re-entry on empty space.

- DebugSetCamera: all 5 inputs (camera XYZ + Y rotation + elevation).
  Clicking a different field while editing confirms the current value and
  opens the new one. Float display formatting changed from %f to %.2f.

All keyboard completion callbacks on Win64 now use Win64_GetKeyboardText
(two params: buffer + size) instead of InputManager.GetText, which reads
from the correct g_Win64KeyboardResult global when using the in-game
keyboard scene.

SCROLL WHEEL

Mouse wheel events (ACTION_MENU_OTHER_STICK_UP/DOWN) are now centrally
remapped to ACTION_MENU_UP/DOWN in UIController::handleKeyPress when KBM
is active. Previously each scene would need to handle OTHER_STICK actions
separately, and most did not, so scroll wheel only worked in a few places.

* Add mouse click support to CraftingMenu (tab switching, slot selection, craft)

The crafting screen's horizontal recipe slots and category tabs are custom-drawn
via Iggy callbacks rather than regular Flash buttons, so the standard mouse hover
system can't interact with them. This adds handleMouseClick to derive clickable
regions from the H slot positions cached during customDraw.

Tab clicking: tab hitboxes are computed relative to the H slot row since the
Vita TouchPanel overlays (full-screen invisible rectangles) aren't suitable
for direct hit-testing on Win64. The Y bounds were tuned empirically to match
the SWF tab icon positions. Clicking a tab runs the same switch logic as
LB/RB: hide old highlight, update group index, reset slot indices,
recalculate recipes, and refresh the display.

H slot clicking: clicking a different recipe slot selects it (updating V slots,
highlight, and re-showing the previous slot). Clicking the already-selected
slot crafts the item by dispatching ACTION_MENU_A through handleKeyDown,
reusing the existing crafting path. Empty slots (iCount == 0) are ignored.

All mouse clicks on the scene are consumed (return true) to prevent misses
from falling through as ACTION_MENU_A and accidentally triggering a craft.
This only suppresses mouse-originated A presses via m_mouseClickConsumedByScene;
keyboard and controller A remain fully functional.

Also enables GetMainPanel for Win64 (was Vita-only) so the mouse hover system
can filter controls by active panel, same as other tabbed menus.

* Fix mouse hover selecting wrong buttons from the third onward

The hover code was doing a redundant second hit-test against Iggy
focusable object bounds after the C++ control bounds had already
identified the correct control. Iggy focusable bounds are wider than
the actual visible buttons and overlap vertically, so the "pick
largest x0" heuristic would match focusables belonging to earlier
buttons when hovering the right side of buttons 3+.

Replaced the IggyPlayerGetFocusableObjects path with a direct
SetFocusToElement call using the already-correct hitControlId from
the C++ hit-test, same approach the click path uses in
handleMouseClick. Also switched the overlap tiebreaker from "largest
x0" to smallest area, consistent with how clicks resolve overlapping
controls. TextInput is excluded from hover focus to avoid showing
the caret on mere mouse-over (its Iggy focus is set on click).

* Use smallest-area tiebreaker for mouse click hit-testing too

Same overlap fix applied to handleMouseClick: when multiple controls
contain the click point, prefer the one with the smallest bounding
area instead of the one with the largest left-edge X. This is more
robust for any layout (vertical menus, grids, overlapping panels)
and matches the hover path logic.

Those changes were initially made in order to fix the teleport ui for the mouse but broke every other well working ui.

* Fix mouse cursor staying trapped in window on alt-tab

When the inventory or other UI with a hidden cursor was open,
alt-tabbing out would leave the cursor locked to the game window.
SetWindowFocused(false) from WM_KILLFOCUS correctly released the
clip and showed the cursor, but Tick() was unconditionally calling
SetCursorPos every frame to re-center it, overriding the release.

Added m_windowFocused to the Tick() condition so cursor manipulation
only happens while the window actually has focus.

* Map mouse right click to ACTION_MENU_X for inventory half-stack

Right clicking an item stack in Java Edition picks up half of it.
Console Edition already handles this via ACTION_MENU_X (the X button
on controller), which sets buttonNum=1 in handleKeyDown. This maps
mouse right click to that same action so KBM players get the same
behavior across all container menus (inventory, chests, furnaces,
hoppers, etc).

* Fix mouse hover hitting removed controls (ghost hitboxes)

When removeControl() removes a Flash element (e.g. the Reinstall
button in Help & Options, or the Debug button when disabled), the
C++ control object stays in the m_controls vector. On Vita this was
handled by calling setHidden(true) and checking getHidden() in the
touch hit-test, but on Windows64 none of that was happening.

The result: removed buttons kept phantom bounds that the hover code
would match against, stealing focus from the buttons that shifted
into their visual position. In the Help & Options menu with debug
enabled, the removed Reinstall button (Button6) had ghost bounds
overlapping where the Debug button (Button7) moved to after the
removal, making Debug un-hoverable and snapping focus to Button1.

The fix has three parts:

- removeControl() now calls setHidden(true) on all platforms, not
  just Vita. The m_bHidden member was already declared on all
  platforms, only the accessors were ifdef'd behind __PSVITA__.

- Removed the __PSVITA__ ifdef from setHidden/getHidden in
  UIControl.h so they're available everywhere.

- Added getHidden() checks in both the hover and click hit-test
  loops, matching what the Vita touch code already does. The check
  is a simple bool read (no Flash/Iggy call), placed before the
  getVisible() query which hits Flash and can return stale values
  for removed elements.

* Add right-click to open save options in world selection menu

On controller, RB (ACTION_MENU_RIGHT_SCROLL) opens the save options
dialog (rename/delete) when a save is selected. Mouse right-click
maps to ACTION_MENU_X, which had no Windows64 handler in this scene.

Added save options handling under ACTION_MENU_X for _WINDOWS64 so
right-clicking a save opens the same dialog. Also handles the mashup
world hide action for right-click consistency. Console-only options
(copy save, save transfer) are excluded since they don't apply here.

* Fix splitscreen mouse, keyboard cursor, and local player join

Mouse hover and click in split-screen was broken: the coordinate
conversion from window pixels to Flash/SWF space did not account for
the viewport tile-origin offset or the smaller display dimensions of
each splitscreen quadrant. Now the mouse position is mapped through
three steps: window pixels to UIController screen space, subtract the
viewport origin (which varies per quadrant/split type), then scale
from display size to SWF authoring size. This fixes hover highlighting
and click targeting in all splitscreen layouts.

Mouse input was also bleeding into other splitscreen players' UI groups
because the scene lookup iterated all groups. Now it only checks the
fullscreen group and the primary (KBM) player's group, so controller
players' menus are never affected by mouse movement.

Mouse grab/release (cursor lock for gameplay) was triggering for every
local player's tick, causing fights between splitscreen players over
the cursor state. Now only the primary pad player controls grab state.

The in-game keyboard scene in PC mode had no cursor movement: typing
always appended at the end and backspace always deleted from the end.
Added a cursor position tracker (m_iCursorPos) so that characters are
inserted at the cursor, backspace deletes behind it, and arrow keys,
Home, End, and Delete all work as expected. The Flash caret is synced
to the cursor position each tick. Also stopped syncing the text buffer
back from Flash in PC mode, which was resetting the cursor every tick.
Arrow keys in PC mode no longer get forwarded to Flash (which would
move the on-screen keyboard selector instead of the text cursor).

AddLocalPlayerByUserIndex was calling NotifyPlayerJoined before the
IQNet slot was actually registered, passing a pointer obtained via
GetLocalPlayerByUserIndex which checks customData (not set yet at that
point). Now AddLocalPlayerByUserIndex is called first, and if it
succeeds, the notification uses the static m_player array directly.
The stub AddLocalPlayerByUserIndex now properly initialises the slot
with gamertag and remote/host flags instead of being a no-op.

IsSignedIn was hardcoded to return true only for pad 0, preventing
splitscreen players from joining. Now it checks IsPadConnected so any
connected controller can sign in.

GetXUID returned INVALID_XUID for all pads except 0, which broke
splitscreen player identity. Now each pad gets a unique XUID derived
from the base value plus the pad index.

Pinned internal resolution to 1920x1080 and removed GetSystemMetrics
auto-detection which was picking up the native monitor resolution and
breaking the 16:9 assumption in the viewport math and Flash layout.
DPI awareness is kept for consistent pixel coordinates.

* Fix Escape key not opening pause menu during tutorial hints

The KBM pause check had a IsTutorialVisible guard that blocked
Escape entirely while any tutorial popup was on screen. The
controller path never had this restriction. Removed the check
so Escape behaves the same as Start on controller.

* Fix crash in WriteHeader when save buffer is too small for header table

When a player enters a new region, RegionFile's constructor calls
createFile which adds a FileEntry with length 0 to the file table.
This increases the header table size (appended at the end of the save
buffer) by sizeof(FileEntrySaveData) per entry, but since no actual
data is written to the file, MoveDataBeyond is never called and the
committed virtual memory pages are never grown to match.

On the next autosave tick, saveLevelData writes level.dat first
(before chunkSource->save which would have grown the buffer). If
level.dat doesn't need to grow, finalizeWrite calls WriteHeader which
tries to memcpy the now-larger header table past the end of committed
memory, causing an access violation.

This is especially likely in splitscreen where two players exploring
at the same time can create multiple new RegionFile entries within a
single tick, quickly exhausting the page-alignment slack in the buffer
(yes i am working at splitscreen in the meanwhile :) )

The fix was deduced by tracing the crash callstack through the save
system: FileHeader, ConsoleSaveFileOriginal, the stream chain, and
the RegionFile/RegionFileCache layer. The root cause turned out to be
a gap between createFile (which grows the header table) and
MoveDataBeyond (the only place that grows the buffer), with
finalizeWrite sitting right in between unprotected.

The buffer growth check added here mirrors the exact same VirtualAlloc
pattern already used in MoveDataBeyond (line 484-497) and in the
constructor's decompression path (line 176-190), so it integrates
naturally with the existing code. Same types, same page rounding,
same error handling. The fast path (no new entries, buffer already big
enough) is a single DWORD comparison that doesn't get taken, so there
is zero overhead in the common case.

This is the right place for the fix because finalizeWrite is the sole
caller of WriteHeader, meaning every code path that writes the header
(closeHandle, PrepareForWrite, deleteFile, Flush) is now protected by
a single check point.

* Fix TextInput bugs and refactor direct edit handling into UIScene base class

The fake cursor character (_) used for SWFs without m_mcCaret was leaking
into saved sign and anvil text. This happened because setLabel() with
instant=false only updates the C++-side cache, deferring the Flash write
to the next control tick. Any getLabel() call before that tick reads the
old Flash value still containing the underscore. Fixed by passing
instant=true in confirmDirectEdit, cancelDirectEdit, and the Enter key
path inside tickDirectEdit, so the cleaned text hits Flash immediately.

Mouse hover over TextInput controls (world name, anvil name, seed field)
was not showing the yellow highlight border. The hover code used
IggyPlayerSetFocusRS which sets Iggy's internal dispatch focus but does
not trigger Flash's ChangeState callback, so no visual feedback appeared.
Buttons worked fine because Iggy draws its own focus ring on them, but
TextInput relies entirely on ChangeState(0) for the yellow border.
Switched to SetFocusToElement which goes through the Flash-side SetFocus
path, then immediately call setCaretVisible(false) to suppress the
blinking caret that comes with focus. No visual flicker since rendering
happens after both tickInput and scene tick complete.

While direct editing, mouse hover was able to move focus away to other
TextInputs on the same scene (most noticeably on the sign editor, where
hovering a different line would steal focus from the line being typed).
Added an isDirectEditBlocking() check in the hover path to skip focus
changes when any input on the scene is actively being edited.

The Done button in SignEntryMenu was unresponsive to mouse clicks during
direct editing. The root cause is execution order: handleMouseClick runs
before handleInput in the frame. The base handleMouseClick found the Done
button and called handlePress, but handlePress bailed out because of the
isDirectEditing guard. The click was marked consumed, so handleInput
never saw it. Fixed by overriding handleMouseClick in SignEntryMenu to
detect the Done button hit while editing and confirm + close directly.

Added click-outside-to-deselect for anvil and world name text inputs.
Both scenes previously required Enter to confirm the edit, which felt
wrong. Now clicking anywhere outside the text field bounds confirms the
current text, matching standard UI behavior.

The anvil menu now updates the item name in real time while typing, like
Java edition. Previously the name was only applied on Enter, so the
repair cost display was stale until confirmation.

The biggest change is structural: every scene that used direct editing
(AnvilMenu, CreateWorldMenu, SignEntryMenu, LaunchMoreOptionsMenu,
DebugCreateSchematic, DebugSetCamera) had its own copy of the same
boilerplate -- tickDirectEdit loops in tick(), click-outside hit testing
in handleMouseClick(), cooldown guard checks in handleInput/handlePress,
and result dispatch with switch/if chains. This was around 200 lines of
near-identical code scattered across 6 files, each with its own slight
variations and its own bugs waiting to happen.

Pulled all of it into UIScene with two virtual methods: getDirectEditInputs()
where scenes register their text inputs, and onDirectEditFinished() where
they handle confirmed/cancelled results. The base class tick() drives
tickDirectEdit on all registered inputs, handleMouseClick() does the
click-outside-to-deselect hit test generically using panel offsets, and
isDirectEditBlocking() replaces all the inline cooldown checks. Scenes
now just override those two methods and get everything for free.

Also removed the m_activeDirectEditControl enum tracking from the debug
scenes (DebugCreateSchematic, DebugSetCamera) since the base class
handles lifecycle tracking through the controls themselves.

* Remap scroll wheel to LEFT/RIGHT for horizontal controls

The scroll wheel was always remapped to UP/DOWN, which is fine for
vertical lists but useless on horizontal controls like sliders and
the texture pack selector.

Track whether the mouse is hovering a horizontal control during the
hover hit-test (new bool m_bMouseHoverHorizontalList, set for
eTexturePackList and eSlider). When the flag is set, handleKeyPress
emits LEFT/RIGHT instead of UP/DOWN for wheel events.

TexturePackList is also now part of the mouse hover system with
proper hit-testing, relative-coord SetTouchFocus and GetRealHeight
for accurate bounds.

* Guard setCaretVisible and setCaretIndex against null movie

tickDirectEdit calls into Iggy every tick without checking if the
movie is still valid, which crashes inside iggy_w64.dll when the
Flash movie gets unloaded or isn't ready yet.

* Fix creative inventory scroll for both mouse wheel and controller

The mouse scroll wheel was not working in the creative inventory at
all. UIController remaps wheel input from OTHER_STICK to UP/DOWN for
KBM users, but the base container menu handler consumed UP/DOWN for
grid navigation before it could reach the creative menu's page
scrolling logic in handleAdditionalKeyPress. Fixed by detecting
scroll wheel input on UP/DOWN in the base handler and forwarding it
as OTHER_STICK to handleAdditionalKeyPress instead.

Also fixed the controller right stick scrolling way too fast: it was
jumping TabSpec::rows (5) rows per tick at 100ms repeat rate, which
blew through the entire item list almost instantly. Reduced to 1 row
per tick so scrolling feels controlled on both input methods.

* Fix split-screen world rendering aspect ratio

gluPerspective was hardcoded to use g_iAspectRatio (always 16:9)
instead of the aspect parameter from getFovAndAspect, which adjusts
for split-screen viewports. The 3D world was horizontally stretched
in top/bottom split because the projection used 16:9 while the
viewport was 32:9.

* Split-screen UI system with full ultrawide and multi-aspect-ratio support

Screen resolution is now auto-detected from the monitor at startup
instead of being hardcoded to 1920x1080. This fixes rendering on
ultrawide (21:9), super-ultrawide (32:9), 16:10, and any other
aspect ratio -- both in singleplayer and split-screen multiplayer.

The 3D world renders at native resolution so the full monitor is used.
Flash UI is 16:9-fitted and centered inside each viewport, pillarboxed
on wide displays and letterboxed on tall ones. Logical game dimensions
(used for ortho projection and HUD layout) are computed proportionally
from the real screen aspect ratio, fixing the stretched world projection
and HUD that the old hardcoded 1280x720 caused on non-16:9 monitors.

GameRenderer::ComputeViewportForPlayer uses the actual backbuffer size
instead of the logical game size, which was causing split-screen
viewports to be sized incorrectly.

UIScene::render fits menus to 16:9 within each split viewport using
GetViewportRect + Fit16x9, keeping inventory/crafting/options screens
at their designed aspect ratio instead of stretching.

Panorama and MenuBackground render at full viewport size with proper
tile scaling so the background fills the entire area without gaps in
vertical split and quadrant layouts.

HUD tile rendering uses ComputeTileScale to uniformly scale the SWF
and show the bottom portion (hotbar, hearts, hunger) in horizontal
and quadrant splits. repositionHud passes visible SWF-space dimensions
to ActionScript for proper element centering within each viewport.

Chat and Tooltips overlays use ComputeTileScale and
ComputeSplitContentOffset to anchor correctly to the bottom of each
player's viewport tile.

Container menus apply Fit16x9 to pointer coordinate mapping so the
cursor tracks correctly in split-screen. getMouseToSWFScale moved out
of the header into the .cpp. Mouse input in onMouseTick is gated to
pad 0 since raw mouse deltas should only drive player 1.

All shared viewport math lives in UISplitScreenHelpers.h:
- GetViewportRect: origin and dimensions for any viewport type
- Fit16x9: aspect-correct fitting with centering offsets
- ComputeTileScale: uniform scale and Y-offset for tile rendering
- ComputeSplitContentOffset: content centering for overlay components

* Fix XUID assignment for split-screen local players

Main's XUID refactor returned INVALID_XUID for pad != 0, which breaks
split-screen because each local player needs a distinct identity for
the save system and per-player inventory data.

Now pad 1-3 get unique XUIDs derived from the legacy embedded base
(base + iPad), same as the original console behavior. Only pad 0
uses the persistent uid.dat-backed XUID for networking.

* Use persistent XUID for all pads in GetXUID

All pads now get unique XUIDs derived from the persistent uid.dat value
(base + iPad offset). This gives each split-screen player a globally
unique identity that works for both local play and online multiplayer.

The host legacy XUID override for save compatibility still happens in
Minecraft.cpp after GetXUID is called, so old worlds are unaffected.

* Split-screen networking, window resize, bitmap font fix, and multiplayer stability

Adds the networking layer for non-host split-screen multiplayer, implements
live window resize with swap chain recreation, fixes bitmap font scaling at
small window sizes, and fixes several crash-causing bugs in the multiplayer
stack (compression buffer overflow, TCP stream desync, chunk visibility race,
CompressedTileStorage torn reads, reconnect stability).

== Non-host split-screen multiplayer ==

Each split-screen pad on a non-host client opens its own TCP connection to
the host. From the host's perspective each connection looks like a normal
remote player (gets its own smallId, Socket, PlayerConnection).

WinsockNetLayer: JoinSplitScreen(), CloseSplitScreenConnection(),
SplitScreenRecvThreadProc, per-pad socket/thread/smallId tracking
(s_splitScreenSocket[], s_splitScreenSmallId[], s_splitScreenRecvThread[]).
GetLocalSocket() returns the correct TCP socket for a given local sender's
smallId. GetSplitScreenSmallId() returns the host-assigned smallId for a pad.

GameNetworkManager::CreateSocket: non-host path (localPlayer && !IsHost() &&
IsInGameplay()) calls JoinSplitScreen, sets the IQNet slot's smallId and
resolvedXuid, creates a non-hostLocal Socket + ClientConnection, sends
PreLoginPacket, registers via addPendingLocalConnection.

PlatformNetworkManagerStub::RemoveLocalPlayerByUserIndex: implemented the
formerly-empty stub. Calls NotifyPlayerLeaving, CloseSplitScreenConnection,
and clears the IQNet slot fields so the pad can rejoin cleanly.

SmallId pool: s_nextSmallId starts at XUSER_MAX_COUNT (4), reserving
m_player[0-3] for local pads so remote players never collide.

IQNetPlayer::SendData: non-host local senders now route through
GetLocalSocket(m_smallId) instead of always using SendToSmallId.
IQNet::GetLocalPlayerByUserIndex: rewritten. Pad 0 on non-host uses
GetLocalSmallId() for direct lookup; pads 1-3 check m_player[padIdx].
C_4JProfile::IsSignedIn: pad 0 always returns true (was checking controller
connection, which is unreliable on Win64).

GetGamertag/GetDisplayName: for pads 1-3 with active local players, returns
the pad-specific gamertag from IQNet::m_player instead of always returning
the primary username.

ClientConnection: isPrimaryConnection() (true on host or for the primary pad
on non-host) guards relative-delta and world-modifying handlers to prevent
double-processing of shared state:
- Guarded: handleMoveEntity, handleMoveEntitySmall, handleChunkTilesUpdate,
  handleBlockRegionUpdate, handleTileUpdate, handleTakeItemEntity,
  handleSignUpdate, handleTileEntityData, handleTileEvent,
  handleTileDestruction, handleComplexItemData, handleLevelEvent,
  handleSoundEvent, handleParticleEvent, handleAddGlobalEntity.
- handleSetEntityMotion: secondary connections only accept motion targeting
  their own local player (knockback).
- handleExplosion: world modification (finalizeExplosion) guarded,
  per-player knockback unguarded. Added null check on localplayers[].
- Entity spawn/remove/teleport/data handlers left unguarded (putEntity is
  idempotent, absolute value setters).

handleLogin: added else clause to set level when the dimension already exists
(was leaving level NULL on reconnect).
handleChunkVisibilityArea/handleChunkVisibility: added null check on level.
handleContainerOpen: added null check on localplayers[m_userIndex].

== Reconnect stability ==

PendingConnection: duplicate XUID no longer rejects with eDisconnect_Banned.
Instead it force-disconnects the stale old connection via
stalePlayer->connection->disconnect(), queues the old smallId for recycling
via queueSmallIdForRecycle(), then calls handleAcceptedLogin for the new
connection.

MinecraftServer: swapped tick order so players->tick() (disconnect queue)
runs before connection->tick() (new logins). The old player is removed
from PlayerList before the new LoginPacket's XUID check runs.

PlayerList: PushFreeSmallId and ClearSocketForSmallId moved here from
DoWork, called only after PlayerConnection::disconnect() completes and
the read/write threads are dead. New queueSmallIdForRecycle() method lets
PendingConnection push smallIds into m_smallIdsToClose, which PlayerList::tick()
processes through closePlayerConnectionBySmallId() for deferred cleanup.
Prevents a race where the old write thread could resolve getPlayer() to a
recycled smallId's new connection and send stale packets on it.

SocketInputStreamLocal::close() and SocketOutputStreamLocal::close() now
actually clear their queues (std::swap with empty queue instead of calling
.empty() which is a read-only no-op).

ServerConnection::stop(): pending and players vectors are snapshot-copied
before iterating (prevents iterator invalidation). Remote players receive
a DisconnectPacket via disconnect(eDisconnect_Quitting) instead of raw
close(). tick(): added else clause so flush() only runs on live connections.

WinsockNetLayer::Shutdown(): accept thread stopped first (prevents new recv
threads from spawning), then all recv threads are collected and waited on,
then connections are closed and split-screen sockets cleaned up. Clears
disconnect and free-pool vectors before deleting critical sections.

WinsockNetLayer::JoinGame(): waits for old s_clientRecvThread to fully
exit before creating a new TCP connection. Prevents the old recv thread
from reading bytes off the new socket and desynchronizing the stream.

== Compression buffer overflow ==

CompressLZXRLE and CompressRLE wrote RLE intermediate output into a fixed
100KB buffer with no bounds checking. Full chunk columns are ~160KB and
the RLE step can expand 0xFF bytes to 2 bytes each, easily overflowing
into rleDecompressBuf and heap metadata. This caused delayed crashes in
unrelated code (Packet::readPacket, LevelRenderer::updateDirtyChunks) after
the first autosave, since that's when full chunks get compressed.

Fix: dynamic allocation when worst-case RLE output (SrcSize * 2) exceeds
the static buffer. Static buffer still used for small inputs (zero overhead).
CompressRLE: moved LeaveCriticalSection after dynamic buffer cleanup.

DecompressLZXRLE: now checks zlib return value (was completely ignored).
On failure, bails out immediately with *pDestSize = 0. Added RLE input
bounds checking (pucIn >= pucEnd before reading count/data bytes) and
output bounds checking (pucOut + count > pucOutEnd). Same bounds checks
applied to DecompressRLE.

== Stream desync (Connection write thread) ==

The write thread had two output paths to the same TCP socket: bufferedDos
(5KB buffered stream) and direct sos->writeWithFlags(). Chunk data sent
via queueSend() used the direct path with shouldDelay=true, while other
packets used bufferedDos. If bufferedDos had unflushed bytes, the direct
write arrived at the client first, reordering the TCP stream and producing
bad packet ID crashes.

Fix: flush bufferedDos immediately before every direct sos->writeWithFlags().

== Chunk visibility race (empty first chunk after 30s) ==

BlockRegionUpdatePacket (direct socket write via queueSend) could arrive
at the client before ChunkVisibilityAreaPacket (buffered). The client
called getChunk() on a chunk that didn't exist yet in the cache, got
EmptyLevelChunk (whose setBlocksAndData is a no-op), and silently lost
the block data. On superflat this left one invisible chunk; on normal
worlds it crashed the renderer.

Fix: handleBlockRegionUpdate calls dimensionLevel->setChunkVisible() for
full-chunk BRUPs before writing data, making it independent of packet
ordering. Added post-write verification logging.

CompressedTileStorage race: get() reads indicesAndData twice without a
lock. compress() can swap the pointer between reads, producing indices
from the old buffer paired with data from the new buffer. Fix: snapshot
indicesAndData into a local variable before deriving both pointers. Same
snapshot pattern applied to getData() (non-Vita path), isRenderChunkEmpty(),
getHighestNonEmptyY(), getAllocatedSize(), and write(). All methods now
also guard against NULL snapshots.

== Window resize ==

ResizeD3D() destroys the old swap chain, creates a new one at the target
size, then patches InternalRenderManager members directly via memory
offsets (0x20=swap chain, 0x28=RTV, 0x50=SRV, 0x98=DSV, 0x5138/0x513C=
backbuffer width/height). Offset verification cross-checks known pointers
(device at 0x10, swap chain at 0x20) before patching. Old RTV/SRV are
intentionally leaked (orphaned with the old swap chain) to avoid fighting
unknown ref holders in the precompiled RenderManager.

The flow: Suspend RenderManager, ClearState+Flush, release views,
gdraw_D3D11_PreReset, destroy old swap chain, create new swap chain via
IDXGIFactory, patch offsets, recreate RTV/SRV/DSV, rebind render targets,
update UIController (updateRenderTargets + updateScreenSize),
gdraw_D3D11_PostReset + SetRendertargetSize, IggyFlushInstalledFonts,
Resume, PostProcesser::Init.

WM_SIZE handling defers resize during window drag (WM_ENTERSIZEMOVE/
WM_EXITSIZEMOVE). Immediate resizes (maximize, programmatic) call
ResizeD3D directly. Removed the old UpdateAspectRatio() function.

CleanupDevice() was leaking g_pDepthStencilView and g_pDepthStencilBuffer.

InitDevice: swap chain BufferUsage now includes DXGI_USAGE_SHADER_INPUT
(needed for the SRV created from the backbuffer for CaptureThumbnail).

New globals: g_rScreenWidth/g_rScreenHeight (real window dimensions,
updated on resize) vs g_iScreenWidth/g_iScreenHeight (fixed logical
resolution, stays 1920x1080).

ComputeViewportForPlayer and getFovAndAspect now use g_rScreenWidth/
g_rScreenHeight instead of the fixed startup values, so 3D perspective
and split-screen viewports adapt to window size.

Main loop: rendering skipped when window is minimized (IsIconic check)
to avoid 100% GPU usage on a hidden swap chain.

Windows64_UIController: new updateRenderTargets(rtv, dsv) method updates
cached D3D pointers used by gdraw_D3D11_SetTileOrigin every frame.
UIController.h: new inline updateScreenSize(w, h) sets m_fScreenWidth/
m_fScreenHeight so all downstream UI code picks up the new size.

== Bitmap font scaling ==

At small window sizes, dynamic text (scrollable list items, HowToPlay
pages) showed overlapping characters. Static SWF text was unaffected
because it uses embedded vector glyphs.

Root cause in UIBitmapFont.cpp GetGlyphBitmap: when display scale is
smaller than the bitmap's native scale (pixel_scale < truePixelScale,
glyphScale stays at 1), Iggy displayed the glyph at native 1:1 pixel
size but advanced the cursor by the smaller display-scale amount.

At intermediate window sizes (e.g. 1678x756, scale factor ~0.7), a
second bug appeared: some SWF font sizes produced pixel_scale just above
truePixelScale (13 for Mojangles_11) while others fell just below,
splitting glyphs across the small-display and normal cache branches.
The normal branch cached all glyphs in a single [truePixelScale, 99]
range, so the first glyph cached set pixel_scale_correct for every
subsequent request regardless of font size. Different font sizes then
got scaled by wrong ratios (e.g. 18.9/13.3 = 1.42x with point sampling),
producing visibly inconsistent letter sizes. This only happened at
specific window sizes where the display scale put some fonts above and
others below the truePixelScale boundary. Full 1080p and very small
windows were unaffected because all fonts landed in the same branch.

Fix: on _WINDOWS64, always use pixel_scale_correct = truePixelScale so
every cache entry is consistent regardless of which font size creates it
first. Two cache ranges: downscale (pixel_scale < truePixelScale) uses
bilinear for smooth reduction, upscale uses point_sample for crisp
pixel-art rendering. At most two cache entries per glyph. The console
code path (fixed resolution, integer-multiple scaling) is preserved
behind #else.

UIScene.cpp loadMovie: always load 1080.swf on _WINDOWS64 regardless of
window size. The old height-based selection could pick 480 or 720 variants
which either crashed or loaded the wrong skin library (skinHD.swf vs
skin.swf). Display size is now set via Fit16x9 BEFORE the init tick so
Iggy's ActionScript text field creation sees the same scale that render()
will use. IggyFlushInstalledFonts() called after init tick to clear stale
glyph cache entries from previous scenes.

Font.cpp addCharacterQuad/renderCharacter: yOff was computed with
m_charWidth instead of m_charHeight, producing wrong texture coordinates
for non-square glyph cells. This is the world-rendering font (chat, signs,
name tags), not the Iggy UI font.

== XUID generation ==

Split-screen pad XUIDs derived by hashing baseXuid + iPad through Mix64
(DeriveXuidForPad in Windows64_Xuid.h) instead of simple addition. Pad 0
returns the base XUID unchanged for save compatibility. Includes validity
fallbacks if the hash produces an invalid XUID. (Suggested by rtm516)

== Misc ==

Packet::readPacket: thread-local ring buffer tracks last 8 good packet IDs.
On bad packet ID, dumps the history plus next 32 bytes of stream for
diagnosing TCP desynchronization.

PendingConnection/PlayerList: debug logging for the reconnect flow
(duplicate XUID handling, force-disconnect, handleAcceptedLogin,
placeNewPlayer with smallId/entityId/dimension).

ClientConnection::handleBlockRegionUpdate: warning log when a full chunk
arrives with ys==0 (empty full chunk, data loss indicator).

== Known issues / future work ==

SendOnSocket global lock (WinsockNetLayer.cpp): s_sendLock is a single
CriticalSection serializing ALL TCP sends across ALL connections. If one
client's send() blocks (TCP window full, slow network), every other write
thread stalls — no data flows to any player until the slow send completes.
Each PlayerConnection has its own write thread, so with 8+ players one slow
client can cause latency spikes or timeout disconnects for healthy players.
Fix: replace s_sendLock with per-socket locks indexed by smallId. The lock
only needs to prevent header+payload interleaving on the SAME socket; sends
to different sockets are independent. Deferred to a separate PR to keep
this one focused.

Textures::releaseTexture: early return for id <= 0, checks
TextureGetTexture(id) != NULL before calling glDeleteTextures. Prevents
crashes on stale texture IDs after RenderManager reset.

UIController TextureSubstitutionDestroyCallback: null guard on
Minecraft::GetInstance() and mc->textures before calling releaseTexture.
Prevents crash during shutdown.

StringTable: removed __debugbreak() on language load failure in debug builds.
2026-03-08 15:49:50 -05:00
Us3ful"-DevandGitHub 9d2eb5c9b0 Flame not working with oneshot arrow (#856)
set on fire before the entity takes damage (while still checking for invulnerability)
2026-03-09 03:18:31 +08:00
8ad70cd2be Fix focus sound playing repeatedly on mouse hover (#890)
Only play eSFX_Focus when the focus control or child actually changes. Previously the sound fired on every focus event even when hovering over the same element, causing rapid sound spam over Texture Pack icons in the Create World menu.

Fixes a bug reported on Discord.

Co-authored-by: MCbabel <MCbabel@users.noreply.github.com>
2026-03-09 03:16:06 +08:00
Ayush ThorenandGitHub a14a4542c9 Fix stale held item appearing when switching worlds (#910)
Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-09 03:12:49 +08:00
Ayush ThorenandGitHub 2f443fe333 Fix F3 debug crash when throwing ender pearl long distance (#934)
Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-09 03:10:47 +08:00
Adem KurtandGitHub 4cec4f4500 Allow closing some menus with inventory/crafting keys (#868) 2026-03-09 03:06:01 +08:00
Ayush ThorenandGitHub 45704388b6 Fix second-person nametag pitch (#963)
Signed-off-by: Ayush Thoren <ayushthoren@gmail.com>
2026-03-09 02:39:37 +08:00
LokiandGitHub dc91a1dad0 Add Discord Invite to issue flow 2026-03-08 03:50:16 -05:00
Matthew ToroandGitHub 3a5f1b6179 Add "Add Server" functionally to "Join Game" Menu + relocate servers.txt to servers.db. (#911)
* Add "Add Server" functionally to "Join Game" Menu + relocate servers.txt to servers.db

* enchancement: add edit and delete server functionality, solves FriendSessionInfo corruption issues
2026-03-08 03:10:15 -05:00
Alezito2008andGitHub d461012efb fix: prevent TNT minecarts from exploding if TNT host option is disabled (#921) 2026-03-08 03:02:23 -05:00
E x o t i candGitHub 110e86ca2a Fix missing break statement for minecarts (#930) 2026-03-08 03:00:25 -05:00
eh-KandGitHub a865cea026 Adjust gamma calculation based on slider value (#893) 2026-03-07 22:31:20 -06:00
cfcec48ae1 Fix horse rendering: culling when looking up + fire debug texture (#899)
- Skip frustum culling for the entity the player is currently riding, preventing the horse from disappearing when looking up (fixes a bug reported on Discord)

- Fix HorseRenderer::bindTexture() to delegate to base class for single textures (fire atlas, enchant glint), only using bindTextureLayers() for multi-layer horse textures

Co-authored-by: MCbabel <MCbabel@users.noreply.github.com>
2026-03-07 22:30:44 -06:00
Loki Rautio 087b7e7abf Revert "Project modernization (#630)"
This code was not tested and breaks in Release builds, reverting to restore
functionality of the nightly. All in-game menus do not work and generating
a world crashes.

This reverts commit a9be52c41a.
2026-03-07 21:12:22 -06:00
ModMaker101andGitHub a9be52c41a Project modernization (#630)
* Fixed boats falling and a TP glitch #266

* Replaced every C-style cast with C++ ones

* Replaced every C-style cast with C++ ones

* Fixed boats falling and a TP glitch #266

* Updated NULL to nullptr and fixing some type issues

* Modernized and fixed a few bugs

- Replaced most instances of `NULL` with `nullptr`.
- Replaced most `shared_ptr(new ...)` with `make_shared`.
- Removed the `nullptr` macro as it was interfering with the actual nullptr keyword in some instances.

* Fixing more conflicts

* Replace int loops with size_t and start work on overrides
2026-03-08 09:56:03 +07:00
Vincent ZhangandGitHub 1be5faaea7 bugfix: Holding CTRL key resets flying acceleration (#863) 2026-03-07 23:18:25 +00:00
TraoX_andGitHub bbe396d90d Update to zlib 1.3.2 (#852) 2026-03-07 13:56:03 -06:00
9cac3e0394 Change F3 rendering and add git version information (#836)
* Change F3 rendering and add git version information

* Change position, block, chunk and facing

* Limit position decimal places

* Move LCE unique to the bottom and add more java features

* Fix chunk information disappearing after y256

* Add chunk count information

* Move build number script to prebuild.ps1

* We dont need to specify vector and wstring are from std

* Restore build number to fix multiplayer

* Use short symbolic-ref

* Restore original BuildVer.h

---------

Co-authored-by: Loki <lokio.casebstv@gmail.com>
Co-authored-by: Loki Rautio <lokirautio@gmail.com>
2026-03-07 13:55:44 -06:00
Loki Rautio e5ad785803 Revert "50% - 100% increase to some mob caps. (#789)"
It's unclear if this change maintains mob density parity so it has been
reverted. This can be committed back in if parity is properly verified
2026-03-07 12:54:40 -06:00
LokiandGitHub 766f5e2c57 Update CONTRIBUTING.md 2026-03-07 12:46:35 -06:00
LokiandGitHub 2e21f4830d Fix formatting issue in CONTRIBUTING.md 2026-03-07 12:08:06 -06:00
LokiandGitHub 3839bf6187 Add LCE Parity guidelines to CONTRIBUTING.md 2026-03-07 12:03:20 -06:00
eh-KandGitHub b3ff7f5998 50% - 100% increase to some mob caps. (#789)
* 50% increase to most mob caps, doubling some.

* Changed from 75 to 70 to match PC parity. Ambient is back to 20
2026-03-08 00:32:01 +07:00
void_17 b7bd9bb903 Move to newer C++17 language standard 2026-03-08 00:23:39 +07:00
bulkmoerlsandGitHub 261c7f3de0 added git lfs (#849) 2026-03-08 00:22:21 +07:00
VivyaCCandvoid_17 52b1882f13 win cpp23 compat: Minecraft.Client 2026-03-07 23:58:51 +07:00
VivyaCCandvoid_17 6dfdd90328 win cpp23 compat: Minecraft.World 2026-03-07 23:58:21 +07:00
GuglioIsStupidandGitHub 7c2869c5b9 I genuinely didn't know release and debug had seperate include dirs 😢😢😢 i suck with vs projects (#830) 2026-03-07 21:09:34 +07:00
GuglioIsStupidandGitHub 220fe18487 Fix PCH (#828) 2026-03-07 20:21:37 +07:00
GuglioIsStupidandGitHub 38ce933fd5 voids request - Move the filesystem files to root/ as it will be used in both Minecraft.Client and Minecraft.World (#819)
* Move Filesystem to root/include/ as per devoiders request

* Filesystem -> lce_filesystem
2026-03-07 18:36:05 +07:00
ModMaker101andGitHub e754bad17e Improve gamma shader parity - fixes #611 (#790)
* Call gamma post process after `ui.render` #611

* Fixed "washed out" look.

* Improve gamma pass and cache viewport size
2026-03-07 03:00:38 -06:00
KevinandGitHub cc85ecf05a Block sneak while chat is open. (#803) 2026-03-07 02:57:20 -06:00
Loki Rautio 341dfa1868 update audio to prevent artifacts 2026-03-07 00:50:44 -06:00
Loki Rautio 4f73dd18b1 Actually really switch back to extracted sounds, add back missing sounds
The sounds Guglio was using were missing several sounds (skeleton damage, etc) as well as the "original" sound pack just being wrong. Switches back to the original sounds, though Miles was still louder somehow
2026-03-06 22:11:29 -06:00
Loki Rautio 16eec7e68b Revert to original sounds
Original sounds from Guglio - should be correct audio levels. Current sounds
were too quiet so swapping these for JE sounds will have to be done with
some sort of normalization level sampling thingie with ffmpeg or smthn
2026-03-06 20:59:25 -06:00
Loki Rautio c590cd6995 Fix SkinsBirthday.pck incompatability
Technically incompatible in debug builds, this removes the .loc file from the archive
2026-03-06 20:36:05 -06:00
KevinandGitHub 13960a93b2 Max players from 8 -> 255 + small connection optimizations (#722)
* Multiplayer 8 to max byte increase.

Made-with: Cursor

* Server chunk optimizations for large player counts, server full notification fix, added to server.properties.
2026-03-06 19:23:32 -06:00
MijaeLioandGitHub 16446265d5 Add Render Distance option. (#675)
* FOV option without debug menu

Now located in Graphics section.

Based on the FOV thing from discord idk

* language

* render distance option for graphics menu

* oop

* swf files on media

* revert changes on language selector

* nvm it was actually easy to fix

* forgot this

* Final probably

Fixed visual bug and made the chunk updates depend to your view distance.
2026-03-06 19:14:06 -06:00
Loki Rautio 216943716b Revert "Fix UI button staying focused on mouse-out + controller snap (#773)"
This reverts commit 2f614a52c2.
Causes weird selection regression in certain menus
2026-03-06 19:05:12 -06:00
Adem KurtandGitHub 8f2ae54b3a Add toggle inventory/crafting with E and C/R keys (#593) 2026-03-06 19:02:42 -06:00
GabsPuNs123andGitHub 8dee53a565 Update DLCs for windows64media (#778)
* Fix DLCs textures and crash in 720p

* Revert "Fix DLCs textures and crash in 720p"

This reverts commit 7c386053608a489e31875e00460f69b231d3fe8b.

* Update Durango and Windows64 DLCs Textures also fix crash in 720p

* DLC update for Windows edition

- The windows edition dont use anymore DurangoMedia
- Fixed Bed and missing items in Skyrim
- Fixed Hud in almost all the DLCs (Halo hud in 720p is still the default hud)
- Add 720p support
- Add missing skin packs
- High quality Music for DLCs

* Add Fantasy Texture Pack, Remove LittleBigPlanet DLC

The LittleBigPlanet world crash the game, the texture pack dont support 1080p, and the loc file wasn't working
2026-03-06 18:56:15 -06:00
FriedMonkeyandGitHub 54df68ac53 Fix ocelot hit noises (#776)
it couldnt play sound because folder has hitt with 2 t instead of just hit
2026-03-06 18:48:05 -06:00
a6699a2e6f Fixed baby zombie hitbox size (#765)
* Added scaling to zombie

i added scaling to zombie based on if its a baby or not

just setting the size does not work you have to set it in the tick (look at the tick for slimes which is a scalable monster)

* add output dir to gitignore

the build output folder is now added to the git ignore

---------

Co-authored-by: Loki <lokirautio@gmail.com>
2026-03-06 18:45:22 -06:00
LrxhandGitHub 2f614a52c2 Fix UI button staying focused on mouse-out + controller snap (#773) 2026-03-06 18:39:55 -06:00
GuglioIsStupidandGitHub 55be6447e3 Sound Fixes (#686)
* Fix sound settings not applying

* Reimplement miles sound artifacts

* Fix stone brick stairs recipe

* Fix craft and scroll sound

* Rename scrollfocus.ogg to scroll.ogg

* Remove unneeded code

* Reorganize sounds, revert spam sound press, add witch sounds and fix slimes

* I forgot my console again
2026-03-06 18:38:14 -06:00
Vincent ZhangandGitHub d4db0b947f Add Adventure Mode as an option when creating world (#757)
* per user config should be .gitignored

* add comment surrounding gitignore update

* make it wildcard

* add fullscreen to launch option struct

* remove redundant forward declaration and use fullscreen launch option in main

* add adventure mode option as well as adjust cycling logic

* Revert deleting *.user from end of .gitignore

* rework comments
2026-03-06 18:37:11 -06:00
Loki Rautio 48028145dc Disable yet more debug stuff from Release 2026-03-06 17:06:21 -06:00
Loki Rautio f254af3d0c Disable more debug features in Release build 2026-03-06 16:46:06 -06:00
catdbgandGitHub eeedbf08d3 Save FOV value to settings (#670)
* Save FOV value to settings.dat

* Batch font drawing to fix debug overlay FPS

* Revert "Batch font drawing to fix debug overlay FPS"

This reverts commit 7dcecdbd4d6037194e75d9fe3130845dd8690928.
2026-03-06 16:38:16 -06:00
Loki Rautio 4e67706dc3 Revert "Fixed stained glass and glass pane not rendering the water and held item transparency for stained glass and pane (#748)"
This reverts commit a4214805d1.
2026-03-06 16:29:46 -06:00
MarvelcoandGitHub a4214805d1 Fixed stained glass and glass pane not rendering the water and held item transparency for stained glass and pane (#748)
* fixed stained glass and glass pane not rendering the water

* Fixed held item transparency for stained glass and pane
2026-03-06 15:35:30 -06:00
catdbgandGitHub d265ce29a2 Scale debug overlay, truncate terrain lines (#751) 2026-03-06 15:34:37 -06:00
void_17andGitHub 988e3042e0 Remove all MSVC __int64 (#742) 2026-03-07 03:31:30 +07:00
Loki Rautio 175fc3824e Disable EULA popup 2026-03-06 13:44:43 -06:00
void_17 fc7ddbab14 Cherry-pick non-code files to exclude from vscode search
It slowed down the code search significantly, so I had to manually cherry-pick assets and binary files from vscode search which made it much, much faster.
2026-03-07 02:35:34 +07:00
LokiandGitHub c5229cde93 Update README with download instructions
Added download instructions for Windows users in README.
2026-03-06 13:36:24 -06:00
LokiandGitHub 563a1b0d12 Update README.md
Add details about current server functionality
2026-03-06 13:34:54 -06:00
Loki Rautio 0404a97257 Disable overlapping debug cheat inputs on dpad for Release
Same thing as last commit
2026-03-06 13:11:24 -06:00
Loki Rautio ed2a20dab7 Disable DPad Cheat Overrides on Release builds
These cheats conflict with normal DPad behavior so they should be disabled.
If we want to reintroduce these, we'll need to find a better set of triggers
(and ideally respect server cheat settings) for allowing their use
2026-03-06 13:08:09 -06:00
KaoruBoyandGitHub 015c368fc1 Don't block KEYDOWN messages (#698) 2026-03-06 13:00:53 -06:00
catdbgandGitHub 9cbbae1c3e Batch font drawing to fix debug overlay FPS (#732) 2026-03-06 12:56:35 -06:00
Loki Rautio 84c06dde72 Switch back to Iggy chat temporarily
Partially reverts changes in #682 that uses a better technique for rendering
the chat in favor of Iggy. We will need to go back once we update that
version for better visual parity with the Iggy chat rendering (position,
spacing, font size) but this works for now. Fixes #718
2026-03-06 12:54:28 -06:00
T3stAccandGitHub 2327161747 Update README.md (#727) 2026-03-06 12:40:51 -06:00
MrTheShyandGitHub ce24910f30 Overhaul Keyboard/Mouse Support (#612)
* Sync keyboard text buffer from Flash before processing physical input

The native keyboard scene maintained a separate C++ buffer
(m_win64TextBuffer) for physical keyboard input, which was pushed
to the Flash text field via setLabel(). However, when the user typed
with the on-screen controller buttons, Flash updated its text field
directly through ActionScript without updating the C++ buffer.

This caused a desync: switching back to the physical keyboard would
overwrite any text entered via controller, since m_win64TextBuffer
still held the old value before the controller edits.

Fix: read the current Flash text field into m_win64TextBuffer at the
start of each tick(), before consuming new physical keyboard chars.
This ensures both input methods always operate on the same state.

* Use last active input device to decide keyboard mode instead of connection state

The keyboard UI mode (on-screen virtual keyboard vs direct text input)
was determined by Win64_IsControllerConnected(), which checks if any
XInput controller is physically plugged in. This meant that even if
the player was actively using mouse and keyboard, the virtual keyboard
would still appear as long as a controller was connected.

Replace the connection check with g_KBMInput.IsKBMActive(), which
tracks the actual last-used input device based on per-frame input
detection. Now the keyboard mode is determined by what the player is
currently using, not what hardware happens to be plugged in.

Affected scenes: CreateWorldMenu (world naming) and LoadOrJoinMenu
(world renaming).

* Fix TextInput caret behavior and add proper cursor editing for KBM direct edit

The direct text editing mode introduced for KBM users had several
issues with the TextInput control's caret (blinking cursor) and text
manipulation:

1. Caret visible when not editing:
   When navigating to the world name field with keyboard/mouse, Flash's
   Iggy focus system would show the blinking caret even though the field
   wasn't active for editing yet (Enter not pressed). This was misleading
   since typing had no effect in that state.

   Fix: access the FJ_TextInput's internal m_mcCaret MovieClip and
   force its visibility based on editing state. This is enforced every
   tick because setLabel() and Flash focus transitions continuously
   reset the caret state.

2. No cursor movement during editing:
   The direct edit implementation treated the text as a simple buffer
   with push_back/pop_back — there was no concept of cursor position.
   Backspace only deleted from the end, and arrow keys did nothing.

   Fix: track cursor position (m_iCursorPos) in C++ and use wstring
   insert/erase at that position. Arrow keys (Left/Right), Home, End,
   and Delete now work as expected. The visual caret position is synced
   to Flash via the FJ_TextInput's SetCaretIndex method.

3. setLabel() resetting caret position:
   Every call to setLabel() (when text changes) caused Flash to reset
   the caret to the end of the string, making the cursor jump visually
   even though the C++ position was correct.

   Fix: enforce caret position via setCaretIndex every tick during
   editing, so any Flash-side resets are immediately corrected.

New UIControl_TextInput API:
- setCaretVisible(bool): toggles m_mcCaret.visible in Flash
- setCaretIndex(int): calls FJ_TextInput.SetCaretIndex in Flash

* Fix keyboard/arrow navigation not working when no UI element is focused

On Windows64 with KBM, moving the mouse over empty space (outside any
button) would clear the Iggy focus entirely. After that, pressing arrow
keys did nothing because Flash had no starting element to navigate from.

Two changes here:

- Don't set focus to IGGY_FOCUS_NULL when the mouse hovers over empty
  space. The previous hover target stays focused, so switching back to
  arrows keeps working seamlessly.

- When a navigation key is pressed and nothing is focused at all (e.g.
  mouse was already on empty space when the menu opened), grab the first
  focusable element instead of silently dropping the input. The keypress
  is consumed to avoid jumping two elements at once.

This makes mixed mouse+keyboard navigation feel a lot more natural.
You can point at a button, then continue with arrows, or just start
pressing arrows right away without having to hover first.

* Overhaul mouse support and generalize direct text editing to all UI scenes

This is a large rework of the Windows64 KBM (keyboard+mouse) input layer.
It touches the mouse hover system, the mouse click dispatch, and the direct
text editing infrastructure, then applies all of it to every scene that has
text input fields or non-standard clickable elements.

MOUSE HOVER REWRITE (UIController.cpp tickInput)

The old hover code had two structural problems:

(a) Scene lookup was group-first: it iterated UI groups and checked all
layers within each group. The Tooltips layer on eUIGroup_Fullscreen (which
holds non-interactive overlays like button hints) would be found before
in-game menus on eUIGroup_Player1. The tooltip scene focusable objects
captured mouse input and prevented hover from reaching the actual menu.

Fixed by switching to layer-first lookup across all groups, and skipping
eUILayer_Tooltips entirely since those are never interactive.

(b) On tabbed menus (LaunchMoreOptionsMenu Game vs World tabs), all
controls from all tabs are registered in Flash at the same time. There was
no filtering, so controls from inactive tabs had phantom hitboxes that
overlapped the active tab controls, making certain buttons unhoverable.

Fixed by introducing parent panel tracking: each UIControl now has a
m_pParentPanel pointer, set automatically by the UI_MAP_ELEMENT macro
during mapElementsAndNames(). The hover code checks the control parent
panel against the scene GetMainPanel() and skips mismatches. This is the
same technique the Vita touch code used, but applied to mouse hover.

The coordinate conversion was also simplified. The old code had two separate
scaling paths (window dimensions for hover, display dimensions for sliders).
Now there is one conversion from window pixel coords to SWF coords using
the scene own render dimensions.

REUSING VITA TOUCH APIs FOR MOUSE (ButtonList, UIScene)

Several APIs originally gated behind __PSVITA__ are now enabled for Win64:

- UIControl_ButtonList::SetTouchFocus(x,y) and CanTouchTrigger(x,y): the
  Flash-side ActionScript methods were already registered on all platforms
  in setupControl(), only the C++ wrappers were ifdef-gated. Opening the
  ifdefs to include _WINDOWS64 lets the mouse hover code delegate to Flash
  for list item highlighting, which handles internal scrolling and item
  layout that would be impractical to replicate in C++.

- UIScene::SetFocusToElement(id): programmatic focus-by-control-ID, used as
  a fallback when Iggy focusable objects do not match the C++ hit test.

- UIScene_LaunchMoreOptionsMenu::GetMainPanel(): returns the active tab
  panel control, needed by the hover code to filter inactive tab controls.

MOUSE CLICK DISPATCH (UIScene.cpp handleMouseClick)

Left-clicking previously relied entirely on Iggy ACTION_MENU_OK dispatch,
which routes to whatever Flash considers focused. This broke for custom-
drawn elements that are not Flash buttons (crafting recipe slots), and for
scenes where Iggy focus did not match what the user visually clicked.

Added a virtual handleMouseClick(x, y) on UIScene with a default
implementation that hit-tests C++ controls. When multiple controls report
overlapping bounds (common in debug scenes where TextInputs report full
Flash-width), it picks the one whose left edge X is closest to the click.
Returns true to consume the click and suppress the normal ACTION_MENU_A
dispatch via a m_mouseClickConsumedByScene flag on UIController.

The default implementation handles buttons, text inputs, and checkboxes
(toggling state and calling handleCheckboxToggled directly).

CRAFTING MENU MOUSE CLICK (UIScene_CraftingMenu.cpp)

The crafting menu recipe slots (H slots) are rendered through Iggy custom
draw callback, not as Flash buttons. They have no focusable objects, so
mouse clicking did nothing.

The solution caches SWF-space positions during rendering: inside customDraw,
when H slot 0 and H slot 1 are drawn, the code extracts SWF coordinates
from the D3D11 transform matrix via gdraw_D3D11_CalculateCustomDraw_4J.
The X difference between slot 0 and slot 1 gives the uniform slot spacing.

handleMouseClick then uses these cached bounds to determine which recipe
slot was clicked, resets the vertical slot indices (same pattern as the
constructor), updates the highlight and vertical slots display, and re-shows
the old slot icon. This mirrors the existing controller LEFT/RIGHT
navigation in the base class handleKeyDown.

DIRECT EDIT REFACTORING (UIControl_TextInput)

The direct text editing feature (type directly into text fields instead of
opening the virtual keyboard) was originally implemented inline in
CreateWorldMenu with all the state, character consumption, cursor tracking,
caret visibility, and cooldown logic hardcoded in one scene.

Moved everything into UIControl_TextInput:
- beginDirectEdit(charLimit): captures current label, inits cursor at end
- tickDirectEdit(): consumes chars, handles Backspace/Enter/Escape, arrow
  keys (Left/Right/Home/End/Delete), enforces caret visibility every tick
  (because setLabel and Flash focus transitions continuously reset it),
  returns Confirmed/Cancelled/Continue
- cancelDirectEdit() / confirmDirectEdit(): programmatic control
- isDirectEditing() / getDirectEditCooldown() / getEditBuffer(): state query

For SWFs that lack the m_mcCaret MovieClip child (like AnvilMenu), the
existence check validates by reading a property from the resolved path,
since IggyValuePathMakeNameRef always succeeds even for undefined refs.
When no caret exists, the control inserts a _ character at the cursor
position as a visual fallback.

The caret check result is cached in m_bHasCaret/m_bCaretChecked to avoid
repeated Iggy calls that could corrupt internal state.

SCENES UPDATED WITH DIRECT EDIT + VIRTUAL KEYBOARD

Every scene with text input now supports both input modes: direct editing
when KBM is active, virtual keyboard (via NavigateToScene eUIScene_Keyboard)
when using a controller. The mode is chosen at press time based on
g_KBMInput.IsKBMActive().

- CreateWorldMenu: refactored to use the new UIControl_TextInput API,
  removing ~80 lines of inline editing code.

- AnvilMenu: item renaming now supports direct edit. The keyboard callback
  uses Win64_GetKeyboardText instead of InputManager.GetText (which reads
  from a different buffer on Win64). The virtual keyboard is opened with
  eUILayer_Fullscreen + eUIGroup_Fullscreen so it does not hide the anvil
  container menu underneath. Added null guards on getMovie() in setCostLabel
  and showCross since the AnvilMenu SWF may not fully load on Win64.

- SignEntryMenu: all 4 sign lines support direct edit. Clicking a different
  line while editing confirms the current one. Each line cooldown timer
  is checked independently to prevent Enter from re-opening the edit.

- LaunchMoreOptionsMenu: seed field direct edit with proper input blocking.

- DebugCreateSchematic: all 7 text inputs (name + start/end XYZ coords).
  handleMouseClick is overridden to always consume clicks during edit to
  prevent Iggy re-entry on empty space.

- DebugSetCamera: all 5 inputs (camera XYZ + Y rotation + elevation).
  Clicking a different field while editing confirms the current value and
  opens the new one. Float display formatting changed from %f to %.2f.

All keyboard completion callbacks on Win64 now use Win64_GetKeyboardText
(two params: buffer + size) instead of InputManager.GetText, which reads
from the correct g_Win64KeyboardResult global when using the in-game
keyboard scene.

SCROLL WHEEL

Mouse wheel events (ACTION_MENU_OTHER_STICK_UP/DOWN) are now centrally
remapped to ACTION_MENU_UP/DOWN in UIController::handleKeyPress when KBM
is active. Previously each scene would need to handle OTHER_STICK actions
separately, and most did not, so scroll wheel only worked in a few places.

* Add mouse click support to CraftingMenu (tab switching, slot selection, craft)

The crafting screen's horizontal recipe slots and category tabs are custom-drawn
via Iggy callbacks rather than regular Flash buttons, so the standard mouse hover
system can't interact with them. This adds handleMouseClick to derive clickable
regions from the H slot positions cached during customDraw.

Tab clicking: tab hitboxes are computed relative to the H slot row since the
Vita TouchPanel overlays (full-screen invisible rectangles) aren't suitable
for direct hit-testing on Win64. The Y bounds were tuned empirically to match
the SWF tab icon positions. Clicking a tab runs the same switch logic as
LB/RB: hide old highlight, update group index, reset slot indices,
recalculate recipes, and refresh the display.

H slot clicking: clicking a different recipe slot selects it (updating V slots,
highlight, and re-showing the previous slot). Clicking the already-selected
slot crafts the item by dispatching ACTION_MENU_A through handleKeyDown,
reusing the existing crafting path. Empty slots (iCount == 0) are ignored.

All mouse clicks on the scene are consumed (return true) to prevent misses
from falling through as ACTION_MENU_A and accidentally triggering a craft.
This only suppresses mouse-originated A presses via m_mouseClickConsumedByScene;
keyboard and controller A remain fully functional.

Also enables GetMainPanel for Win64 (was Vita-only) so the mouse hover system
can filter controls by active panel, same as other tabbed menus.

* Fix mouse hover selecting wrong buttons from the third onward

The hover code was doing a redundant second hit-test against Iggy
focusable object bounds after the C++ control bounds had already
identified the correct control. Iggy focusable bounds are wider than
the actual visible buttons and overlap vertically, so the "pick
largest x0" heuristic would match focusables belonging to earlier
buttons when hovering the right side of buttons 3+.

Replaced the IggyPlayerGetFocusableObjects path with a direct
SetFocusToElement call using the already-correct hitControlId from
the C++ hit-test, same approach the click path uses in
handleMouseClick. Also switched the overlap tiebreaker from "largest
x0" to smallest area, consistent with how clicks resolve overlapping
controls. TextInput is excluded from hover focus to avoid showing
the caret on mere mouse-over (its Iggy focus is set on click).

* Use smallest-area tiebreaker for mouse click hit-testing too

Same overlap fix applied to handleMouseClick: when multiple controls
contain the click point, prefer the one with the smallest bounding
area instead of the one with the largest left-edge X. This is more
robust for any layout (vertical menus, grids, overlapping panels)
and matches the hover path logic.

Those changes were initially made in order to fix the teleport ui for the mouse but broke every other well working ui.

* Fix mouse cursor staying trapped in window on alt-tab

When the inventory or other UI with a hidden cursor was open,
alt-tabbing out would leave the cursor locked to the game window.
SetWindowFocused(false) from WM_KILLFOCUS correctly released the
clip and showed the cursor, but Tick() was unconditionally calling
SetCursorPos every frame to re-center it, overriding the release.

Added m_windowFocused to the Tick() condition so cursor manipulation
only happens while the window actually has focus.

* Map mouse right click to ACTION_MENU_X for inventory half-stack

Right clicking an item stack in Java Edition picks up half of it.
Console Edition already handles this via ACTION_MENU_X (the X button
on controller), which sets buttonNum=1 in handleKeyDown. This maps
mouse right click to that same action so KBM players get the same
behavior across all container menus (inventory, chests, furnaces,
hoppers, etc).

* Fix mouse hover hitting removed controls (ghost hitboxes)

When removeControl() removes a Flash element (e.g. the Reinstall
button in Help & Options, or the Debug button when disabled), the
C++ control object stays in the m_controls vector. On Vita this was
handled by calling setHidden(true) and checking getHidden() in the
touch hit-test, but on Windows64 none of that was happening.

The result: removed buttons kept phantom bounds that the hover code
would match against, stealing focus from the buttons that shifted
into their visual position. In the Help & Options menu with debug
enabled, the removed Reinstall button (Button6) had ghost bounds
overlapping where the Debug button (Button7) moved to after the
removal, making Debug un-hoverable and snapping focus to Button1.

The fix has three parts:

- removeControl() now calls setHidden(true) on all platforms, not
  just Vita. The m_bHidden member was already declared on all
  platforms, only the accessors were ifdef'd behind __PSVITA__.

- Removed the __PSVITA__ ifdef from setHidden/getHidden in
  UIControl.h so they're available everywhere.

- Added getHidden() checks in both the hover and click hit-test
  loops, matching what the Vita touch code already does. The check
  is a simple bool read (no Flash/Iggy call), placed before the
  getVisible() query which hits Flash and can return stale values
  for removed elements.

* Add right-click to open save options in world selection menu

On controller, RB (ACTION_MENU_RIGHT_SCROLL) opens the save options
dialog (rename/delete) when a save is selected. Mouse right-click
maps to ACTION_MENU_X, which had no Windows64 handler in this scene.

Added save options handling under ACTION_MENU_X for _WINDOWS64 so
right-clicking a save opens the same dialog. Also handles the mashup
world hide action for right-click consistency. Console-only options
(copy save, save transfer) are excluded since they don't apply here.

* Fix Escape key not opening pause menu during tutorial hints

The KBM pause check had a IsTutorialVisible guard that blocked
Escape entirely while any tutorial popup was on screen. The
controller path never had this restriction. Removed the check
so Escape behaves the same as Start on controller.

* Fix crash in WriteHeader when save buffer is too small for header table

When a player enters a new region, RegionFile's constructor calls
createFile which adds a FileEntry with length 0 to the file table.
This increases the header table size (appended at the end of the save
buffer) by sizeof(FileEntrySaveData) per entry, but since no actual
data is written to the file, MoveDataBeyond is never called and the
committed virtual memory pages are never grown to match.

On the next autosave tick, saveLevelData writes level.dat first
(before chunkSource->save which would have grown the buffer). If
level.dat doesn't need to grow, finalizeWrite calls WriteHeader which
tries to memcpy the now-larger header table past the end of committed
memory, causing an access violation.

This is especially likely in splitscreen where two players exploring
at the same time can create multiple new RegionFile entries within a
single tick, quickly exhausting the page-alignment slack in the buffer
(yes i am working at splitscreen in the meanwhile :) )

The fix was deduced by tracing the crash callstack through the save
system: FileHeader, ConsoleSaveFileOriginal, the stream chain, and
the RegionFile/RegionFileCache layer. The root cause turned out to be
a gap between createFile (which grows the header table) and
MoveDataBeyond (the only place that grows the buffer), with
finalizeWrite sitting right in between unprotected.

The buffer growth check added here mirrors the exact same VirtualAlloc
pattern already used in MoveDataBeyond (line 484-497) and in the
constructor's decompression path (line 176-190), so it integrates
naturally with the existing code. Same types, same page rounding,
same error handling. The fast path (no new entries, buffer already big
enough) is a single DWORD comparison that doesn't get taken, so there
is zero overhead in the common case.

This is the right place for the fix because finalizeWrite is the sole
caller of WriteHeader, meaning every code path that writes the header
(closeHandle, PrepareForWrite, deleteFile, Flush) is now protected by
a single check point.

* Fix TextInput bugs and refactor direct edit handling into UIScene base class

The fake cursor character (_) used for SWFs without m_mcCaret was leaking
into saved sign and anvil text. This happened because setLabel() with
instant=false only updates the C++-side cache, deferring the Flash write
to the next control tick. Any getLabel() call before that tick reads the
old Flash value still containing the underscore. Fixed by passing
instant=true in confirmDirectEdit, cancelDirectEdit, and the Enter key
path inside tickDirectEdit, so the cleaned text hits Flash immediately.

Mouse hover over TextInput controls (world name, anvil name, seed field)
was not showing the yellow highlight border. The hover code used
IggyPlayerSetFocusRS which sets Iggy's internal dispatch focus but does
not trigger Flash's ChangeState callback, so no visual feedback appeared.
Buttons worked fine because Iggy draws its own focus ring on them, but
TextInput relies entirely on ChangeState(0) for the yellow border.
Switched to SetFocusToElement which goes through the Flash-side SetFocus
path, then immediately call setCaretVisible(false) to suppress the
blinking caret that comes with focus. No visual flicker since rendering
happens after both tickInput and scene tick complete.

While direct editing, mouse hover was able to move focus away to other
TextInputs on the same scene (most noticeably on the sign editor, where
hovering a different line would steal focus from the line being typed).
Added an isDirectEditBlocking() check in the hover path to skip focus
changes when any input on the scene is actively being edited.

The Done button in SignEntryMenu was unresponsive to mouse clicks during
direct editing. The root cause is execution order: handleMouseClick runs
before handleInput in the frame. The base handleMouseClick found the Done
button and called handlePress, but handlePress bailed out because of the
isDirectEditing guard. The click was marked consumed, so handleInput
never saw it. Fixed by overriding handleMouseClick in SignEntryMenu to
detect the Done button hit while editing and confirm + close directly.

Added click-outside-to-deselect for anvil and world name text inputs.
Both scenes previously required Enter to confirm the edit, which felt
wrong. Now clicking anywhere outside the text field bounds confirms the
current text, matching standard UI behavior.

The anvil menu now updates the item name in real time while typing, like
Java edition. Previously the name was only applied on Enter, so the
repair cost display was stale until confirmation.

The biggest change is structural: every scene that used direct editing
(AnvilMenu, CreateWorldMenu, SignEntryMenu, LaunchMoreOptionsMenu,
DebugCreateSchematic, DebugSetCamera) had its own copy of the same
boilerplate -- tickDirectEdit loops in tick(), click-outside hit testing
in handleMouseClick(), cooldown guard checks in handleInput/handlePress,
and result dispatch with switch/if chains. This was around 200 lines of
near-identical code scattered across 6 files, each with its own slight
variations and its own bugs waiting to happen.

Pulled all of it into UIScene with two virtual methods: getDirectEditInputs()
where scenes register their text inputs, and onDirectEditFinished() where
they handle confirmed/cancelled results. The base class tick() drives
tickDirectEdit on all registered inputs, handleMouseClick() does the
click-outside-to-deselect hit test generically using panel offsets, and
isDirectEditBlocking() replaces all the inline cooldown checks. Scenes
now just override those two methods and get everything for free.

Also removed the m_activeDirectEditControl enum tracking from the debug
scenes (DebugCreateSchematic, DebugSetCamera) since the base class
handles lifecycle tracking through the controls themselves.

* Remap scroll wheel to LEFT/RIGHT for horizontal controls

The scroll wheel was always remapped to UP/DOWN, which is fine for
vertical lists but useless on horizontal controls like sliders and
the texture pack selector.

Track whether the mouse is hovering a horizontal control during the
hover hit-test (new bool m_bMouseHoverHorizontalList, set for
eTexturePackList and eSlider). When the flag is set, handleKeyPress
emits LEFT/RIGHT instead of UP/DOWN for wheel events.

TexturePackList is also now part of the mouse hover system with
proper hit-testing, relative-coord SetTouchFocus and GetRealHeight
for accurate bounds.

* Guard setCaretVisible and setCaretIndex against null movie

tickDirectEdit calls into Iggy every tick without checking if the
movie is still valid, which crashes inside iggy_w64.dll when the
Flash movie gets unloaded or isn't ready yet.

* Fix creative inventory scroll for both mouse wheel and controller

The mouse scroll wheel was not working in the creative inventory at
all. UIController remaps wheel input from OTHER_STICK to UP/DOWN for
KBM users, but the base container menu handler consumed UP/DOWN for
grid navigation before it could reach the creative menu's page
scrolling logic in handleAdditionalKeyPress. Fixed by detecting
scroll wheel input on UP/DOWN in the base handler and forwarding it
as OTHER_STICK to handleAdditionalKeyPress instead.

Also fixed the controller right stick scrolling way too fast: it was
jumping TabSpec::rows (5) rows per tick at 100ms repeat rate, which
blew through the entire item list almost instantly. Reduced to 1 row
per tick so scrolling feels controlled on both input methods.
2026-03-06 12:38:12 -06:00
LrxhandGitHub 185af94839 fix gamma breaking f3 menu (#704) 2026-03-06 11:14:44 -06:00
NecmiandGitHub 6cd6b21926 Only drop one seed, not 3 (#710)
* Fix mouse getting grabbed outside window of the game

* seedfix by changing spawnresources() & removing other branch pullrequest

* revert sln change & remove comment
2026-03-06 11:05:03 -06:00
KevinandGitHub ea65542c1b Add Chat / Pastes / Formatting (#682)
* Initial fixes for ContainerSetSlotPacket and CraftItemPacket

* Chat: paste, history, § formatting, 1-9 block when open (Windows64)

Made-with: Cursor

* static_cast refactor
2026-03-06 09:52:28 -06:00
Andrew P. HarperandGitHub 1755cd58be Fix Stained Glass being wrong colors (#529)
Fixes issue with stained glass not showing the correct color in the name
2026-03-06 09:35:40 -06:00
GuglioIsStupidandGitHub de46641cda Reimplement miles sound artifacts, Stone Brick Stairs recipe, and craft sound (#684)
* Reimplement miles sound artifacts

* Fix stone brick stairs recipe

* Fix craft and scroll sound
2026-03-06 01:45:25 -06:00
EribetraandGitHub 0469e982ce Replace .ogg music with their Java edition counterparts (#677)
* Replace .ogg music with their Java edition counterparts

Now that we are using MiniAudio, we can add Java Edition's music files, which have much higher quality than LCE's .binka files.

Note that the_end_dragon_alive.ogg is different as a result.

* Update the_end_dragon_alive.ogg

* Update cat.ogg

* high quality LCE cat.ogg recreation

* Updated cat.ogg to have exact music length
2026-03-06 00:42:55 -06:00
kuwaandGitHub 182d76f391 Introduce uid.dat (offline PlayerUIDs), fix multiplayer save data persistence (#536)
* fix: fix multiplayer player data mix between different players bug

Fixes a Win64 multiplayer issue where player data (`players/*.dat`) could be mismatched because identity was effectively tied to connection-order `smallId` XUIDs.
Introduces a deterministic username-derived persistent XUID and integrates it into the existing XUID-based save pipeline.

- Added `Windows64_NameXuid` for deterministic `name -> persistent xuid` resolution
- On Win64 login (`PlayerList`), set `ServerPlayer::xuid` from username-based resolver
- Aligned local player `xuid` assignment (`Minecraft`) for create/init/respawn paths to use the same resolver
- Added Win64 local-self guard in `ClientConnection::handleAddPlayer` using name match to avoid duplicate local remote-player creation
- Kept `IQNet::GetPlayerByXuid` compatibility fallback behavior, while extending lookup to also resolve username-based XUIDs
- Moved implementation to `Minecraft.Client/Windows64/Windows64_NameXuid.h`; kept legacy `Win64NameXuid.h` as compatibility include

Rename migration is intentionally out of scope (same-name identity only).

* fix: preserve legacy host xuid (base xuid + 0) for existing world compatibility

- Add legacy embedded host XUID helper (base + 0).
- When Minecraft.Client is hosting, force only the first host player to use legacy host XUID.
- Keep name-based XUID for non-host players.
- Prevent old singleplayer/hosted worlds from losing/mismatching host player data.

* update: migrate Win64 player uid to `uid.dat`-backed XUID and add XUID based duplicate login guards

- Replace Win64 username-derived XUID resolution with persistent `uid.dat`-backed identity (`Windows64_Xuid` / `Win64Xuid`).
- Persist a per-client XUID next to the executable, with first-run generation, read/write, and process-local caching.
- Keep legacy host compatibility by pinning host self to legacy embedded `base + 0` XUID for existing world/playerdata continuity.
- Propagate packet-authoritative XUIDs into QNet player slots via `m_resolvedXuid`, and use it for `GetXuid`/`GetPlayerByXuid` with legacy fallback.
- Update Win64 profile/network paths to use persistent XUID for non-host clients and clear resolved identity on disconnect.
- Add login-time duplicate checks: reject connections when the same XUID is already connected (in addition to existing duplicate-name checks on Win64).
- Add inline compatibility comments around legacy/new identity coexistence paths for easier future maintenance.

* update: ensure uid.dat exists at startup in client mode for multiplayer
2026-03-06 00:01:36 -06:00
MozzarellaRatandGitHub c45541080f Fix boat gravity (#651)
reimplements boat gravity
2026-03-05 23:35:45 -06:00
Vincent ZhangandGitHub 73cc345f54 Add a launch argument for full screen (#663)
* per user config should be .gitignored

* add comment surrounding gitignore update

* make it wildcard

* add fullscreen to launch option struct

* remove redundant forward declaration and use fullscreen launch option in main
2026-03-05 22:54:30 -06:00
qwasdrizzelandGitHub 255a18fe8e Fix crash by ensuring FOV is not less than 1 2026-03-05 22:20:39 -06:00
qwasdrizzelandGitHub 06a5f103b4 Fix crash by ensuring FOV is not less than 1 2026-03-05 22:20:39 -06:00
qwasdrizzelandGitHub cffe636e35 Merge branch 'smartcmd:main' into main 2026-03-05 22:18:36 -06:00
qwasdrizzelandGitHub 53adf17cb2 Merge branch 'smartcmd:main' into main 2026-03-05 22:18:36 -06:00
GuglioIsStupidandGitHub 5cbdf27b46 Fix sound settings not applying (#664)
* Fix sound settings not applying

* Remove my AllocConsole

* Forgot this printf
2026-03-05 22:05:59 -06:00
ZyroXandGitHub e2b8699ba5 Add missing Firework sounds (#660) 2026-03-05 21:42:09 -06:00
KevinandGitHub d22ab815e3 Initial fixes for ContainerSetSlotPacket and CraftItemPacket (#649) 2026-03-05 21:20:40 -06:00
MarlianandGitHub 0c2e27cae7 Add missing horse/donkey/mule/zombie/skeleton horse sounds (#650) 2026-03-05 20:41:43 -06:00
Loki Rautio 090cc653cc Disable "Debug Settings" in Release builds
People keep breaking random stuff by using these settings, so turn them
off for now in release builds. If folks can figure out how to compile a
debug build locally, they can use em :)
2026-03-05 20:32:04 -06:00
PatrxgtandGitHub 0d95980dca Added missing dots and linked official Microsoft VS 2022 Community Edition mirror in the build instructions. (#626) 2026-03-06 07:56:28 +07:00
hexlocationandGitHub 34c22f6ab5 fix: properly detect host env. (#628) 2026-03-06 07:54:40 +07:00
MarvelcoandGitHub b7b29c0b7b Fixed the double block break in Creative mode (#642)
* this seems unnecessary

* fixed the double block break on single click
2026-03-06 07:48:27 +07:00
GuglioIsStupidandGitHub 8398eb16b8 Miniaudio Implementation (+stb_vorbis) (#624)
* Miniaudio Implementation

* Do not link miles + remove miles lib
2026-03-06 07:48:12 +07:00
MarlianandGitHub f012250219 Fix creative mode double block break on single click (#640) 2026-03-06 07:25:37 +07:00
qwasdrizzelandGitHub 5d544bcb83 Fix for flying angle snapping (#641)
* Modify dispense behavior to set outcome as LEFT_ITEM

* Fix the angle problem with flying

Removed checks that limit flying to a 90 degree angle, which caused the problem.
2026-03-06 07:22:54 +07:00
qwasdrizzelandGitHub d1eb09a4b9 Merge branch 'smartcmd:main' into main 2026-03-05 18:01:32 -06:00
qwasdrizzelandGitHub a71a093235 Merge branch 'smartcmd:main' into main 2026-03-05 18:01:32 -06:00
qwasdrizzelandGitHub 4b13b3345e Fix the angle problem with flying
Removed checks that limit flying to a 90 degree angle, which caused the problem.
2026-03-05 18:01:13 -06:00
qwasdrizzelandGitHub 9eb77ec0ef Fix the angle problem with flying
Removed checks that limit flying to a 90 degree angle, which caused the problem.
2026-03-05 18:01:13 -06:00
AcTh2andGitHub 75c4f51218 Close the villager trade gui when he dies (#637) 2026-03-06 07:00:04 +07:00
qwasdrizzelandGitHub 0666959d31 Merge branch 'smartcmd:main' into main 2026-03-05 17:17:45 -06:00
qwasdrizzelandGitHub 28f9e89e59 Merge branch 'smartcmd:main' into main 2026-03-05 17:17:45 -06:00
ModMaker101andGitHub eed770b121 Fixed boats falling and a TP glitch #266 (#615) 2026-03-05 16:07:47 -06:00
GuglioIsStupidandGitHub a0b2fe885d Fix compiling with cmake (#619) 2026-03-05 15:50:27 -06:00
EnderActuallyandGitHub cd3bb89317 Add issue templates again (#457)
* Update issue templates

* Update bug_report.md

* change to form

* Refactor bug report template

* Remove 'type' field from bug report template

Removed the 'type' field from the bug report template.

* Add final Fields

* remove invalid syntax

* Fix typo in bug report template for Debug label

* Change input types to textareas in bug report template

Fixes uploads with images and videos

* Change to form

* Update bug report template validations

Changed 'required' validation for additional context from true to false.

* Change feature request template to suggestion request

* fix title

* Refactor suggestion request template

Removed duplicate textarea for solution and updated title format.
2026-03-05 15:33:38 -06:00
catdbgandGitHub ee24488ab6 Fix audio settings resetting on launch (#610) 2026-03-05 15:09:36 -06:00
dtentiionandGitHub aadb511504 Fix save list, delete save, exit without saving, and blank username on Windows64 (#539)
* Fix world save rename not applying new name

KeyboardCompleteWorldNameCallback had no _WINDOWS64 branch, so the
typed name was validated then silently discarded on every rename attempt.

Write the new name to a worldname.txt sidecar file next to the save
(Windows64\GameHDD\{folder}\worldname.txt) and update the in-memory
display name immediately. ReadLevelNameFromSaveFile now checks for this
sidecar first so renamed saves persist correctly across restarts.

* Fixed gamertag being blank upon renaming and re-joining a save

* Save deletion fix, exiting without saving fix

* Add native in-game keyboard UI for world naming and renaming
2026-03-05 14:57:37 -06:00
Loki Rautio f48a39ae3d Adjust github action for debug 2026-03-05 14:33:33 -06:00
CristiandisandGitHub d3593f1df3 Trim newline characters from IP address (#600) 2026-03-05 14:27:08 -06:00
ModMaker101andGitHub 7147dbad92 Fix debug build not working (#603) 2026-03-05 14:17:12 -06:00
Loki Rautio 9e52beaa9d Support debug compile test in PRs 2026-03-05 14:12:31 -06:00
Loki Rautio f208a5c80e Add debug action 2026-03-05 14:11:04 -06:00
void_17andGitHub 5c6f09f395 Forgot these AUTO_VAR macros too
Remove the remaining `AUTO_VAR` macros I forgot to remove
2026-03-06 02:46:20 +07:00
ModMaker101andGitHub cbcf3de358 Fix gamma slider via pixel shader #178 (#481)
* Fix gamma slider via pixel shader #178

* LCE-like gamma using postprocess shader
2026-03-06 02:41:17 +07:00
void_17andGitHub 55231bb8d3 Remove AUTO_VAR macro and _toString function (#592) 2026-03-06 02:11:18 +07:00
7d6658fe5b Add servers.txt so players can add an arbitrary amount of servers to the "Join Game" list (#478)
* Code to read servers.txt

* logging (still doesnt work)

* server names load properly hooray

* remove logger as it only spews out nonsense anyways

* Do not use _countof, use sizeof(label)/sizeof(wchar_t) or make label std::array<wchar_t, 128> and call .size()

* Fix memory leak by listing info pointers

* C++ style cast (i think)

* this throws a RAV but why

* why oh why

* I just assume infos get deleted elsewhere otherwise idk why it breaks no matter what i do

* they get deleted all this time ohhhhhh

---------

Co-authored-by: Siepert123 <createlegacy69@gmail.com>
2026-03-05 22:57:54 +07:00
Loki Rautio a03c36f83f Update nightly description
Fix broken new lines. Oops, forgot this was yaml
2026-03-05 09:06:14 -06:00
Loki Rautio 1b69eef4b0 Update nightly description 2026-03-05 07:48:32 -06:00
MarlianandGitHub 9c17f3473a Fix Ctrl-sprint not working while flying in creative mode (#563)
Remove the !player->abilities.flying guard that was incorrectly added around the Ctrl-sprint block in Input.cpp during the KBM refactor. This prevented Ctrl+W from initiating sprint while flying in creative mode. Sprinting on the ground in both survival and creative worked fine.

The sprint flag now sets correctly whenever Ctrl+W is held, including while flying. LocalPlayer::aiStep() still properly gates setSprinting() with onGround, enoughFoodToSprint, isUsingItem etc.

Fixes smartcmd/MinecraftConsoles#470
2026-03-05 07:39:11 -06:00
Loki Rautio a37ebe221c Add Contributor's Guide, update README 2026-03-05 07:23:01 -06:00
Loki Rautio 23cb7de110 Add additional warnings and a field to PR template 2026-03-05 07:11:47 -06:00
MarlianandGitHub c236e46ef6 Fix music disc sound leaking across dimensions (#552)
Stop streaming music (jukebox) when the player changes dimensions so music disc sounds from the overworld cannot be heard in the nether or vice versa.

Previously, the streaming audio continued playing at its original world coordinates even after a dimension change, causing the sound to leak into the new dimension at the same position.

Fixes #411
2026-03-05 17:22:55 +07:00
GabsPuNs123andGitHub c2da9e90f8 Fix DLCs textures and update logo in 720p (#517)
* Fix DLCs textures and crash in 720p

* Revert "Fix DLCs textures and crash in 720p"

This reverts commit 7c386053608a489e31875e00460f69b231d3fe8b.

* Update Durango and Windows64 DLCs Textures also fix crash in 720p
2026-03-05 15:12:50 +07:00
void_17andGitHub 8cb42a4806 Revert "Fix crash when launching at 720p" (#545) 2026-03-05 15:12:01 +07:00
KoreanandGitHub 8d5452679f Updated to work with KBM refactor (#507) 2026-03-05 14:48:06 +07:00
MarvelcoandGitHub c77bb4dae4 fixed delay issue when breaking a block (#537) 2026-03-05 14:46:38 +07:00
qwasdrizzelandGitHub 892a6056ea Modify dispense behavior to set outcome as LEFT_ITEM (#542) 2026-03-05 14:31:37 +07:00
disintegrateandGitHub 33c798a885 Failsafe for signs if entered over max line length (#389)
* Failsafe for signs if entered over max line length

* Removed debug message.

* Revert "Removed debug message."

This reverts commit 553c43669769dc0468c266f1e31778552c615d0c.

* Update SignTileEntity.cpp

* Changed flag to _DEBUG
2026-03-05 14:30:56 +07:00
PortalandGitHub fcc9970ec6 Replace CopyAssets.cmake with multithreaded Robocopy (and rsync) implementation. (#410)
* Replace CopyAssets.cmake with Robocopy implementation.

* Replace CopyAssets.cmake with Robocopy implementation.
2026-03-05 14:30:22 +07:00
Alezito2008andGitHub 053eb0119c Fix F3 opening host menu (#522)
* Fix debug menu opening game info menu

* remove redundant F4 handling
2026-03-05 14:26:19 +07:00
ModMaker101andGitHub 91e50aa346 Fix animals stuck in panic state #514 (#519) 2026-03-05 14:23:56 +07:00
Siobhan 🏳️‍⚧️andGitHub 981c87732c Restore the original follow range for Zombies and Withers (#510)
* Restore original follow range for Zombie

* Restore original WitherBoss follow range
2026-03-05 14:22:31 +07:00
Alezito2008andGitHub 87e3bd193c Fix beacon crash (#512) 2026-03-05 14:17:17 +07:00
SkeagleandGitHub 8cdbf08900 fix creeper model y offset (#504) 2026-03-05 14:16:18 +07:00
qwasdrizzelandGitHub 9370cbc7d8 Modify dispense behavior to set outcome as LEFT_ITEM 2026-03-05 00:02:17 -06:00
qwasdrizzelandGitHub ee83ec8df9 Modify dispense behavior to set outcome as LEFT_ITEM 2026-03-05 00:02:17 -06:00
LokiandGitHub f1d477c1ec Merge pull request #523 from kuwacom/main
Fix crash when launching at 720p
2026-03-04 20:18:05 -06:00
kuwacom 26582a7439 fix: Fixed crash when launching at 720p #517
Modify `MediaWindows64.arc` to include `skinHud.swf`
2026-03-05 11:13:31 +09:00
LokiandGitHub 9383b2aa01 Merge pull request #491 from siobhan-saoirse/main
Decrease the mob ticks from 3 to 1 to reduce jittering
2026-03-04 16:25:57 -06:00
Siobhan 🏳️‍⚧️andGitHub 4f85afe325 Adjust entity tracking ticks for several types
This fixes the jittery problem.
2026-03-04 17:19:05 -05:00
Loki Rautio cb9ab4ef51 Ship revised logo from @wiskerdmage
This one looks a bit nicer so let's use this for now...
2026-03-04 15:23:12 -06:00
Loki Rautio 391dd3caae Ship updated, maybe temporary subtitle
People keep going "Oh no I don't like the red WINDOWS text, oh no! I hate it!
The red windows text is the devil, it will be my undoing! Please remove the red
windows text or I shall simply perish!" And for that? Well, I have removed it. Now
you can enjoy this logo made by @wiskerdmage in the style of the existing Edition
logos. (https://github.com/smartcmd/MinecraftConsoles/pull/385#issuecomment-3996671081)
2026-03-04 14:56:53 -06:00
MarlianandGitHub 3f1388e06f Persist fullscreen setting and start windowed mode maximized (#446)
Save fullscreen toggle state to options.txt when F11 is pressed, and restore it on the next launch. When starting in windowed mode, the window now opens maximized instead of at a smaller default size.

Previously, g_isFullscreen was hardcoded to false and never persisted, so the game always started in windowed mode. The window also started at a non-maximized size requiring manual maximization.

Fixes #391
2026-03-05 03:50:06 +07:00
LetsGoAwayandGitHub c517f31b3d Update ItemInHandRenderer.cpp (#418) 2026-03-05 03:26:56 +07:00
Loki Rautio 51eb86ad28 Revert "fix: fix #464"
This reverts commit 5922824950.
2026-03-04 13:43:40 -06:00
Fayaz ShaikhandGitHub 9372887aef Fix for any aspect ratio in 3D Environments (#320)
* Add initial AnyAspectRatio support

* Remove some logic that didn't work

* Remove rogue back slash

* Remove more remnants

* Update UILayer.h

* Update some comments

* Remove WIP UI changes

* Fix diffs

* Remove UI resize call from `UpdateAspectRatio`

* handle merge conflict

* Update to C++ style static cast

* Fix syntax
2026-03-05 02:13:58 +07:00
daoge_cmd 5922824950 fix: fix #464 2026-03-05 02:57:52 +08:00
daoge_cmd 4108ed142b fix: restore KBM sprint on either Ctrl key 2026-03-05 01:49:38 +08:00
daoge_cmd 7b35df8714 Fix controller paging regression in creative menu
Preserve smooth row-by-row scrolling for mouse wheel input, but restore
full-page movement for controller/menu scroll actions in the creative
inventory.

Commit 3093ca3 changed page indexing to support smooth scrolling, which
caused ACTION_MENU_OTHER_STICK_UP/DOWN to advance by one row instead of
one page. Track whether the scroll action originated from the mouse
wheel and only use single-row steps in that case.

Fixes #253
2026-03-05 01:38:34 +08:00
daoge_cmd ef66f6736d fix: ignore dedicated server properties in normal world startup 2026-03-05 01:26:21 +08:00
ModMaker101andGitHub 870d3e4b68 Fix mob nametag position to match correct height offset #422 (#440) 2026-03-05 00:24:42 +07:00
daoge_cmd 1dc8a005ed refactor: refactor KBM input code 2026-03-05 01:12:48 +08:00
Alezito2008andGitHub ac03b88a90 Fix:Prevent horse spawner crash (#433) 2026-03-04 23:42:32 +07:00
ModMaker101andGitHub 206c6800f2 Fix incorrect distance comparison return value (#432) 2026-03-04 23:41:59 +07:00
ModMaker101andGitHub 464cf91f4c Prevent door sounds from playing twice #392 (#425) 2026-03-04 23:28:37 +07:00
Alezito2008andGitHub cea1084978 Fix duplicated stained glass when art tools enabled (#426) 2026-03-04 23:28:20 +07:00
ModMaker101andGitHub 2be856a2d4 Fix Chunk destructor segfault using smart pointers #112 (#414) 2026-03-04 22:43:29 +07:00
Davi Eler MagalhãesandGitHub ca5fde56fe Fix: Sorted the item list in the debug overlay (#340)
* Fix: Sorted the item list in the debug overlay

* revert show all files to false

* Revert ShowAllFiles by removing it

* removed extra line

* Adressed PR review changes

* Replaced push_back with emplace_back

* Removed redundant emplace_back
2026-03-04 22:07:37 +07:00
MarlianandGitHub 2d430798a5 Fix creative inventory crash with Art Tools debug option (#399)
Fix vector out-of-bounds crash when scrolling the potions tab in the creative inventory with Art Tools debug enabled.

- Fix getPageCount() returning total rows instead of scrollable pages in Art Tools mode

- Fix off-by-one boundary check in populateMenu() for both static and debug group loops (< should be <=)

Fixes #386
2026-03-04 19:47:43 +07:00
Loki Rautio 52d9bcc9a9 Enable Stained Glass in Creative Menu 2026-03-04 06:14:06 -06:00
Loki Rautio 0e9d8629f1 Update README with info about username.txt 2026-03-04 05:59:48 -06:00
Loki Rautio ea17b152b7 Restore username.txt loading without conflict
Still allows for -name launch argument, but restores old expected behavior
2026-03-04 05:57:56 -06:00
Loki Rautio 0993e628ab Disable automatic Windows account username
This could reveal someone's private information on a livestream or video.
We need a long-term username implementation
2026-03-04 05:44:16 -06:00
LokiandGitHub e6950a91d9 Merge pull request #201 from dtentiion/pr/win64-world-saves
Show actual world names in save list, sorting, preserve level and its name on load/resave
2026-03-04 04:06:51 -06:00
Loki Rautio 42aec6dac5 Merge branch 'main' into pr/win64-world-saves
# Conflicts:
#	Minecraft.Client/MinecraftServer.cpp
#	README.md
2026-03-04 03:56:03 -06:00
daoge_cmd ef9b6fd500 docs: fix table formatting in README.md 2026-03-04 17:48:19 +08:00
daoge_cmd 5d9f6f6347 docs: mark V-Sync note as WIP in README.md 2026-03-04 17:47:16 +08:00
daoge_cmd d112090fde feat: headless server 2026-03-04 17:29:43 +08:00
daoge_cmd 8ecfc52547 feat: add support for username, IP, and port configuration via launch arguments 2026-03-04 15:33:52 +08:00
daoge_cmd 575cc4ce6e fix: fix horse texture rendering 2026-03-04 14:55:13 +08:00
daoge_cmd b1b4435c01 fix: fix inverted pitch in the second third person view 2026-03-04 14:40:52 +08:00
dtentiionandGitHub c9d58eeac7 Delete README.md
Unnecessary
2026-03-04 06:05:24 +00:00
Tygo de VriesandGitHub 779cf56f4b Removed private information (#333)
Maybe we should not have this out there to find so easily?
2026-03-04 12:39:16 +07:00
ModMaker101andGitHub bfcc4aa10c renderer: frustum test new chunks so newly generated chunks render to full view distance #175 (#344) 2026-03-04 12:37:04 +07:00
Alezito2008andGitHub 6c842b2854 Disable flight state when riding entities (#368) 2026-03-04 13:21:21 +08:00
MykeyandGitHub c8a8f9dd6c Update crafting controls description (#359)
Clarified crafting controls in README.
2026-03-04 12:32:51 +08:00
rtm516andGitHub b1b622c303 Fix overlapping debug menus and screens (#294)
* Fix overlapping debug menus and screens

Also resolves a formatting issue with clang-format

* Update readme
2026-03-04 12:31:47 +08:00
4winandGitHub f216abca42 fix: properly offset the mouse position in containers (#327) 2026-03-04 12:30:14 +08:00
Alezito2008andGitHub d31d261ffd Prevent world input from affecting inventory (#354) 2026-03-04 12:29:29 +08:00
ZekkenandGitHub f870ef2a10 Fix Texture Pack images in menu (#335) 2026-03-03 23:56:16 +00:00
Boom244andGitHub ac30f09085 #221: Fix menu glitch. (#254) 2026-03-04 05:43:06 +07:00
SlendermanandGitHub ac480f6745 Update username logic and implement latest LCEMP changes (#311)
* Update username logic and implement latest LCEMP changes

* Update old reference

* Fix tutorial world crash

* Restore deleted comment
2026-03-04 04:50:28 +07:00
FinandGitHub 30ecc80250 Add menu display check for sneak toggle in flying mode (#319)
Fixes being able to fly down while a menu is open.
2026-03-04 04:13:35 +07:00
rtm516andGitHub 384b9f4445 Fix ender dragon hit not making left side red (#309) 2026-03-04 03:40:53 +07:00
TGSandGitHub 31cc598b75 Remove duplicate elif from LevelRender.h (#296) 2026-03-03 20:22:31 +00:00
rtm516 9b5348113c Don't build when PR template is updated 2026-03-03 18:20:14 +00:00
rtm516 942ef7e99f Tidy up PR template 2026-03-03 18:17:33 +00:00
FancyEXandGitHub 540e33d787 Separate _WINDOWS64 and _XBOX_ONE (#248)
The latter returning to the original 512 value.
2026-03-04 00:58:04 +07:00
DetectivErenandGitHub 1b0e5df27e chunk optimization (#246)
makes chunks load a bit faster
2026-03-04 00:55:27 +07:00
SlendermanandGitHub 515f91cad8 Fix player save data issue & multiple username implementations (#257)
* fix saving issue & multiple username implementations

* Update README.md

Updated the method for overriding in-game username from '-name' to 'username.txt'.

* remove unused include i forgot to get rid of while testing
2026-03-03 23:58:22 +07:00
slcyedandGitHub 5c91c26086 shift + click for quickmove (#278)
* shift + click for quickmove

* shift click quick move in inventory
2026-03-03 23:27:23 +07:00
void_17andGitHub b44d29b2ff Ship the .pdb file in nightly builds too 2026-03-03 23:18:57 +07:00
void_17andGitHub a3095a7050 Ship updated binary alongside with the whole archive in nightly builds
Now ship both the entire .zip archive and the separate .exe binary updated on each commit.
2026-03-03 23:07:37 +07:00
VioletandGitHub 42bb19d490 chore: add .clang-format based on the style 4J seemed to use (#30) (#273)
The style 4J used seems to be based on the Microsoft style (presumably the
default settings of whatever Visual Studio they used to write this). However,
the source files do not have much consistency so I highly doubt 4J cared too
much about styling, just going with whatever happened to be the default.

This style is therefore basically the Microsoft style (4-space indents,
C#/Allman style braces) with some settings set based on my observations
about the code.

Fixes: #30
2026-03-03 22:53:28 +07:00
daoge_cmd 1444581cb6 chore: remove duplicated /Ob3 flag from CMake Release optimization settings 2026-03-03 17:59:06 +08:00
daoge_cmd a97ee4aab1 chore: sync VS Release warning-disable setting into CMake 2026-03-03 17:45:25 +08:00
daoge_cmd 2915044f95 chore: sync VS release optimization flags into CMake build 2026-03-03 17:40:21 +08:00
daoge_cmd 6d4ce5136c fix: fix executable icon when using cmake 2026-03-03 17:40:21 +08:00
4winandGitHub ca7615d77d feat: make the game sensitivity slider affect mouse sensitivity (#255) 2026-03-03 15:13:20 +08:00
Loki Rautio cd03a390b7 Move Tutorial.pck to the correct Dec2014 location
Fixes #190
2026-03-03 00:07:31 -06:00
void_17andGitHub c1ec83aedc Add nightly.yml release description
Compiler information mostly
2026-03-03 12:59:47 +07:00
Loki Rautio 8f17df6351 Disable blank changelog popup for now
Partially addresses issue in #190
2026-03-02 23:46:39 -06:00
4winandGitHub 7ce1fa3452 feat: bind F1 to toggle the HUD settings (#244) 2026-03-03 13:32:26 +08:00
Loki Rautio fad108aaee Use Xbox One command buffer limit - fixes #238 2026-03-02 23:27:20 -06:00
void_17andGitHub 3093ca37d3 Implement smooth scrolling in Creative Mode menu (#240) 2026-03-03 13:21:41 +08:00
Loki Rautio af5d62a81e Add back missing filters 2026-03-02 23:19:29 -06:00
Loki Rautio 354a0989eb Add back x64 stub XUID (temp savedata fix)
Fixes savedata loading for existing saves, needs permanent solution
2026-03-02 23:05:25 -06:00
void_17andGitHub b42a4a4e4d Revert "Revert "Win64: configurable username (username.txt) and persistent ga…" (#235)
This reverts commit 7f7d99501c.
2026-03-03 10:31:09 +07:00
void_17andGitHub 7f7d99501c Revert "Win64: configurable username (username.txt) and persistent game setti…" (#234)
This reverts commit b8a7f816b5.
2026-03-03 10:23:28 +07:00
daoge_cmd 77a161e813 docs: update Discord invite link in README.md 2026-03-03 11:23:15 +08:00
Fayaz ShaikhandGitHub 0b1e51f620 Cleaner implementation of support dynamic resizing aspect ratio (#228)
* Add dynamic resolution

* Clean up implementation

* Use existing ints instead of new ones

* Remove WM_SIZE argument (unecessary now that we directly use g_iScreenWidth and g_iScreenHeight)
2026-03-03 10:11:16 +07:00
void_17 acf4a38555 Enable more aggressive optimizations /O2 /Ob3 2026-03-03 09:45:52 +07:00
void_17 d7882b68a4 Fix crash on item frame destruction 2026-03-03 09:27:28 +07:00
MijaeLioandGitHub 17a11d7913 FOV option without debug menu (#209)
Now located in Graphics section.

Based on the FOV thing from discord idk
2026-03-03 09:02:25 +07:00
void_17 ccebb87ca7 Enable Whole Program Optimization in Release mode
This noticeably improves FPS
2026-03-03 08:54:08 +07:00
void_17 a5e3cb04b3 Remove #203 core code before a cleaner implementation 2026-03-03 08:45:26 +07:00
void_17 95d4d0a703 Temporarily turn off all MSVC warnings
Before any major refactoring, warnings do help a little except for slowing down the compilation (as it needs to output everything to stdout), so disable MSVC warnings in Release mode.
2026-03-03 07:10:55 +07:00
GuglioIsStupidandGitHub 3dce71ef32 Copy assets fix (#207)
* Update CopyAssets to ignore source files and only copy used files.

* Forgot the debug copy assets

* Remove leftovers from testing

* Fix ClientSources.cmake to include WinsockNetLayer.cpp

* Ignore xml and lang files in output, also remove Layout directory as it only includes a useless binary

* Debug & Release use the same file structure
2026-03-03 07:04:36 +07:00
void_17 dea460381f Remove dyn_SetProcessDpiAwareness 2026-03-03 07:00:55 +07:00
daoge_cmd 52a954e06e docs: simplify LAN multiplayer section in README.md 2026-03-03 07:56:23 +08:00
daoge_cmd 24da81a1ca docs: add LAN multiplayer details to README.md 2026-03-03 07:51:20 +08:00
dtentiionandGitHub b8a7f816b5 Win64: configurable username (username.txt) and persistent game settings (settings.dat) (#195) 2026-03-03 07:50:45 +08:00
8b28c20d7a Fixes for PR #96 (#170)
* Implement basic multiplayer functionality

* Update README.md

---------

Co-authored-by: Slenderman <ssimulpong@outlook.com>
2026-03-03 06:30:22 +07:00
St4lker0k765andGitHub 15129932da Add saves folder to .gitignore (#184) 2026-03-03 06:26:20 +07:00
DetectivErenandGitHub f731a68422 TAB key opens up game info instead of host options (#204)
* TAB key opens up game info instead of host options

TAB key opens up game info menu instead of host options menu because the player accesses host options from game info

* Update README.md
2026-03-03 06:23:59 +07:00
void_17andGitHub e888735798 Revert "Fix sound not working" (#205) 2026-03-03 06:22:43 +07:00
daogeandGitHub 7eb4c78488 fix: fix gamma (#191) 2026-03-03 06:20:55 +07:00
void_17 13c8bafad5 Minor fixes
1. Improve const correctness in a few places (such as `Container::getMaxStackSize()` -> `Container::getMaxStackSize() const`)

2. Use C++11 varargs for `I18n::get`, `Entity::newDoubleList` and `Language::getElement`
2026-03-03 06:14:34 +07:00
Fayaz ShaikhandGitHub 41ded31af8 Add dynamic resolution (#203) 2026-03-03 06:04:53 +07:00
Twig6943andGitHub 2189da6f92 Make ci skip on non important stuff - give tutorial image a name (#202) 2026-03-03 06:01:00 +07:00
dtentiionandGitHub 2d6a62a0e0 Refactor README for consistent formatting
Updated formatting for clarity and consistency in the README.
2026-03-02 23:00:42 +00:00
daoge_cmd fd6350b7f9 docs: update version reference in README.md 2026-03-03 05:49:21 +08:00
daoge_cmd 1fbc2d1eb8 docs: clarify platform support and building requirements in README.md and COMPILE.md 2026-03-03 05:43:32 +08:00
daoge_cmd e53d41d333 docs: fix typo in README.md 2026-03-03 05:24:34 +08:00
dtentiion 63e590d783 Win64: show actual world names in save list, sort newest-first, preserve level name on load/resave 2026-03-02 21:13:11 +00:00
daoge_cmd 8f6647b5d8 fix: fix mouse and controller input handling in container menus 2026-03-03 04:59:08 +08:00
AndrewandGitHub f917335b13 Fix Windows64 mouse capture and static initialization crashes (#177) 2026-03-03 03:17:10 +07:00
bbef5445f9 Add ARM64EC Support (#174)
Co-authored-by: Tubbymcwubby <maneggioausten@gmail.com>
2026-03-03 03:06:21 +07:00
daoge_cmd b08493cdac fix: fix cursor for controller 2026-03-03 04:02:35 +08:00
void_17 796a743b75 remove dynamic shcore dependency
Almost forgot it. https://github.com/smartcmd/MinecraftConsoles/pull/160
2026-03-03 02:19:57 +07:00
void_17andGitHub 5a9e512117 Restore Windows 7 compatibility (#160)
* Call SetProcessDpiAwareness via GetProcAddress to preserve Windows 7 compatibility

Shcore.dll and SetProcessDpiAwareness were introduced in Windows 8 and higher, so to keep compatibility with Windows 7, we use GetProcAddress to call this function dynamically, avoiding linker writing binary dependency on shcore.dll in the import table

* Revert "Call SetProcessDpiAwareness via GetProcAddress to preserve Windows 7 compatibility"

This reverts commit f1f397fdbe64e64ab8f7b5457e8206e9193cece0.

* Reapply the fix
2026-03-03 03:20:24 +08:00
daoge bdc8fb5dfa docs: update README.md 2026-03-03 03:10:29 +08:00
b3feddfef3 feat: TU19 (Dec 2014) Features & Content (#155)
* try to resolve merge conflict

* feat: TU19 (Dec 2014) Features & Content (#32)

* December 2014 files

* Working release build

* Fix compilation issues

* Add sound to Windows64Media

* Add DLC content and force Tutorial DLC

* Revert "Add DLC content and force Tutorial DLC"

This reverts commit 97a43994725008e35fceb984d5549df9c8cea470.

* Disable broken light packing

* Disable breakpoint during DLC texture map load

Allows DLC loading but the DLC textures are still broken

* Fix post build not working

* ...

* fix vs2022 build

* fix cmake build

---------

Co-authored-by: Loki <lokirautio@gmail.com>
2026-03-03 03:04:10 +08:00
void_17 84c31a2331 Also remove clicking sound effect on empty container UI slots for rclick and middle mouse button click
Tested by me so no PR and just push upstream
2026-03-03 02:01:12 +07:00
void_17andGitHub 53443f1d55 Disable annoying click sound effect when clicking the empty container UI (#152) 2026-03-03 00:41:01 +07:00
852b9aac50 Allow for loading of WAVE Audio files (#148)
* Allow for loading of WAVE Audio files

* Remove usage of strcpy and use _s versions of file opening

* Update SoundEngine.cpp

---------

Co-authored-by: void_17 <61356189+void2012@users.noreply.github.com>
2026-03-03 00:27:32 +07:00
ZincandGitHub fe65211d42 Change flight activation/deactivation requirements (#145) 2026-03-03 00:21:55 +07:00
daoge_cmd bbb199c2a2 feat(timer): improve high-FPS timing with high-resolution Windows clock 2026-03-03 00:31:47 +08:00
AlexandGitHub a4691f58e8 Only handle host options when there is no menu on screen (#140) 2026-03-02 23:02:52 +07:00
void_17andGitHub 7ad6102763 Revert "Revert "fix: fix resolution detection (#133)" (#143)" (#144)
This reverts commit 8c18926d59.
2026-03-02 23:01:57 +07:00
daoge_cmd 5c3040affe docs: update README.md 2026-03-03 00:01:15 +08:00
void_17andGitHub 8c18926d59 Revert "fix: fix resolution detection (#133)" (#143)
This reverts commit afa4efbc85.
2026-03-02 22:56:56 +07:00
daogeandGitHub afa4efbc85 fix: fix resolution detection (#133)
* fix: fix UI skin/scene resolution mismatch and readd screen resolution detection

* fix: fix build in vs2022
2026-03-02 23:52:18 +08:00
2145ada7ce now able to press SPACE to continue on hints that wait for you to press A (#135)
* now possible to accept and decline tutorial hints

that part when it asks if you want to do the tutorial (should work for when the games asks if you already know something like when opening inventories for the first time)

* Update ChoiceTask.cpp

* now able to press SPACE to continue on hints that wait for you to press A

and the hints what wait for you to move the gamepad stick now just skip instantly

* windows specific patch now

* added ifdefs to shit i did

* i think it is fixed now

---------

Co-authored-by: daoge <3523206925@qq.com>
2026-03-02 22:47:45 +07:00
void_17andGitHub 320550b30b Add download link to README.md
For newbies
2026-03-02 20:37:20 +07:00
JeanandGitHub 59339a7afc Bound F3 and F4 to open debug menus (#94)
* feat: Added f3 and f4 keys to open debug stuff

* fix: only open debug overlay when ingame, to avoid crashes

* docs: added keybinds to docs

* docs: moved the keybinds to the bottom, as they are less important

* fix: add missing # ifdef
2026-03-02 20:00:02 +07:00
void_17andGitHub 73ceca7fc2 Fix typo in pull_request_template.md 2026-03-02 19:43:22 +07:00
void_17andGitHub 40953f857e Update pull_request_template.md 2026-03-02 19:41:30 +07:00
DFelipehandGitHub f9b266e02c add minecraft icon to windows version (#126) 2026-03-02 19:03:40 +07:00
DFelipehandGitHub bab9b563de fix being able to walk, jump and sneak on inventory, crafting, anvil, chest screens (#122) 2026-03-02 17:51:06 +07:00
void_17 82c4a50ba0 Merge branch 'main' of https://github.com/smartcmd/MinecraftConsoles 2026-03-02 17:40:01 +07:00
6d9d43c9e9 Remove duplicate input support mention (#121)
* Remove duplicate input support mention

Removed duplicate mention of keyboard and mouse input support.

* Remove DPI awareness line in README

---------

Co-authored-by: void_17 <61356189+void2012@users.noreply.github.com>
2026-03-02 17:41:28 +07:00
void_17 b9a2951901 Revert "Get rid of MSVC's __int64"
This reverts commit d63f79325f.
2026-03-02 17:39:35 +07:00
void_17 119bff3514 Revert "shared_ptr -> std::shared_ptr"
This reverts commit 7074f35e4b.
2026-03-02 17:37:16 +07:00
void_17 8a2a62ea1d Revert "Add hook for modloader (#117)"
This reverts commit 7bee4770df.
2026-03-02 17:37:12 +07:00
void_17 7ae0c13854 Revert "dynamic_pointer_cast -> std::dynamic_pointer_cast"
This reverts commit 07ad68bc15.
2026-03-02 17:36:56 +07:00
void_17 07ad68bc15 dynamic_pointer_cast -> std::dynamic_pointer_cast 2026-03-02 17:10:34 +07:00
Daniel McGuireandGitHub 7bee4770df Add hook for modloader (#117) 2026-03-02 16:12:49 +07:00
void_17 7074f35e4b shared_ptr -> std::shared_ptr
This is one of the first commits in a plan to remove all `using namespace std;` lines in the entire codebase as it is considered anti-pattern today.
2026-03-02 15:58:20 +07:00
void_17 d63f79325f Get rid of MSVC's __int64
Use either int64_t, uint64_t or long long and unsigned long long, defined as per C++11 standard
2026-03-02 15:53:32 +07:00
KarsamandGitHub d6ec138710 Fixed issue 109 with tab menu (#116) 2026-03-02 15:28:30 +07:00
rtm516andGitHub e15bd26917 Move to a postbuild.ps1 script and set the working dir at runtime as output dir (#113)
* Move to a postbuild.ps1 script and Set the working dir at runtime as output dir

* Update for 2f711d4

* Only copy newer files and remove needed files from gitignore
2026-03-02 15:14:14 +07:00
void_17 09e0c04f7b Further C-style struct definitions fixes 2026-03-02 15:11:05 +07:00
void_17 def238ff08 Fix C-style struct functor definitions 2026-03-02 14:51:05 +07:00
void_17andGitHub dea1d62074 Revert "Move to a postbuild.ps1 script and Set the working dir at runtime as …" (#111)
This reverts commit 8810566bf6.
2026-03-02 14:13:12 +07:00
rtm516andGitHub 8810566bf6 Move to a postbuild.ps1 script and Set the working dir at runtime as output dir (#91) 2026-03-02 14:05:46 +07:00
void_17andGitHub 7eac79acc3 Merge pull request #78 from WushR00M/patch-2
Optimize file paths in some include files to use relative paths
2026-03-02 14:02:09 +07:00
void_17andGitHub 3033ba58ad Merge pull request #93 from SleepyLark/fix-sound
Fix sound not working
2026-03-02 13:44:29 +07:00
void_17 df2925a4ed Fix Iggy player crashes on systems with DPI changed
The code that was supposed to make the game DPI-aware was broken. I remove it until a proper implementation.
2026-03-02 13:32:41 +07:00
void_17andGitHub 3680090ff9 Merge pull request #108 from smartcmd/revert-99-fix/q-drop
Revert "Implement item drop functionality with Q key"
2026-03-02 13:24:46 +07:00
void_17andGitHub 236e9d9f71 Revert "Implement item drop functionality with Q key (#99)"
This reverts commit 9e5d9d19ee.
2026-03-02 13:24:19 +07:00
MrSimpleJSandGitHub 9e5d9d19ee Implement item drop functionality with Q key (#99)
Added functionality to drop items using the Q key, with support for dropping entire stacks when Ctrl is held. Included checks to prevent dropping items while destroying blocks.
2026-03-02 13:43:51 +08:00
rtm516andGitHub 109f563daa Fixes the exit button sound (#92) 2026-03-02 13:41:40 +08:00
fa4a1206b3 feat: now can skip the tutorial (#82)
* now possible to accept and decline tutorial hints

that part when it asks if you want to do the tutorial (should work for when the games asks if you already know something like when opening inventories for the first time)

* Update ChoiceTask.cpp

---------

Co-authored-by: daoge <3523206925@qq.com>
2026-03-02 13:40:04 +08:00
VvisandGitHub 75bf7ee54a Allow TAB to open host options (#97) 2026-03-02 13:33:18 +08:00
Skylark 2f711d4c22 Actually moved sound to "Windows64" so commit 9691561 works
Copy sound folder in "Durango" to "Windows64" rather than to media since it looks like that folder is mainly for the DLC content
2026-03-01 16:52:27 -07:00
void_17andGitHub 5b5b9f6072 Merge pull request #84 from Firebladedoge229/main
Create Manual Workflow for LCE Artifact Creation
2026-03-02 06:21:28 +07:00
void_17andGitHub 1d9eb31a69 Merge pull request #85 from BetaZay/main
Add optional CMake build support for Windows x64, runtime asset/DLL copy, and unified compile docs
2026-03-02 06:15:29 +07:00
isaiah 661caf704a Merge branch 'main' of https://github.com/BetaZay/MinecraftConsoles 2026-03-01 15:47:56 -07:00
isaiah 9a85a1cd07 Add functions to ensure directory creation and copy legacy redistributables 2026-03-01 15:47:31 -07:00
isaiah 6cbdc8ac9b Update Visual Studio version in compile instructions to 2022 2026-03-01 15:47:31 -07:00
isaiah 5109b8c07a Add CMake build system and source files for Minecraft Client
- Created Compile.md with detailed instructions for building the project using Visual Studio and CMake.
- Added ClientSources.cmake to define the source files for the Minecraft Client.
- Implemented CopyAssets.cmake to handle asset copying during the build process.
- Introduced WorldSources.cmake to list the source files for Minecraft world functionalities.
2026-03-01 15:47:31 -07:00
isaiah aa8f16631f Add functions to ensure directory creation and copy legacy redistributables 2026-03-01 15:46:25 -07:00
FirebladeandGitHub b2381555b2 Merge branch 'smartcmd:main' into main 2026-03-01 17:41:09 -05:00
isaiah 706e9665bb Update Visual Studio version in compile instructions to 2022 2026-03-01 15:26:34 -07:00
void_17andGitHub 4576e46e7f Merge pull request #62 from omrih4/main
Add nightly release github action
2026-03-02 05:25:43 +07:00
isaiah a0edf193fe Add CMake build system and source files for Minecraft Client
- Created Compile.md with detailed instructions for building the project using Visual Studio and CMake.
- Added ClientSources.cmake to define the source files for the Minecraft Client.
- Implemented CopyAssets.cmake to handle asset copying during the build process.
- Introduced WorldSources.cmake to list the source files for Minecraft world functionalities.
2026-03-01 15:16:04 -07:00
WushR00MandGitHub 4f184b3a8f More relative path optimizations 2026-03-01 15:09:45 -07:00
WushR00MandGitHub 30f895527d Optimized File Paths
Wow, this code is not the best :P
2026-03-01 15:08:51 -07:00
FirebladeandGitHub cd34348db5 create workflow for minecraft legacy console edition compilation 2026-03-01 17:07:52 -05:00
WushR00MandGitHub 50bea25064 Optimize TutorialMode.h Filepath in ConsoleGameMode.h 2026-03-01 15:06:42 -07:00
WushR00MandGitHub 7e96fc7c3f Optimize Path for Tutorial.h in ConsoleGameMode.cpp 2026-03-01 15:05:24 -07:00
OmriandGitHub 0d33cfbdbc Merge branch 'smartcmd:main' into main 2026-03-02 00:00:08 +02:00
void_17andGitHub 071d4f6599 Merge pull request #77 from WushR00M/main
Move "img.png" to seperate directory to reduce root directory clutter
2026-03-02 04:45:47 +07:00
WushR00MandGitHub 08b81c34fb Update image path in README.md 2026-03-01 14:18:16 -07:00
WushR00MandGitHub a4dd1c4bc7 Add files via upload 2026-03-01 14:08:52 -07:00
WushR00MandGitHub e11f15b729 Move img.png to .github to reduce root directory clutter 2026-03-01 14:08:27 -07:00
void_17andGitHub 0d09ffe389 Merge pull request #67 from smartcmd/revert-41-main
Revert "Added bug, and feature template for issues"
2026-03-02 03:53:07 +07:00
void_17andGitHub 180ad193ee Revert "Added bug, and feature template for issues" 2026-03-02 03:52:55 +07:00
void_17andGitHub a3f3717e1e Merge pull request #64 from simulpingus/main
Update Build Events to work more consistently
2026-03-02 03:51:36 +07:00
SlendermanandGitHub 82fbda28f1 Merge branch 'smartcmd:main' into main 2026-03-01 15:46:03 -05:00
void_17andGitHub 286e06972b Merge pull request #63 from smartcmd/revert-59-dlc-sounds
Revert "Add missing DLC and Sounds to Windows64Media"
2026-03-02 03:44:38 +07:00
void_17andGitHub b0facaeb9c Revert "Add missing DLC and Sounds to Windows64Media" 2026-03-02 03:44:23 +07:00
void_17andGitHub daca9c5707 Merge pull request #59 from codeHusky/dlc-sounds
Add missing DLC and Sounds to Windows64Media
2026-03-02 03:37:48 +07:00
Omri H 34d398cf1b dumbass 2026-03-01 22:34:48 +02:00
Loki Rautio 1f90b1ab44 Add missing DLC and Sounds to Windows64Media 2026-03-01 14:32:42 -06:00
void_17andGitHub 4d5cc71ccf Merge pull request #57 from NEVARLeVrai/main
Add double-tap sprint and mouse toggle
2026-03-02 03:30:46 +07:00
Omri H 7bed2fb0e9 use working action for release 2026-03-01 22:29:31 +02:00
NΞVΛR e31d31f018 Add double-tap sprint and mouse toggle
Update controls in README: expand Sprint entry to include "Double-tap W" as an alternative to holding Ctrl, and add a new "Toggle Mouse Capture" binding (Left Alt) for debugging. Documentation-only change to clarify input options.
2026-03-01 21:29:10 +01:00
SlendermanandGitHub 213e3180c2 Merge branch 'smartcmd:main' into main 2026-03-01 15:22:29 -05:00
void_17andGitHub a0da2512ea Merge pull request #47 from KdotDevelopment/main
Crafting menu LB RB KBM fix
2026-03-02 03:21:48 +07:00
Omri H 465be08bbf update nightly release 2026-03-01 22:21:18 +02:00
SlendermanandGitHub 91f0f0e3cc Merge branch 'smartcmd:main' into main 2026-03-01 15:14:10 -05:00
Omri H 99ddc06eb8 fix target 2026-03-01 22:13:05 +02:00
Slenderman 55a86b8dc3 fix my idiocrisy 2026-03-01 15:12:52 -05:00
void_17andGitHub a2cf02cc38 Merge pull request #49 from izanthebestn1/increase-rendertarget-limit
Increase GDRAW_D3D11_RESOURCE_rendertarget limit from 32 MB to 64 MB (or more) …
2026-03-02 03:11:38 +07:00
void_17andGitHub 6825d2ed52 Merge pull request #48 from simulpingus/main
Fix saves
2026-03-02 03:10:50 +07:00
Omri H 44aafd7d53 fix target 2026-03-01 22:08:37 +02:00
SlendermanandGitHub e7e32a5cd6 Merge branch 'smartcmd:main' into main 2026-03-01 15:07:15 -05:00
Slenderman 4b7a97f904 Update Minecraft.Client.vcxproj 2026-03-01 15:06:39 -05:00
Omri H 2c7803a2cf setup msbuild 2026-03-01 22:05:29 +02:00
Omri H 904f19b74c fix workflow 2026-03-01 22:03:47 +02:00
void_17andGitHub f580a6a603 Remove the word template from PR template
Looks like people don't change this field so the word `template` is not needed here.
2026-03-02 03:02:18 +07:00
Omri H 7378cbdc02 feat: build workflow 2026-03-01 22:02:02 +02:00
void_17andGitHub 1b6b973054 Merge pull request #41 from NEVARLeVrai/main
Added bug, and feature template for issues
2026-03-02 03:00:55 +07:00
Izan d1e8418a77 Increase GDRAW_D3D11_RESOURCE_rendertarget limit from 32 MB to 64 MB to prevent allocation warnings at high resolutions 2026-03-01 21:00:40 +01:00
NΞVΛRandGitHub c48120dd35 Remove heart emoji from feature request template 2026-03-01 20:55:00 +01:00
NΞVΛRandGitHub dc1e90fdc0 Removed emoji from feature request name for consistency. 2026-03-01 20:54:42 +01:00
NΞVΛRandGitHub 47924e86fd Rename bug report template to remove emoji 2026-03-01 20:54:18 +01:00
Ryan K 8048c793ed Crafting menu LB RB KBM fix 2026-03-01 14:54:15 -05:00
void_17andGitHub 5037420311 Merge pull request #45 from simulpingus/main
Remove need for Durango folder, properly use Windows64Media, and add all DLC content
2026-03-02 02:40:01 +07:00
void_17andGitHub 9382049029 Merge pull request #44 from rtm516/cleanup/ignore
Remove GameHDD save data and update .gitignore
2026-03-02 02:37:10 +07:00
Slenderman 9691561693 Remove need for Durango folder 2026-03-01 14:33:30 -05:00
rtm516 8c79598b01 Remove GameHDD save data and update .gitignore 2026-03-01 19:32:26 +00:00
void_17andGitHub b06177599c Merge pull request #43 from Foxify52/main
Increased max available memory beyond 512 mb for Xbox One/Windows build
2026-03-02 02:28:04 +07:00
void_17andGitHub d76650f333 Merge pull request #42 from simulpingus/main
fix my cast and put it into a separate function
2026-03-02 02:24:29 +07:00
Slenderman a2bcce6426 fix my cast and put it into a separate function 2026-03-01 14:22:01 -05:00
NΞVΛR 15e952d4cb added config for issues 2026-03-01 20:20:20 +01:00
Chris c1aebee5b9 Merge branch 'main' of https://github.com/Foxify52/MinecraftConsoles 2026-03-01 14:18:00 -05:00
Chris 5484b78eca Adjusted max memory usage for renderer 2026-03-01 14:17:45 -05:00
void_17andGitHub 38b442b1e3 Merge pull request #37 from simulpingus/main
Unlock DLC, fix world names in load menu, fix dlc pack titles
2026-03-02 02:15:04 +07:00
Slenderman 6080c4ceac use C++ style cast instead of C-style cast 2026-03-01 14:12:39 -05:00
NΞVΛR c23dc98b67 added bug report template 2026-03-01 20:10:49 +01:00
NΞVΛR cde94faefa added feature request template 2026-03-01 20:07:49 +01:00
void_17andGitHub f5ebb5bfff Merge pull request #38 from NEVARLeVrai/main
added Controls info (Keyboard & Mouse) to readme
2026-03-02 01:55:17 +07:00
void_17andGitHub 6850c3b42c Create pull_request_template.md 2026-03-02 01:54:47 +07:00
NΞVΛR 82fb9f4e33 added Controls info (Keyboard & Mouse) to readme 2026-03-01 19:50:45 +01:00
Slenderman 90504b1479 fix various things 2026-03-01 13:38:11 -05:00
void_17andGitHub 99a8c53bc1 Merge pull request #33 from APAmk2/main
Windows: More proper shutdown
2026-03-02 01:28:47 +07:00
void_17andGitHub 3bf5db9584 Merge pull request #34 from galenguyer/fix-release-assets
Copy release assets instead of changing working directory at runtime
2026-03-02 01:23:23 +07:00
Galen Guyer ec61d19d78 Revert "Merge pull request #25 from NEVARLeVrai/main"
This reverts commit 33e1b5ceb9, reversing
changes made to 44b68333a3.
This is a hacky way of doing it instead of just copying the assets that are needed
2026-03-01 13:14:36 -05:00
APAmk2 3db164d913 Windows: More proper shutdown 2026-03-01 22:13:44 +04:00
Galen Guyer bf24f709f9 Copy other folders needed for a standalone release asset 2026-03-01 13:13:11 -05:00
void_17andGitHub b865228eed Merge pull request #31 from yuri-kiss/main
fix: ps3 build error
2026-03-02 00:59:16 +07:00
Miyo ShoandGitHub 0714be8b8d fix: ps3 build error 2026-03-01 12:57:42 -05:00
void_17andGitHub 33e1b5ceb9 Merge pull request #25 from NEVARLeVrai/main
Fix for exe not running, not founding the project directory
2026-03-02 00:50:22 +07:00
void_17andGitHub 44b68333a3 Merge pull request #28 from rtm516/feature/exit
Fix game exit
2026-03-02 00:42:53 +07:00
NΞVΛR e23945a020 Fixed performance issue
thx to @void2012
2026-03-01 18:40:09 +01:00
rtm516 31e993d6ee Fix game exit 2026-03-01 17:29:59 +00:00
void_17andGitHub e6e1b4ef38 Merge pull request #23 from DFelipehDEV/main
remove 4j source control warning when opening the solution
2026-03-02 00:22:38 +07:00
daoge_cmd 6cba5705dd fix: fix sprinting 2026-03-02 01:21:56 +08:00
NΞVΛR fa25430694 Fix for exe not running, not founding the project directory
In _tWinMain (Windows64_Minecraft.cpp) add logic to detect if the executable path contains "\\x64\\". If found, truncate the path at that position, append "\\Minecraft.Client" and call SetCurrentDirectoryA to set the process working directory. This ensures relative resource paths resolve correctly when running from an x64 build output directory; the change is guarded by a substring check and uses MAX_PATH-safe APIs.
2026-03-01 18:19:38 +01:00
Zasus 9481c9aa8b remove 4j source control warning when opening the solution 2026-03-01 17:08:31 +00:00
Sean HoytandGitHub b5111232aa feat: Windows64 local multiplayer support (#13)
- Skip QuadrantSignin (profile selector) on Windows64 in both LoadMenu
  and CreateWorldMenu, proceeding directly to local play since Xbox Live
  stubs always return true for IsSignedInLive()
- Fix IsLocalMultiplayerAvailable() to not require IsHiDef() on Windows64
- Allow pad-connected players to join without a profile sign-in check
- Fix ghost RemotePlayer creation by scanning all local player slots and
  matching on server-assigned player index rather than controller slot,
  fixing P3/P4 ghost entities when joining out of controller order
- Give each player a unique name (Player 1-4) based on controller index
  instead of a single shared stub name
- Use raw XInput (XInputGetState) for secondary controller join detection,
  bypassing the 4J toggle system which consumes all button presses before
  game logic runs; uses a 120-frame latch for a reliable detection window
- Add .gitignore for Visual Studio build artifacts and output directories
2026-03-02 00:50:48 +08:00
daoge_cmd d5707899db feat: update scroll wheel behavior for page navigation 2026-03-02 00:50:37 +08:00
rtm516andGitHub 05ea5ca043 Add gitignore (#17)
* Add gitignore

* Use some of the stuff from #13
2026-03-02 00:45:30 +08:00
daoge_cmd 47e00f7b62 feat: improve mouse input handling 2026-03-02 00:43:04 +08:00
hehckerandGitHub e16600a3e6 fix: render issues on release builds (#16) 2026-03-02 00:06:51 +08:00
void_17andGitHub 754303b327 Fix compilation for Clang-cl (#10)
1. Converted `MinecraftWindows.rc` and `Resource.h` to UTF-8 from UTF-16(they didn't use any UTF-16 symbols anyway);

2. Added explicit signed->unsigned integer casts in `gdraw_d3d1x_shared.inl` for C++11 compatibility

3. Linked against `legacy_stdio_definitions.lib` to avoid undefined references to `_vsnprintf` llvm-link errors
2026-03-01 23:29:08 +08:00
daoge_cmd 5fa4418adb feat: implement per-frame mouse look for reduced input latency on Windows 2026-03-01 21:50:44 +08:00
daoge_cmd 71daf43d99 chore: update image asset 2026-03-01 21:37:39 +08:00
daoge_cmd 7e3bdebd77 fix: do not use hardcoded screen size 2026-03-01 21:32:42 +08:00
daoge_cmd 515f8e6fa7 doc: remove outdated note about missing sound effects in README.md 2026-03-01 21:23:29 +08:00
daoge_cmd 8b1dafd361 feat: add DPI awareness and auto-detect screen resolution 2026-03-01 21:22:02 +08:00
daogeandGitHub f90c74d9a3 Merge pull request #3 from deadman96385/main
fix: copy sound assets to Windows64 build output
2026-03-01 21:10:47 +08:00
daoge_cmd 4c81c7960c feat: fullscreen mode 2026-03-01 21:05:16 +08:00
deadman96385 4a7d75194a fix: copy sound assets to Windows64 build output
The Debug|x64 and Release|x64 configurations had no PostBuildEvent to
deploy sound assets alongside the executable. At runtime, SoundEngine
looks for Durango\Sound\Minecraft.msscmp and music\ relative to the
output directory, causing silent failure (no sound effects or music).

Add post-build xcopy steps for both configurations to mirror what the
Durango build already does.
2026-03-01 06:36:06 -06:00
daoge_cmd 52a256562f feat: disable vsync 2026-03-01 20:12:58 +08:00
daoge_cmd 2aee607d6c feat: implement game-tick input handling and per-frame edge detection 2026-03-01 19:59:48 +08:00
daoge_cmd e067d710e3 fea: remove fps limit 2026-03-01 19:32:00 +08:00
daoge_cmd bdef1f9412 feat: add support for keyboard and mouse input 2026-03-01 19:20:41 +08:00
daoge_cmd 9af787692e fix: fix release mode compilation on Windows 2026-03-01 16:04:34 +08:00
daoge_cmd 3c459b465c doc: update README.md 2026-03-01 15:08:13 +08:00
daoge_cmd d26f70a0cb update readme 2026-03-01 12:21:31 +08:00
daoge_cmd b691c43c44 Initial commit 2026-03-01 12:16:08 +08:00
daoge_cmd def8cb4153 first commit 2026-03-01 12:13:52 +08:00
842 changed files with 169299 additions and 116003 deletions
+3
View File
@@ -0,0 +1,3 @@
.github/workflows/docker-nightly.yml merge=ours
.github/workflows/nightly.yml merge=ours
docker-compose.dedicated-server.ghcr.yml merge=ours
Binary file not shown.

After

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 646 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 KiB

-107
View File
@@ -1,107 +0,0 @@
name: TU31 Release
on:
workflow_dispatch:
push:
branches:
- 'TU31'
paths:
- '**'
- '!.gitignore'
- '!*.md'
- '!.github/**'
- '.github/workflows/nightly.yml'
permissions:
contents: write
concurrency:
group: TU31
cancel-in-progress: true
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
platform: [Windows64]
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
- name: Set platform lowercase
run: echo "MATRIX_PLATFORM=$('${{ matrix.platform }}'.ToLower())" >> $env:GITHUB_ENV
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
- name: Setup CMake
uses: lukka/get-cmake@latest
- name: Run CMake
uses: lukka/run-cmake@v10
env:
VCPKG_ROOT: "" # Disable vcpkg for CI builds
with:
configurePreset: ${{ env.MATRIX_PLATFORM }}
buildPreset: ${{ env.MATRIX_PLATFORM }}-release
buildPresetAdditionalArgs: "['--target', 'Minecraft.Client']"
- name: Zip Build
run: 7z a -r LCE${{ matrix.platform }}.zip ./build/${{ env.MATRIX_PLATFORM }}/Minecraft.Client/Release/* "-x!*.ipdb" "-x!*.iobj"
- name: Stage artifacts
run: |
New-Item -ItemType Directory -Force -Path staging
Copy-Item LCE${{ matrix.platform }}.zip staging/
- name: Stage exe and pdb
if: matrix.platform == 'Windows64'
run: |
Copy-Item ./build/${{ env.MATRIX_PLATFORM }}/Minecraft.Client/Release/Minecraft.Client.exe staging/
- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
name: build-${{ matrix.platform }}
path: staging/*
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: artifacts
merge-multiple: true
- name: Update release
uses: andelf/nightly-release@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: TU31
name: Nightly Client Release
body: |
Requires at least Windows 7 and DirectX 11 compatible GPU to run.
# 🚨 First time here? 🚨
If you've never downloaded the game before, you need to download `LCEWindows64.zip` and extract it to the folder where you'd like to keep the game. The other files are included in this `.zip` file!
files: |
artifacts/*
cleanup:
needs: [build, release]
if: always()
runs-on: ubuntu-latest
steps:
- name: Cleanup artifacts
uses: geekyeggo/delete-artifact@v5
with:
name: build-*
+169 -63
View File
@@ -1,107 +1,213 @@
name: Nightly Release
on:
workflow_dispatch:
push:
branches:
- 'TU19'
paths:
- '**'
- '!.gitignore'
- '!*.md'
- '!.github/**'
- '.github/workflows/nightly.yml'
workflow_dispatch:
permissions:
contents: write
id-token: write
attestations: write
packages: write
concurrency:
group: nightly
cancel-in-progress: true
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
platform: [Windows64]
build-client:
name: Build Client
runs-on: [self-hosted, windows]
steps:
- name: Checkout
uses: actions/checkout@v6
uses: https://github.com/actions/checkout@v6
with:
submodules: recursive
- name: Set platform lowercase
run: echo "MATRIX_PLATFORM=$('${{ matrix.platform }}'.ToLower())" >> $env:GITHUB_ENV
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
uses: https://github.com/ilammy/msvc-dev-cmd@v1
- name: Setup CMake
uses: lukka/get-cmake@latest
uses: https://github.com/lukka/get-cmake@latest
- name: Run CMake
uses: lukka/run-cmake@v10
uses: https://github.com/lukka/run-cmake@v10
env:
VCPKG_ROOT: "" # Disable vcpkg for CI builds
VCPKG_ROOT: ""
with:
configurePreset: ${{ env.MATRIX_PLATFORM }}
buildPreset: ${{ env.MATRIX_PLATFORM }}-release
configurePreset: windows64
buildPreset: windows64-release
buildPresetAdditionalArgs: "['--target', 'Minecraft.Client']"
- name: Zip Build
run: 7z a -r LCE${{ matrix.platform }}.zip ./build/${{ env.MATRIX_PLATFORM }}/Minecraft.Client/Release/* "-x!*.ipdb" "-x!*.iobj"
shell: pwsh
run: |
$source = "./build/windows64/Minecraft.Client/Release"
$zip = "LCE-Online-Client-Win64.zip"
$topLevel = "LCE-Online-Client-Win64"
$files = Get-ChildItem -Path $source -Recurse -File |
Where-Object { $_.Extension -notin '.pch', '.pdb', '.zip', '.ipdb', '.iobj', '.exp', '.lib' }
Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem
$basePath = (Resolve-Path $source).Path
$fs = [System.IO.File]::Open($zip, [System.IO.FileMode]::Create)
try {
$archive = New-Object System.IO.Compression.ZipArchive($fs, [System.IO.Compression.ZipArchiveMode]::Create)
try {
Get-ChildItem -Path $basePath -Recurse -Directory | ForEach-Object {
$rel = $_.FullName.Substring($basePath.Length).TrimStart('\', '/')
$archive.CreateEntry("$topLevel/$($rel -replace '\\','/')/") | Out-Null
}
foreach ($file in $files) {
$rel = $file.FullName.Substring($basePath.Length).TrimStart('\', '/')
$entryName = "$topLevel/$($rel -replace '\\','/')"
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
$archive, $file.FullName, $entryName,
[System.IO.Compression.CompressionLevel]::Optimal
) | Out-Null
}
} finally { $archive.Dispose() }
} finally { $fs.Dispose() }
Write-Host "Created $zip"
- name: Stage artifacts
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path staging
Copy-Item LCE${{ matrix.platform }}.zip staging/
- name: Stage exe and pdb
if: matrix.platform == 'Windows64'
run: |
Copy-Item ./build/${{ env.MATRIX_PLATFORM }}/Minecraft.Client/Release/Minecraft.Client.exe staging/
Copy-Item LCE-Online-Client-Win64.zip staging/
Copy-Item ./build/windows64/Minecraft.Client/Release/Minecraft.Client.exe staging/
Copy-Item ./build/windows64/Minecraft.Client/Release/Minecraft.Client.pdb staging/
- name: Upload artifacts
uses: actions/upload-artifact@v6
uses: https://github.com/actions/upload-artifact@v3
with:
name: build-${{ matrix.platform }}
name: client-build
path: staging/*
release:
needs: build
runs-on: ubuntu-latest
release-client:
name: Release Client
needs: build-client
runs-on: [self-hosted, linux]
steps:
- name: Download all artifacts
uses: actions/download-artifact@v7
- name: Checkout
uses: https://github.com/actions/checkout@v6
- name: Download client artifacts
uses: https://github.com/actions/download-artifact@v3
with:
name: client-build
path: artifacts
merge-multiple: true
- name: Update release
uses: andelf/nightly-release@main
- name: Install jq
run: apt-get update && apt-get install -y --no-install-recommends jq
- name: Get short SHA
id: sha
run: echo "short=$(echo '${{ github.sha }}' | cut -c1-7)" >> "$GITHUB_OUTPUT"
- name: Delete old release and tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: nightly
name: Nightly Client Release
body: |
Requires at least Windows 7 and DirectX 11 compatible GPU to run.
# 🚨 First time here? 🚨
If you've never downloaded the game before, you need to download `LCEWindows64.zip` and extract it to the folder where you'd like to keep the game. The other files are included in this `.zip` file!
files: |
artifacts/*
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG="Nightly"
API="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
AUTH="Authorization: token $FORGEJO_TOKEN"
EXISTING_ID=$(curl -sf -H "$AUTH" "$API/releases/tags/$TAG" 2>/dev/null | jq -r '.id // empty' || true)
if [ -n "$EXISTING_ID" ]; then
curl -sf -X DELETE -H "$AUTH" "$API/releases/$EXISTING_ID"
fi
curl -s -X DELETE -H "$AUTH" "$API/tags/$TAG" > /dev/null || true
cleanup:
needs: [build, release]
if: always()
runs-on: ubuntu-latest
steps:
- name: Cleanup artifacts
uses: geekyeggo/delete-artifact@v5
- name: Import GPG key
uses: https://github.com/crazy-max/ghaction-import-gpg@v6
with:
name: build-*
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_user_signingkey: true
git_tag_gpgsign: true
- name: Create signed tag
run: |
git tag -s -f Nightly -m "Nightly release ${{ steps.sha.outputs.short }}"
git push origin Nightly --force
- name: Write release notes
run: |
cat > notes.md <<'NOTES'
# Instructions:
**Newcomers:**
- If this is your first time, download `LCE-Online-Client-Win64.zip` and extract it wherever you would like to keep it.
- I would recommend to set your username prior to launch (create a file called `username.txt`, put your desired username into the file, and save).
- To play, simply run `Minecraft.Client.exe`.
**For those that wish to update their existing installation with the latest build:**
- Download `Minecraft.Client.exe` and copy it over to your existing LCE-Online-Client-Win64 build (overwrite your old version of Minecraft.Client.exe).
**For developers:**
- `Minecraft.Client.pdb` contains debug symbols for crash analysis and development. Place it next to `Minecraft.Client.exe` for stack traces to show function names and line numbers.
**Steam Deck & Linux:**
- Y'all know the drill. Download the `LCE-Online-Client-Win64.zip`, extract it, add the `Minecraft.Client.exe` as a "Non-Steam Game" within the Steam library, turn on compatibility mode with Proton Experimental, and then run it!
# Multiplayer instructions:
LAN games are natively supported, and any LAN games will appear automatically on the right. However, if you'd like to play with your friends online (and if you don't want to require them to setup a vpn, and/or if you don't want to port forward), I would recommend the following setup. Please keep in mind, you do NOT need to do this to enjoy the game. This is just how I have it setup for me so my friends can join without any hassle:
Prerequisites:
- Premium playit.gg account, costs about $3 USD per month. This is for setting up the tunnel.
- playit.gg agent installed on host PC.
How-to:
- Ensure your playit.gg agent is connected to your playit.gg account
- On the playit.gg website, setup a new tunnel (choose TCP). Ensure the configurable settings are set to the below values, assuming your agent is installed on the same computer as your LCE Online game is hosted from.
- Configurable settings:
- Local IP: `127.0.0.1`
- Local Port: `25565`
- Proxy Protocol: `None`
- After creating your tunnel, navigate to the "Tunnels" main page. You'll see the IP address and port for your tunnel. This is what your friends will input when adding your server in order to join your online game!
NOTES
- name: Create release on Forgejo
env:
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG="Nightly"
TITLE="Client: ${{ steps.sha.outputs.short }}"
API="${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
AUTH="Authorization: token $FORGEJO_TOKEN"
BODY=$(cat notes.md)
PAYLOAD=$(jq -nc --arg tag "$TAG" --arg name "$TITLE" --arg body "$BODY" \
'{tag_name:$tag, name:$name, body:$body, draft:false, prerelease:false}')
RID=$(curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d "$PAYLOAD" "$API/releases" | jq -r '.id')
if [ -z "$RID" ] || [ "$RID" = "null" ]; then
echo "Failed to create release" >&2
exit 1
fi
echo "Created release id=$RID"
for asset in artifacts/*; do
name=$(basename "$asset")
size=$(stat -c%s "$asset")
echo "Uploading $name ($size bytes)"
HTTP=$(curl -sS -w '%{http_code}' -o /tmp/upload-resp -X POST -H "$AUTH" \
-F "attachment=@$asset" \
"$API/releases/$RID/assets?name=$name")
if [ "$HTTP" -lt 200 ] || [ "$HTTP" -ge 300 ]; then
echo "Upload failed: HTTP $HTTP" >&2
echo "--- response body ---" >&2
cat /tmp/upload-resp >&2 || true
echo "" >&2
exit 1
fi
echo "Uploaded $name OK (HTTP $HTTP)"
done
+15 -12
View File
@@ -4,31 +4,34 @@ on:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize]
paths:
- '**'
- '!.gitignore'
- '!*.md'
- '!.github/**'
- '.github/workflows/pull-request.yml'
paths-ignore:
- '.gitignore'
- '*.md'
- '.github/*.md'
jobs:
build:
runs-on: windows-latest
runs-on: [self-hosted, windows]
steps:
- name: Checkout
uses: actions/checkout@v6
uses: https://github.com/actions/checkout@v6
with:
submodules: recursive
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
uses: https://github.com/ilammy/msvc-dev-cmd@v1
- name: Setup CMake
uses: lukka/get-cmake@latest
uses: https://github.com/lukka/get-cmake@latest
- name: Setup .NET
uses: https://github.com/actions/setup-dotnet@v4
with:
global-json-file: global.json
- name: Run CMake
uses: lukka/run-cmake@v10
uses: https://github.com/lukka/run-cmake@v10
env:
VCPKG_ROOT: "" # Disable vcpkg for CI builds
with:
+9 -1
View File
@@ -26,6 +26,7 @@ mono_crash.*
[Rr]elease/
[Rr]eleases/
x64/
x64_*/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
@@ -415,12 +416,19 @@ tmp*/
_server_asset_probe/
server-data/
# Tools build artifacts and intermediates
tools/*.class
tools/*.swf
tools/staging/
tools/server-monitor/
# Nix
result
result-*
.direnv/
.xwin-cache/
.xwin/
# macOS
.DS_Store
/.idea
+1 -1
View File
@@ -1,3 +1,3 @@
[submodule "Minecraft.Client/Windows64/4JLibs"]
path = Minecraft.Client/Windows64/4JLibs
url = https://gitea.str1k3r.xyz/str1k3r/4JLibs.git
url = https://github.com/itsRevela/4JLibs.git
+116
View File
@@ -0,0 +1,116 @@
{
"search.exclude": {
"**/Minecraft.Client/Common/DummyTexturePack/res": true,
"**/Minecraft.Client/Common/Media": true,
"**/Minecraft.Client/Common/res": true,
"**/Minecraft.Client/Common/Trial": true,
"**/Minecraft.Client/Durango/4JLibs/libs": true,
"**/Minecraft.Client/Durango/CU": true,
"**/Minecraft.Client/Durango/DLCImages": true,
"**/Minecraft.Client/Durango/DurangoExtras/xcompress.dll": true,
"**/Minecraft.Client/Durango/DurangoExtras/xcompress.lib": true,
"**/Minecraft.Client/Durango/Iggy/lib": true,
"**/Minecraft.Client/Durango/Layout": true,
"**/Minecraft.Client/Durango/Miles/lib": true,
"**/Minecraft.Client/Durango/Network/Windows.Xbox.Networking.RealtimeSession.dll": true,
"**/Minecraft.Client/Durango/Network/windows.xbox.networking.realtimesession.pdb": true,
"**/Minecraft.Client/Durango/Network/windows.xbox.networking.realtimesession.winmd": true,
"**/Minecraft.Client/Durango/ServiceConfig": true,
"**/Minecraft.Client/Durango/Sound": true,
"**/Minecraft.Client/Durango/DLCXbox1.cmp": true,
"**/Minecraft.Client/Durango/*.png": true,
"**/Minecraft.Client/DurangoMedia/DLC": true,
"**/Minecraft.Client/DurangoMedia/Layout": true,
"**/Minecraft.Client/DurangoMedia/loc": true,
"**/Minecraft.Client/DurangoMedia/loc/strings.h": false,
"**/Minecraft.Client/DurangoMedia/Media": true,
"**/Minecraft.Client/DurangoMedia/Sound": true,
"**/Minecraft.Client/music": true,
"**/Minecraft.Client/Orbis/4JLibs/Libs": true,
"**/Minecraft.Client/Orbis/DLCImages": true,
"**/Minecraft.Client/Orbis/GameConfig": true,
"**/Minecraft.Client/Orbis/GameConfig/Minecraft.spa.h": false,
"**/Minecraft.Client/Orbis/Iggy/lib": true,
"**/Minecraft.Client/Orbis/Miles/lib": true,
"**/Minecraft.Client/Orbis/min/min.sig": true,
"**/Minecraft.Client/Orbis/min/pronunciation.sig": true,
"**/Minecraft.Client/Orbis/MinecraftPronunciation/MinecraftPronunciation.sig": true,
"**/Minecraft.Client/Orbis/MinecraftPronunciation/pronunciation.sig": true,
"**/Minecraft.Client/Orbis/PS4ProductCodes.bin": true,
"**/Minecraft.Client/Orbis/session_image.jpg": true,
"**/Minecraft.Client/Orbis/session_image.png": true,
"**/Minecraft.Client/OrbisMedia/DLC": true,
"**/Minecraft.Client/OrbisMedia/loc": true,
"**/Minecraft.Client/OrbisMedia/loc/strings.h": false,
"**/Minecraft.Client/OrbisMedia/Media": true,
"**/Minecraft.Client/PS3/4JLibs/libs": true,
"**/Minecraft.Client/PS3/DATA": true,
"**/Minecraft.Client/PS3/Edge": true,
"**/Minecraft.Client/PS3/GameConfig/MinecraftIcon.png": true,
"**/Minecraft.Client/PS3/GameConfig/set.png": true,
"**/Minecraft.Client/PS3/Iggy/lib": true,
"**/Minecraft.Client/PS3/Media": true,
"**/Minecraft.Client/PS3/Media/*.h": true,
"**/Minecraft.Client/PS3/Miles/lib": true,
"**/Minecraft.Client/PS3/Sound": true,
"**/Minecraft.Client/PS3/SPU_Tasks/*.o": true,
"**/Minecraft.Client/PS3/SPU_Tasks/mssspurs.elf": true,
"**/Minecraft.Client/PS3/PS3ProductCodes.bin": true,
"**/Minecraft.Client/PS3_GAME": true,
"**/Minecraft.Client/PS3Media/DLC": true,
"**/Minecraft.Client/PS3Media/loc": true,
"**/Minecraft.Client/PS3Media/Media": true,
"**/Minecraft.Client/PS4_GAME": true,
"**/Minecraft.Client/PSVita/4JLibs/libs": true,
"**/Minecraft.Client/PSVita/app": true,
"**/Minecraft.Client/PSVita/Builds": true,
"**/Minecraft.Client/PSVita/GameConfig": true,
"**/Minecraft.Client/PSVita/GameConfig/Minecraft.spa.h": false,
"**/Minecraft.Client/PSVita/Iggy/lib": true,
"**/Minecraft.Client/PSVita/Miles/lib": true,
"**/Minecraft.Client/PSVita/Sound": true,
"**/Minecraft.Client/PSVita/Tutorial": true,
"**/Minecraft.Client/PSVita/configuration.psp2path": true,
"**/Minecraft.Client/PSVita/PSVitaProductCodes.bin": true,
"**/Minecraft.Client/PSVita/session_image.png": true,
"**/Minecraft.Client/PSVitaMedia/DLC": true,
"**/Minecraft.Client/PSVitaMedia/loc": true,
"**/Minecraft.Client/PSVitaMedia/Media": true,
"**/Minecraft.Client/PSVitaMedia/Tutorial": true,
"**/Minecraft.Client/PSVitaMedia/Minecraft.Client.self": true,
"**/Minecraft.Client/redist64": true
"**/Minecraft.Client/sce_sys": true
"**/Minecraft.Client/TROPDIR": true
"**/Minecraft.Client/Windows64/4JLibs/libs": true,
"**/Minecraft.Client/Windows64/GameConfig/Minecraft.spa": true,
"**/Minecraft.Client/Windows64/GameHDD": true,
"**/Minecraft.Client/Windows64/Iggy/lib": true,
"**/Minecraft.Client/Windows64Media": true,
"**/Minecraft.Client/Windows64Media/4J_strings.h": false,
"**/Minecraft.Client/Windows64Media/strings.h": false,
"**/Minecraft.Client/x64": true,
"**/Minecraft.Client/Xbox/4JLibs/libs": true,
"**/Minecraft.Client/Xbox/4JLibs/Media": true,
"**/Minecraft.Client/Xbox/Cheats": true,
"**/Minecraft.Client/Xbox/ContentPackageBuild": true,
"**/Minecraft.Client/Xbox/Docs": true,
"**/Minecraft.Client/Xbox/GameConfig": true,
"**/Minecraft.Client/Xbox/GameConfig/Minecraft.spa.h": false,
"**/Minecraft.Client/Xbox/kinect": true,
"**/Minecraft.Client/Xbox/loc": true,
"**/Minecraft.Client/Xbox/ReleaseBuild": true,
"**/Minecraft.Client/Xbox/SubmissionBuild": true,
"**/Minecraft.Client/Xbox/Title Update": true,
"**/Minecraft.Client/Xbox/TMSFiles": true,
"**/Minecraft.Client/Xbox/MinecraftWindows.ico": true,
"**/Minecraft.Client/Xbox/small.ico": true,
"**/Minecraft.Client/alphaTest.png": true,
"**/Minecraft.Client/thumbnailTest64.png": true,
"**/Minecraft.Client/thumbnailTest128.png": true,
"**/Minecraft.Client/thumbnailTest256.png": true,
"**/Minecraft.Client/thumbnailTest1028.png": true,
"**/Minecraft.World/x64_Debug": true,
"**/Minecraft.World/x64_Release": true
"**/x64": true
}
}
+16 -5
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.24)
project(MinecraftConsoles LANGUAGES C CXX RC ASM_MASM)
project(LCE-Revelations LANGUAGES C CXX RC ASM_MASM)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
@@ -12,7 +12,6 @@ endif()
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message(FATAL_ERROR "Use a 64-bit generator/toolchain (x64).")
endif()
set(CMAKE_CONFIGURATION_TYPES
"Debug"
"Release"
@@ -21,7 +20,7 @@ set(CMAKE_CONFIGURATION_TYPES
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
function(configure_compiler_target target)
# MSVC and compatible compilers (like Clang-cl)
# MSVC and compatible compilers (like Clang-cl) !
if (MSVC)
target_compile_options(${target} PRIVATE
$<$<AND:$<CONFIG:Debug>,$<COMPILE_LANGUAGE:C,CXX>>:/W3>
@@ -39,10 +38,10 @@ function(configure_compiler_target target)
# MSVC
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(${target} PRIVATE
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/GL>
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/GL /Zi>
)
target_link_options(${target} PRIVATE
$<$<CONFIG:Release>:/LTCG:incremental>
$<$<CONFIG:Release>:/LTCG:incremental /DEBUG /OPT:REF /OPT:ICF>
)
endif()
@@ -68,9 +67,14 @@ set(MINECRAFT_SHARED_DEFINES
$<$<CONFIG:Debug>:_DEBUG>
_CRT_NON_CONFORMING_SWPRINTFS
_CRT_SECURE_NO_WARNINGS
_HAS_STD_BYTE=0
)
# Add platform-specific defines
if(PLATFORM_NAME STREQUAL "Windows64")
list(APPEND MINECRAFT_SHARED_DEFINES _WINDOWS64)
set(IGGY_LIBS iggy_w64.lib)
endif()
list(APPEND MINECRAFT_SHARED_DEFINES ${PLATFORM_DEFINES})
# ---
@@ -80,6 +84,10 @@ add_subdirectory("Minecraft.Client/${PLATFORM_NAME}/4JLibs")
add_subdirectory(Minecraft.World)
add_subdirectory(Minecraft.Client)
if(PLATFORM_NAME STREQUAL "Windows64") # Server is only supported on Windows for now
add_subdirectory(Minecraft.Server.FourKit)
add_subdirectory(Minecraft.Server)
endif()
# ---
# Build versioning
@@ -97,6 +105,9 @@ add_custom_target(GenerateBuildVer
add_dependencies(Minecraft.World GenerateBuildVer)
add_dependencies(Minecraft.Client GenerateBuildVer)
if(PLATFORM_NAME STREQUAL "Windows64")
add_dependencies(Minecraft.Server GenerateBuildVer)
endif()
# ---
# Project organisation
+121 -61
View File
@@ -1,14 +1,59 @@
# Compile Instructions
## Visual Studio
## Prerequisites
1. Clone the repo, including submodules.
- If you don't, the build will fail. `git clone --recurse-submodules https://github.com/mclemp/MCLEClient.git`
2. Open the repo folder in Visual Studio 2022+.
3. Wait for cmake to configure the project and load all assets (this may take a few minutes on the first run).
4. Right click a folder in the solution explorer and switch to the 'CMake Targets View'
5. Select platform and configuration from the dropdown. EG: `Windows64 - Release`
6. Pick the startup project `Minecraft.Client.exe`
- **Visual Studio 2022** with the **Desktop development with C++** workload (this includes the CMake tools, MSVC toolchain, and Windows 10 SDK).
- **.NET 10 SDK**, required to build the FourKit plugin host (`Minecraft.Server.FourKit`).
- Download: https://dotnet.microsoft.com/download/dotnet/10.0 (pick the **x64 SDK** installer)
- The exact SDK version is pinned in `global.json` at the repo root.
- CMake will fail configure with a clear error message if .NET 10 is not installed, so you find out immediately rather than partway through a build.
- The build invokes `dotnet publish ... --runtime win-x64 --self-contained true`, so the published output bundles a complete .NET 10 runtime alongside the FourKit assembly. End users running the produced server do **not** need to install .NET themselves.
- All FourKit runtime files (DLL + .NET runtime + `hostfxr.dll`) land in a `runtime/` subfolder next to `Minecraft.Server.exe`. An empty `plugins/` folder is also created. Both are produced automatically by the build.
## Visual Studio 2022 quick start (recommended)
VS 2022 has built-in CMake support, so there is no need to generate a `.sln` file by hand.
1. Install the prerequisites above.
2. Clone the repo with submodules. If you don't, you will get a build error!
- `git clone --recurse-submodules https://github.com/itsRevela/LCE-Revelations.git`
3. In Visual Studio: `File > Open > Folder...` and select the **repo root** (the folder that contains `CMakeLists.txt`).
4. Wait for CMake to configure (~5 seconds on a warm cache, a few minutes on the first run while assets copy).
5. Pick a build configuration in the dropdown, for example `windows64-release`.
6. `Build > Build All` (or `F7`). Targets of interest:
- `Minecraft.Client`: the game client.
- `Minecraft.Server`: the **vanilla** dedicated server. Standalone C++ binary, no plugin host, no .NET dependency at runtime, smallest distribution.
- `Minecraft.Server.FourKit`: the **FourKit-enabled** dedicated server. Bundles the .NET 10 plugin host alongside the exe (in `runtime/`) and creates an empty `plugins/` folder for end users to drop plugin DLLs into. Building this target also triggers the `Minecraft.Server.FourKit.Managed` target which publishes the C# project.
7. Use the debug target dropdown to pick `Minecraft.Client.exe` or whichever server flavour you want, then `F5` to launch.
### Server flavours
Both server targets compile from the same source tree and produce a binary literally named `Minecraft.Server.exe`. The variant identity lives in the build directory:
```
build/<preset>/Minecraft.Server/Release/
Minecraft.Server.exe (vanilla, no plugin support)
Common/, Windows64/, ...
build/<preset>/Minecraft.Server.FourKit/Release/
Minecraft.Server.exe (FourKit-enabled, same exe name on purpose)
runtime/ (self-contained .NET 10 + Minecraft.Server.FourKit.dll)
plugins/ (empty drop point)
Common/, Windows64/, ...
```
The FourKit target gets the `MINECRAFT_SERVER_FOURKIT_BUILD` preprocessor define. Inside `FourKitBridge.h`, the real plugin entry points are conditional on that define; the vanilla target sees inline no-op stubs instead, so gameplay code can call `FourKitBridge::Fire*` unconditionally and produce the right behaviour for each flavour without per-call-site `#ifdef`s.
### Dedicated server debug arguments
- Default debugger arguments for both `Minecraft.Server` and `Minecraft.Server.FourKit`:
- `-port 25565 -bind 0.0.0.0 -name DedicatedServer`
- You can override arguments in:
- `Project Properties > Debugging > Command Arguments`
- Both server targets post-build copy the dedicated-server asset set:
- `Common/Media/MediaWindows64.arc`
- `Common/res`
- `Windows64/GameHDD`
## CMake (Windows x64)
@@ -20,12 +65,48 @@ Open `Developer PowerShell for VS` and run:
cmake --preset windows64
```
Build Debug:
```powershell
cmake --build --preset windows64-debug --target Minecraft.Client
```
Build Release:
```powershell
cmake --build --preset windows64-release --target Minecraft.Client
```
Build vanilla Dedicated Server (Debug):
```powershell
cmake --build --preset windows64-debug --target Minecraft.Server
```
Build vanilla Dedicated Server (Release):
```powershell
cmake --build --preset windows64-release --target Minecraft.Server
```
Build FourKit Dedicated Server (Debug):
```powershell
cmake --build --preset windows64-debug --target Minecraft.Server.FourKit
```
Build FourKit Dedicated Server (Release):
```powershell
cmake --build --preset windows64-release --target Minecraft.Server.FourKit
```
Build everything (client + both server flavours):
```powershell
cmake --build --preset windows64-release
```
Run executable:
```powershell
@@ -33,6 +114,20 @@ cd .\build\windows64\Minecraft.Client\Debug
.\Minecraft.Client.exe
```
Run vanilla dedicated server:
```powershell
cd .\build\windows64\Minecraft.Server\Debug
.\Minecraft.Server.exe -port 25565 -bind 0.0.0.0 -name DedicatedServer
```
Run FourKit dedicated server:
```powershell
cd .\build\windows64\Minecraft.Server.FourKit\Debug
.\Minecraft.Server.exe -port 25565 -bind 0.0.0.0 -name DedicatedServer
```
Notes:
- Post-build asset copy is automatic for `Minecraft.Client` in CMake (Debug and Release variants).
- The game relies on relative paths (for example `Common\Media\...`), so launching from the output directory is required.
@@ -55,75 +150,40 @@ Install xwin for downloading the Windows SDK:
cargo install xwin
```
### Download Windows SDK
Download and extract the Windows SDK and CRT:
### Compile
Run this (Release):
```bash
xwin --accept-license splat --output ~/.cache/xwin/splat
./build-linux.sh
```
Create symlinks to account for Linux filesystems being case sensitive:
Or, for debug:
```bash
WINSDK=~/.cache/xwin/splat
ln -sf $WINSDK/sdk/include/shared/sdkddkver.h $WINSDK/sdk/include/shared/SDKDDKVer.h
ln -sf $WINSDK/sdk/lib/um/x86_64/xinput9_1_0.lib $WINSDK/sdk/lib/um/x86_64/XInput9_1_0.lib
ln -sf $WINSDK/sdk/lib/um/x86_64/ws2_32.lib $WINSDK/sdk/lib/um/x86_64/Ws2_32.lib
./build-linux.sh . Debug
```
### Configure
Set environment variables and configure CMake:
### NixOS / Nix
For NixOS or systems with Nix installed, use the provided flake:
```bash
export WINSDK=~/.cache/xwin/splat
export INCLUDE="$WINSDK/crt/include;$WINSDK/sdk/include/um;$WINSDK/sdk/include/ucrt;$WINSDK/sdk/include/shared"
export LIB="$WINSDK/crt/lib/x86_64;$WINSDK/sdk/lib/um/x86_64;$WINSDK/sdk/lib/ucrt/x86_64"
cmake -S . -B build/windows64-clang \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER=clang-cl \
-DCMAKE_CXX_COMPILER=clang-cl \
-DCMAKE_LINKER=lld-link \
-DCMAKE_RC_COMPILER=llvm-rc \
-DCMAKE_MT=llvm-mt \
-DPLATFORM_DEFINES="_WINDOWS64" \
-DPLATFORM_NAME="Windows64" \
-DIGGY_LIBS="iggy_w64.lib;iggyperfmon_w64.lib;iggyexpruntime_w64.lib" \
-DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded \
-DCMAKE_C_FLAGS="/MT -fms-compatibility -fms-extensions --target=x86_64-pc-windows-msvc -imsvc $WINSDK/crt/include -imsvc $WINSDK/sdk/include/ucrt -imsvc $WINSDK/sdk/include/um -imsvc $WINSDK/sdk/include/shared" \
-DCMAKE_CXX_FLAGS="/MT -fms-compatibility -fms-extensions --target=x86_64-pc-windows-msvc -imsvc $WINSDK/crt/include -imsvc $WINSDK/sdk/include/ucrt -imsvc $WINSDK/sdk/include/um -imsvc $WINSDK/sdk/include/shared" \
-DCMAKE_ASM_MASM_FLAGS="-m64" \
-DCMAKE_EXE_LINKER_FLAGS="-libpath:$WINSDK/crt/lib/x86_64 -libpath:$WINSDK/sdk/lib/um/x86_64 -libpath:$WINSDK/sdk/lib/ucrt/x86_64"
nix build .#client
nix build .#server
```
### Build
Build Release:
Or enter the development shell with all dependencies:
```bash
cmake --build build/windows64-clang --config Release
```
Build specific target:
```bash
cmake --build build/windows64-clang --config Release --target Minecraft.Client
```
### Run with Wine
Run executable:
```bash
cd build/windows64-clang/Minecraft.Client
wine ./Minecraft.Client.exe
nix develop
```
Notes:
- Requires LLVM 15+ with clang-cl, lld-link, llvm-rc, and llvm-mt.
- The xwin tool downloads ~1GB of SDK files on first run.
- Wine is required to run the compiled Windows executables on Linux.
### Troubleshooting
- **`'vswhere.exe' is not recognized`**: harmless warning. This appears if you ran `vcvars64.bat` from a plain command prompt instead of `Developer PowerShell for VS`. The Visual Studio Installer's `vswhere.exe` lives at `C:\Program Files (x86)\Microsoft Visual Studio\Installer\` and is not on the default `PATH`. Use the Developer PowerShell shortcut, or open the repo folder directly in VS (which handles the dev env for you).
- **`.NET 10 SDK not found` at configure time**: install the x64 SDK from https://dotnet.microsoft.com/download/dotnet/10.0 and re-run CMake configure (`Project > Configure Cache` in VS, or `cmake --preset windows64` from a shell).
- **Server starts but logs `hostfxr_initialize_for_dotnet_command_line failed`**: the `runtime/` folder next to `Minecraft.Server.exe` is missing or stale. Rebuild the `Minecraft.Server.FourKit` target (which re-stages `runtime/`), or do a clean rebuild of `Minecraft.Server`.
+11 -4
View File
@@ -1,8 +1,5 @@
# Scope of Project
At the moment, this project's scope is generally limited outside of adding new content to the game (blocks, mobs, items). We are currently prioritizing stability, and platform support over these things.
## Backporting
If you're backporting a feature or downporting, please read [PORTING.md](./PORTING.md)
At the moment, this project's scope is generally limited outside of adding new content to the game (blocks, mobs, items). We are currently prioritizing stability, quality of life, and platform support over these things.
## Parity
We are attempting to keep our version of LCE as close to visual and experience parity with the original console experience of LCE as possible. This means that we will not be accepting changes that...
@@ -33,11 +30,21 @@ However, we would accept changes that...
## Current Goals
- Being a robust Desktop version of LCE
- Having proper controller support across all types, brands on Desktop or Desktop-like platforms (Steam Deck)
- Improving stability as much as possible
- Fixing as many bugs as possible
- Enabling Desktop multiplayer options
- LAN P2P Multiplayer
- Splitscreen Multiplayer
- WAN Servers (IP:Port connectivity)
- Platform-based P2P Connectivity
- Steam Networking
- GameDate?
- Maybe more?
- Refining rendering settings, renderer options, as well as reaching rendering parity with true LCE
- Having workable multi-platform compilation for ARM, Consoles, Linux
- Being a good base for further expansion and modding of LCE, such as backports and "modpacks".
# Scope of PRs
All Pull Requests should fully document the changes they include in their file changes. They should also be limited to one general topic and not touch all over the codebase unless its justifiable.
+1 -1
View File
@@ -152,7 +152,7 @@ void AchievementScreen::renderLabels()
// font.draw(xScrollP + ", " + yScrollP, xo + 5, yo + 5 + BIGMAP_HEIGHT + 18, 0x404040);
// font.drawWordWrap("Ride a pig off a cliff.", xo + 5, yo + 5 + BIGMAP_HEIGHT + 16, BIGMAP_WIDTH, 0x404040);
}
void AchievementScreen::renderBg(int xm, int ym, float a)
+18 -19
View File
@@ -6,6 +6,8 @@
ResourceLocation BeaconRenderer::BEAM_LOCATION = ResourceLocation(TN_MISC_BEACON_BEAM);
bool BeaconRenderer::s_renderOuterHalo = false;
void BeaconRenderer::render(shared_ptr<TileEntity> _beacon, double x, double y, double z, float a, bool setColor, float alpha, bool useCompiled)
{
shared_ptr<BeaconTileEntity> beacon = dynamic_pointer_cast<BeaconTileEntity>(_beacon);
@@ -18,21 +20,18 @@ void BeaconRenderer::render(shared_ptr<TileEntity> _beacon, double x, double y,
bindTexture(&BEAM_LOCATION);
// TODO: 4J: Put this back in
//assert(0);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glDepthMask(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
float tt = beacon->getLevel()->getGameTime() + a;
float texVOff = -tt * .20f - floor(-tt * .10f);
if (!s_renderOuterHalo)
{
glDisable(GL_BLEND);
glDepthMask(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
int r = 1;
double rot = tt * .025 * (1 - (r & 1) * 2.5);
@@ -73,20 +72,20 @@ void BeaconRenderer::render(shared_ptr<TileEntity> _beacon, double x, double y,
t->vertexUV(x + enx, y, z + enz, uu2, vv2);
t->vertexUV(x + esx, y, z + esz, uu1, vv2);
t->vertexUV(x + esx, y + top, z + esz, uu1, vv1);
t->vertexUV(x + wsx, y + top, z + wsz, uu2, vv1);
t->vertexUV(x + wsx, y, z + wsz, uu2, vv2);
t->vertexUV(x + wnx, y, z + wnz, uu1, vv2);
t->vertexUV(x + wnx, y + top, z + wnz, uu1, vv1);
t->end();
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
else
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
t->begin();
t->color(255, 255, 255, 32);
@@ -111,22 +110,22 @@ void BeaconRenderer::render(shared_ptr<TileEntity> _beacon, double x, double y,
t->vertexUV(x + wnx, y, z + wnz, uu2, vv2);
t->vertexUV(x + enx, y, z + enz, uu1, vv2);
t->vertexUV(x + enx, y + top, z + enz, uu1, vv1);
t->vertexUV(x + esx, y + top, z + esz, uu2, vv1);
t->vertexUV(x + esx, y, z + esz, uu2, vv2);
t->vertexUV(x + wsx, y, z + wsz, uu1, vv2);
t->vertexUV(x + wsx, y + top, z + wsz, uu1, vv1);
t->vertexUV(x + enx, y + top, z + enz, uu2, vv1);
t->vertexUV(x + enx, y, z + enz, uu2, vv2);
t->vertexUV(x + esx, y, z + esz, uu1, vv2);
t->vertexUV(x + esx, y + top, z + esz, uu1, vv1);
t->vertexUV(x + wsx, y + top, z + wsz, uu2, vv1);
t->vertexUV(x + wsx, y, z + wsz, uu2, vv2);
t->vertexUV(x + wnx, y, z + wnz, uu1, vv2);
t->vertexUV(x + wnx, y + top, z + wnz, uu1, vv1);
t->end();
}
+2
View File
@@ -9,5 +9,7 @@ private:
static ResourceLocation BEAM_LOCATION;
public:
static bool s_renderOuterHalo;
virtual void render(shared_ptr<TileEntity> _beacon, double x, double y, double z, float a, bool setColor, float alpha, bool useCompiled);
};
+11 -3
View File
@@ -21,9 +21,13 @@ set(MINECRAFT_CLIENT_SOURCES
$<$<STREQUAL:${PLATFORM_NAME},Windows64>:${MINECRAFT_CLIENT_WINDOWS}>
$<$<STREQUAL:${PLATFORM_NAME},Xbox>:${MINECRAFT_CLIENT_XBOX360}>
${SOURCES_COMMON}
"${CMAKE_SOURCE_DIR}/Minecraft.Client/Common/StringUtils.cpp"
)
add_executable(Minecraft.Client ${MINECRAFT_CLIENT_SOURCES} "Common/UI/UIScene_AchievementsMenu.cpp" "Common/UI/UIScene_AchievementsMenu.h" "Common/UI/UIControl_AchievementsList.cpp" "Common/UI/UIControl_AchievementsList.h")
add_executable(Minecraft.Client ${MINECRAFT_CLIENT_SOURCES} "Common/UI/UIScene_AchievementsMenu.cpp" "Common/UI/UIScene_AchievementsMenu.h" "Common/UI/UIControl_AchievementsList.cpp" "Common/UI/UIControl_AchievementsList.h" "Windows64/NetworkHelpers.h" "Windows64/NetworkHelpers.cpp" "Windows64/Windows64_Launcher.cpp" "Windows64/Windows64_Launcher.h"
)
# Only define executable on windows
if(PLATFORM_NAME STREQUAL "Windows64")
@@ -35,6 +39,7 @@ target_include_directories(Minecraft.Client PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/Iggy/include"
"${CMAKE_SOURCE_DIR}/include/"
"${CMAKE_CURRENT_SOURCE_DIR}/Windows64/ExtraLibs/webview2/build/native/include"
)
target_compile_definitions(Minecraft.Client PRIVATE
${MINECRAFT_SHARED_DEFINES}
@@ -52,6 +57,7 @@ set_target_properties(Minecraft.Client PROPERTIES
target_link_libraries(Minecraft.Client PRIVATE
Minecraft.World
d3d11
dxgi
d3dcompiler
XInput9_1_0
wsock32
@@ -61,6 +67,9 @@ target_link_libraries(Minecraft.Client PRIVATE
4JLibs.${PLATFORM_NAME}.Storage
4JLibs.${PLATFORM_NAME}.Render
$<$<STREQUAL:${PLATFORM_NAME},Windows64>:${CMAKE_CURRENT_SOURCE_DIR}/Windows64/ExtraLibs/discordsdk/discord_game_sdk.dll.lib>
$<$<STREQUAL:${PLATFORM_NAME},Windows64>:${CMAKE_CURRENT_SOURCE_DIR}/Windows64/ExtraLibs/webview2/build/native/x64/WebView2LoaderStatic.lib>
$<$<STREQUAL:${PLATFORM_NAME},Windows64>:shlwapi>
$<$<STREQUAL:${PLATFORM_NAME},Windows64>:ole32>
)
# Iggy libs
@@ -73,7 +82,7 @@ endforeach()
# ---
include("${CMAKE_SOURCE_DIR}/cmake/CopyAssets.cmake")
set(ASSET_FOLDER_PAIRS
"${CMAKE_CURRENT_SOURCE_DIR}/Music" "${PLATFORM_NAME}Media/Music"
"${CMAKE_CURRENT_SOURCE_DIR}/music" "music"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/Media" "Common/Media"
"${CMAKE_CURRENT_SOURCE_DIR}/Common/res" "Common/res"
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}Media" "${PLATFORM_NAME}Media"
@@ -86,5 +95,4 @@ add_copyredist_target(Minecraft.Client)
# Make sure GameHDD exists on Windows
if(PLATFORM_NAME STREQUAL "Windows64")
add_gamehdd_target(Minecraft.Client)
add_settings_target(Minecraft.Client)
endif()
+25 -8
View File
@@ -6,6 +6,7 @@
#include "../Minecraft.World/SharedConstants.h"
#include "../Minecraft.World/StringHelpers.h"
#include "../Minecraft.World/ChatPacket.h"
#include "../Minecraft.World/ArabicShaping.h"
const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters;
vector<wstring> ChatScreen::s_chatHistory;
@@ -15,7 +16,12 @@ int ChatScreen::s_chatIndex = 0;
bool ChatScreen::isAllowedChatChar(wchar_t c)
{
return c >= 0x20 && (c == L'\u00A7' || allowedChars.empty() || allowedChars.find(c) != wstring::npos);
if (c < 0x20) return false;
// Block Unicode bidirectional override characters that can be used to
// spoof chat messages or impersonate players.
if (c >= 0x202A && c <= 0x202E) return false; // LRE, RLE, PDF, LRO, RLO
if (c >= 0x2066 && c <= 0x2069) return false; // LRI, RLI, FSI, PDI
return true;
}
ChatScreen::ChatScreen()
@@ -110,6 +116,9 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
if (eventKey == Keyboard::KEY_RETURN)
{
wstring trim = trimString(message);
{ char buf[64]; sprintf_s(buf, "[CHAT] Sending (%d chars): ", (int)trim.length()); OutputDebugStringA(buf); }
OutputDebugStringW(trim.c_str());
OutputDebugStringA("\n");
if (trim.length() > 0)
{
if (!minecraft->handleClientSideCommand(trim))
@@ -152,6 +161,7 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
{
message.insert(cursorIndex, 1, ch);
cursorIndex++;
{ char buf[64]; sprintf_s(buf, "[CHAT] Char U+%04X accepted (%d chars)\n", (unsigned)ch, (int)message.length()); OutputDebugStringA(buf); }
}
}
@@ -162,14 +172,21 @@ void ChatScreen::render(int xm, int ym, float a)
int x = 4;
drawString(font, prefix, x, height - 12, 0xe0e0e0);
x += font->width(prefix);
wstring beforeCursor = message.substr(0, cursorIndex);
wstring afterCursor = message.substr(cursorIndex);
drawStringLiteral(font, beforeCursor, x, height - 12, 0xe0e0e0);
x += font->widthLiteral(beforeCursor);
// Shape the full message as one unit so letter connections and word order
// are correct. Track where the logical cursor maps in the visual string.
int visualCursorPos = 0;
wstring shaped = shapeArabicText(message, cursorIndex, &visualCursorPos);
// Render the full shaped message without re-shaping it
drawStringPreshaped(font, shaped, x, height - 12, 0xe0e0e0);
// Place the cursor at the correct visual position
wstring beforeCursorVisual = shaped.substr(0, visualCursorPos);
int cursorX = x + font->widthPreshaped(beforeCursorVisual);
if (frame / 6 % 2 == 0)
drawString(font, L"_", x, height - 12, 0xe0e0e0);
x += font->width(L"_");
drawStringLiteral(font, afterCursor, x, height - 12, 0xe0e0e0);
drawString(font, L"_", cursorX, height - 12, 0xe0e0e0);
Screen::render(xm, ym, a);
}
+231 -16
View File
@@ -58,6 +58,7 @@
#ifdef _WINDOWS64
#include "Xbox/Network/NetworkPlayerXbox.h"
#include "Common/Network/PlatformNetworkManagerStub.h"
#include "Windows64/Network/WinsockNetLayer.h"
#endif
@@ -66,6 +67,30 @@
#include "../Minecraft.World/GenericStats.h"
#endif
namespace
{
char mapIconToFrame(char iconSlot)
{
if (iconSlot >= 8) return iconSlot - 4;
return iconSlot;
}
// Same hash as getRandomPlayerMapIcon in MapItemSavedData.cpp, returning
// the Iggy/SWF frame index (0-7) instead of the raw icon slot.
char computePlayerMapFrame(int entityId, int playerIndex)
{
static const char PLAYER_MAP_ICON_SLOTS[] = { 0, 1, 2, 3, 8, 9, 10, 11 };
unsigned int seed = static_cast<unsigned int>(entityId);
seed ^= static_cast<unsigned int>(playerIndex * 0x9E3779B9u);
seed ^= (seed >> 16);
seed *= 0x7FEB352Du;
seed ^= (seed >> 15);
seed *= 0x846CA68Bu;
seed ^= (seed >> 16);
return mapIconToFrame(PLAYER_MAP_ICON_SLOTS[seed % 8]);
}
}
ClientConnection::ClientConnection(Minecraft *minecraft, const wstring& ip, int port)
{
// 4J Stu - No longer used as we use the socket version below.
@@ -110,6 +135,7 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs
started = false;
savedDataStorage = new SavedDataStorage(nullptr);
maxPlayers = 20;
m_isForkServer = false;
this->minecraft = minecraft;
@@ -342,7 +368,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
Level *dimensionLevel = minecraft->getLevel( packet->dimension );
if( dimensionLevel == nullptr )
{
level = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, false, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
level = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
// 4J Stu - We want to share the SavedDataStorage between levels
int otherDimensionId = packet->dimension == 0 ? -1 : 0;
@@ -377,6 +403,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
BYTE networkSmallId = getSocket()->getSmallId();
app.UpdatePlayerInfo(networkSmallId, packet->m_playerIndex, packet->m_uiGamePrivileges);
app.SetPlayerMapIcon(minecraft->player->getName().c_str(), computePlayerMapFrame(packet->clientVersion, packet->m_playerIndex));
minecraft->player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_All, packet->m_uiGamePrivileges);
// Assume all privileges are on, so that the first message we see only indicates things that have been turned off
@@ -411,7 +438,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
activeLevel = minecraft->getLevel(otherDimensionId);
}
MultiPlayerLevel *dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, false, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
MultiPlayerLevel *dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
dimensionLevel->savedDataStorage = activeLevel->savedDataStorage;
@@ -447,6 +474,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
BYTE networkSmallId = getSocket()->getSmallId();
app.UpdatePlayerInfo(networkSmallId, packet->m_playerIndex, packet->m_uiGamePrivileges);
app.SetPlayerMapIcon(player->getName().c_str(), computePlayerMapFrame(packet->clientVersion, packet->m_playerIndex));
player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_All, packet->m_uiGamePrivileges);
// Assume all privileges are on, so that the first message we see only indicates things that have been turned off
@@ -917,6 +945,36 @@ void ClientConnection::handleAddPlayer(shared_ptr<AddPlayerPacket> packet)
}
}
// Client-side registration: if we still have no IQNet entry for this remote
// player, create one so they appear in the Tab player list.
// Find the first available IQNet slot (customData == 0, skip slot 0 which
// is the host). We can't use packet->m_playerIndex directly because on
// dedicated servers the game-level player index starts at 0 for real
// players, conflicting with the IQNet host slot.
if (matchedQNetPlayer == nullptr)
{
for (int s = 1; s < MINECRAFT_NET_MAX_PLAYERS; ++s)
{
IQNetPlayer* qp = &IQNet::m_player[s];
if (qp->GetCustomDataValue() == 0 && qp->m_gamertag[0] == 0)
{
BYTE smallId = static_cast<BYTE>(s);
qp->m_smallId = smallId;
qp->m_isRemote = true;
qp->m_isHostPlayer = false;
qp->m_resolvedXuid = pktXuid;
wcsncpy_s(qp->m_gamertag, 32, packet->name.c_str(), _TRUNCATE);
if (smallId >= IQNet::s_playerCount)
IQNet::s_playerCount = smallId + 1;
extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager;
g_pPlatformNetworkManager->NotifyPlayerJoined(qp);
matchedQNetPlayer = qp;
break;
}
}
}
if (matchedQNetPlayer != nullptr)
{
// Store packet-authoritative XUID on this network slot so later lookups by XUID
@@ -946,6 +1004,7 @@ void ClientConnection::handleAddPlayer(shared_ptr<AddPlayerPacket> packet)
player->setPlayerIndex( packet->m_playerIndex );
player->setCustomSkin( packet->m_skinId );
player->setCustomCape( packet->m_capeId );
app.SetPlayerMapIcon(packet->name.c_str(), computePlayerMapFrame(packet->id, packet->m_playerIndex));
player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_All, packet->m_uiGamePrivileges);
if (!player->customTextureUrl.empty() && player->customTextureUrl.substr(0, 3).compare(L"def") != 0 && !app.IsFileInMemoryTextures(player->customTextureUrl))
@@ -1083,33 +1142,35 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr<MoveEntityPacketSmall> p
void ClientConnection::handleRemoveEntity(shared_ptr<RemoveEntitiesPacket> packet)
{
#ifdef _WINDOWS64
if (!g_NetworkManager.IsHost())
// On fork servers, IQNet cleanup is handled by the MC|ForkPLeave custom
// payload so players stay in Tab regardless of render distance. On
// upstream servers (no MC|ForkHello received), fall back to the old
// behaviour of cleaning up IQNet here.
if (!m_isForkServer && !g_NetworkManager.IsHost())
{
for (int i = 0; i < packet->ids.length; i++)
{
shared_ptr<Entity> entity = getEntity(packet->ids[i]);
if (entity != nullptr && entity->GetType() == eTYPE_PLAYER)
if (entity != nullptr)
{
shared_ptr<Player> player = dynamic_pointer_cast<Player>(entity);
if (player != nullptr)
{
PlayerUID xuid = player->getXuid();
INetworkPlayer* np = g_NetworkManager.GetPlayerByXuid(xuid);
if (np != nullptr)
for (int s = 1; s < MINECRAFT_NET_MAX_PLAYERS; ++s)
{
NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np;
IQNetPlayer* qp = npx->GetQNetPlayer();
if (qp != nullptr)
IQNetPlayer* qp = &IQNet::m_player[s];
if (qp->GetCustomDataValue() != 0 &&
_wcsicmp(qp->m_gamertag, player->getName().c_str()) == 0)
{
extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager;
g_pPlatformNetworkManager->NotifyPlayerLeaving(qp);
qp->m_smallId = 0;
qp->m_isRemote = false;
qp->m_isHostPlayer = false;
// Clear resolved id to avoid stale XUID -> player matches after disconnect.
qp->m_resolvedXuid = INVALID_XUID;
qp->m_gamertag[0] = 0;
qp->SetCustomDataValue(0);
break;
}
}
}
@@ -2883,7 +2944,7 @@ void ClientConnection::handleRespawn(shared_ptr<RespawnPacket> packet)
MultiPlayerLevel *dimensionLevel = (MultiPlayerLevel *)minecraft->getLevel( packet->dimension );
if( dimensionLevel == nullptr )
{
dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->mapSeed, packet->playerGameType, false, minecraft->level->getLevelData()->isHardcore(), packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->mapSeed, packet->playerGameType, false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
// 4J Stu - We want to shared the savedDataStorage between both levels
//if( dimensionLevel->savedDataStorage != nullptr )
@@ -3328,7 +3389,9 @@ void ClientConnection::handleTileEditorOpen(shared_ptr<TileEditorOpenPacket> pac
void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
{
app.DebugPrintf("ClientConnection::handleSignUpdate - ");
app.DebugPrintf("[SIGN] handleSignUpdate at (%d, %d, %d):\n", packet->x, packet->y, packet->z);
for (int i = 0; i < MAX_SIGN_LINES; i++)
app.DebugPrintf("[SIGN] Line%d: \"%ls\"\n", i+1, packet->lines[i].c_str());
if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z))
{
shared_ptr<TileEntity> te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z);
@@ -3342,7 +3405,7 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
ste->SetMessage(i,packet->lines[i]);
}
app.DebugPrintf("verified = %d\tCensored = %d\n",packet->m_bVerified,packet->m_bCensored);
app.DebugPrintf("[SIGN] verified=%d censored=%d\n", packet->m_bVerified, packet->m_bCensored);
ste->SetVerified(packet->m_bVerified);
ste->SetCensored(packet->m_bCensored);
@@ -3350,12 +3413,12 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
}
else
{
app.DebugPrintf("dynamic_pointer_cast<SignTileEntity>(te) == nullptr\n");
app.DebugPrintf("[SIGN] ERROR: tile entity is not a SignTileEntity\n");
}
}
else
{
app.DebugPrintf("hasChunkAt failed\n");
app.DebugPrintf("[SIGN] ERROR: chunk not loaded at position\n");
}
}
@@ -3742,6 +3805,158 @@ void ClientConnection::handleSoundEvent(shared_ptr<LevelSoundPacket> packet)
void ClientConnection::handleCustomPayload(shared_ptr<CustomPayloadPacket> customPayloadPacket)
{
#ifdef _WINDOWS64
// Build a server-specific identity token file path next to the executable.
// Each server gets its own token file based on a hash of the server address,
// so connecting to multiple secured servers doesn't overwrite tokens.
auto buildIdentityTokenPath = []() -> std::string {
char exePath[MAX_PATH] = {};
DWORD len = GetModuleFileNameA(NULL, exePath, MAX_PATH);
if (len == 0 || len >= MAX_PATH) return std::string();
char *lastSlash = strrchr(exePath, '\\');
if (lastSlash != NULL) *(lastSlash + 1) = 0;
// Hash the server IP:port to create a unique filename per server
char serverAddr[300] = {};
sprintf_s(serverAddr, sizeof(serverAddr), "%s:%d", g_Win64MultiplayerIP, g_Win64MultiplayerPort);
unsigned int hash = 5381;
for (const char *p = serverAddr; *p; ++p)
hash = ((hash << 5) + hash) + static_cast<unsigned char>(*p);
char filename[64] = {};
sprintf_s(filename, sizeof(filename), "identity-token-%08x.dat", hash);
return std::string(exePath) + filename;
};
// Identity token: server issued us a new token - store it locally
if (CustomPayloadPacket::IDENTITY_TOKEN_ISSUE.compare(customPayloadPacket->identifier) == 0)
{
if (customPayloadPacket->data.data != nullptr && customPayloadPacket->length == 32)
{
std::string tokenPath = buildIdentityTokenPath();
if (!tokenPath.empty())
{
FILE *f = nullptr;
fopen_s(&f, tokenPath.c_str(), "wb");
if (f != nullptr)
{
size_t written = fwrite(customPayloadPacket->data.data, 1, 32, f);
fclose(f);
if (written == 32)
{
app.DebugPrintf("Client: Stored identity token to %s\n", tokenPath.c_str());
}
else
{
app.DebugPrintf("Client: Failed to write full identity token (wrote %zu/32)\n", written);
}
}
else
{
app.DebugPrintf("Client: Failed to open %s for writing\n", tokenPath.c_str());
}
}
}
return;
}
// Identity token: server is challenging us to present our stored token
if (CustomPayloadPacket::IDENTITY_TOKEN_CHALLENGE.compare(customPayloadPacket->identifier) == 0)
{
std::string tokenPath = buildIdentityTokenPath();
FILE *f = nullptr;
if (!tokenPath.empty())
fopen_s(&f, tokenPath.c_str(), "rb");
if (f != nullptr)
{
uint8_t token[32] = {};
size_t bytesRead = fread(token, 1, 32, f);
fclose(f);
if (bytesRead == 32)
{
byteArray tokenData(32);
memcpy(tokenData.data, token, 32);
connection->send(std::make_shared<CustomPayloadPacket>(
CustomPayloadPacket::IDENTITY_TOKEN_RESPONSE, tokenData));
app.DebugPrintf("Client: Sent identity token response\n");
}
else
{
app.DebugPrintf("Client: identity-token.dat is invalid (%zu bytes)\n", bytesRead);
connection->send(std::make_shared<CustomPayloadPacket>(
CustomPayloadPacket::IDENTITY_TOKEN_RESPONSE, byteArray()));
}
SecureZeroMemory(token, sizeof(token));
}
else
{
app.DebugPrintf("Client: No identity-token.dat found, sending empty response\n");
connection->send(std::make_shared<CustomPayloadPacket>(
CustomPayloadPacket::IDENTITY_TOKEN_RESPONSE, byteArray()));
}
return;
}
// Stream cipher handshake: server sent us a key
if (CustomPayloadPacket::CIPHER_KEY_CHANNEL.compare(customPayloadPacket->identifier) == 0)
{
if (customPayloadPacket->length == ServerRuntime::Security::StreamCipher::KEY_SIZE &&
customPayloadPacket->data.data != nullptr)
{
app.DebugPrintf("Client: Received MC|CKey from server (%d bytes)\n", customPayloadPacket->length);
// Store key and send ack+activate atomically to prevent ResetClientCipher race
WinsockNetLayer::StoreClientCipherKey(customPayloadPacket->data.data);
if (!WinsockNetLayer::SendAckAndActivateClientSendCipher())
{
app.DebugPrintf("Client: Failed to send cipher ack, connection will be closed\n");
}
}
else
{
app.DebugPrintf("Client: Received malformed MC|CKey (length=%d)\n", customPayloadPacket->length);
}
return;
}
// Fork server identification: enables render-distance-independent player list
if (CustomPayloadPacket::FORK_HELLO_CHANNEL.compare(customPayloadPacket->identifier) == 0)
{
m_isForkServer = true;
app.DebugPrintf("Client: Connected to fork server\n");
return;
}
// Fork server player leave: clean up IQNet slot so player leaves Tab list
if (CustomPayloadPacket::FORK_PLAYER_LEAVE_CHANNEL.compare(customPayloadPacket->identifier) == 0)
{
if (customPayloadPacket->data.data != nullptr && customPayloadPacket->length > 0)
{
int nameLen = customPayloadPacket->length / static_cast<int>(sizeof(wchar_t));
wstring leavingName(reinterpret_cast<const wchar_t*>(customPayloadPacket->data.data), nameLen);
for (int s = 1; s < MINECRAFT_NET_MAX_PLAYERS; ++s)
{
IQNetPlayer* qp = &IQNet::m_player[s];
if (qp->GetCustomDataValue() != 0 &&
_wcsicmp(qp->m_gamertag, leavingName.c_str()) == 0)
{
extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager;
g_pPlatformNetworkManager->NotifyPlayerLeaving(qp);
qp->m_smallId = 0;
qp->m_isRemote = false;
qp->m_isHostPlayer = false;
qp->m_resolvedXuid = INVALID_XUID;
qp->m_gamertag[0] = 0;
qp->SetCustomDataValue(0);
app.DebugPrintf("Client: Player \"%ls\" left fork server, cleared IQNet slot %d\n", leavingName.c_str(), s);
break;
}
}
}
return;
}
#endif
if (CustomPayloadPacket::TRADER_LIST_PACKET.compare(customPayloadPacket->identifier) == 0)
{
ByteArrayInputStream bais(customPayloadPacket->data);
+1
View File
@@ -48,6 +48,7 @@ private:
std::unordered_set<int> m_trackedEntityIds;
std::unordered_set<int64_t> m_visibleChunks;
bool m_isForkServer; // true when connected to a fork server (received MC|ForkHello)
static int64_t chunkKey(int x, int z) { return ((int64_t)x << 32) | ((int64_t)z & 0xFFFFFFFF); }
+10 -2
View File
@@ -1,5 +1,13 @@
#include "stdafx.h"
#include "ClientConstants.h"
#include <string>
const wstring ClientConstants::VERSION_STRING = wstring(L"Minecraft LCE ") + VER_FILEVERSION_STR_W;//+ SharedConstants::VERSION_STRING;
const wstring ClientConstants::BRANCH_STRING = VER_BRANCHVERSION_STR_W;
const wchar_t* ClientConstants::LCEN_HOST = L"";
const std::wstring ClientConstants::VERSION_STRING =
L"Minecraft: Legacy Network Beta Build 2026.06.14-128 [DO NOT DISTRIBUTE]";
std::wstring ClientConstants::GetLCENString()
{
return L"";
}
+3 -1
View File
@@ -13,7 +13,9 @@ class ClientConstants
// INTERNAL DEVELOPMENT SETTINGS
public:
static const wstring VERSION_STRING;
static const wstring BRANCH_STRING;
static const wstring LCEN_STRING;
static const wchar_t* LCEN_HOST;
static std::wstring GetLCENString();
static const bool DEADMAU5_CAMERA_CHEATS = false;
};
+3
View File
@@ -45,6 +45,7 @@
#define GAME_HOST_OPTION_BITMASK_DOTILEDROPS 0x08000000
#define GAME_HOST_OPTION_BITMASK_NATURALREGEN 0x10000000
#define GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE 0x20000000
#define GAME_HOST_OPTION_BITMASK_HARDCORE 0x40000000 // 4J Added - for hardcore mode
#define GAME_HOST_OPTION_BITMASK_ALL 0xFFFFFFFF
#define GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT 20
@@ -104,6 +105,8 @@ enum EGameHostOptionWorldSize
#define GAMESETTING_ANIMATEDCHARACTER 0x00008000
#define GAMESETTING_PS3EULAREAD 0x00010000
#define GAMESETTING_PSVITANETWORKMODEADHOC 0x00020000
#define GAMESETTING_VSYNC 0x01000000
#define GAMESETTING_EXCLUSIVEFULLSCREEN 0x02000000
// defines for languages
+4
View File
@@ -178,6 +178,9 @@ enum eGameSetting
// PSVita
eGameSetting_PSVita_NetworkModeAdhoc,
// PC
eGameSetting_VSync,
eGameSetting_ExclusiveFullscreen,
};
@@ -648,6 +651,7 @@ enum eGameHostOption
eGameHostOption_DoTileDrops,
eGameHostOption_NaturalRegeneration,
eGameHostOption_DoDaylightCycle,
eGameHostOption_Hardcore, // 4J Added - for hardcore mode
};
// 4J-PB - If any new DLC items are added to the TMSFiles, this array needs updated
+160 -81
View File
@@ -8,6 +8,8 @@
#include "../../Minecraft.World/Mth.h"
#include "../../TexturePackRepository.h"
#include "../../DLCTexturePack.h"
#include "../../MultiPlayerGameMode.h"
#include "../../Minecraft.World/LevelSettings.h"
#include "Common/DLC/DLCAudioFile.h"
#ifdef __PSVITA__
@@ -25,7 +27,7 @@
#include <vector>
#include <memory>
#include <mutex>
#include <lce_filesystem\lce_filesystem.h>
#include <lce_filesystem/lce_filesystem.h>
#ifdef __ORBIS__
#include <audioout.h>
@@ -65,7 +67,7 @@ void SoundEngine::playMusicTick() {};
#ifdef _WINDOWS64
char SoundEngine::m_szSoundPath[]={"Windows64Media\\Sound\\"};
char SoundEngine::m_szMusicPath[]={"Windows64Media\\Music\\"};
char SoundEngine::m_szMusicPath[]={"music\\"};
char SoundEngine::m_szRedistName[]={"redist64"};
#elif defined _DURANGO
char SoundEngine::m_szSoundPath[]={"Sound\\"};
@@ -114,6 +116,9 @@ const char *SoundEngine::m_szStreamFileA[eStream_Max]=
"hal4",
"nuance1",
"nuance2",
"piano1",
"piano2",
"piano3",
#ifndef _XBOX
"creative1",
@@ -128,10 +133,6 @@ const char *SoundEngine::m_szStreamFileA[eStream_Max]=
"menu4",
#endif
"piano1",
"piano2",
"piano3",
// Nether
"nether1",
"nether2",
@@ -409,6 +410,13 @@ SoundEngine::SoundEngine()
eStream_end_dragon,eStream_end_end,
eStream_CD_1);
#ifndef _XBOX
m_iStream_Creative_Min = eStream_Overworld_Creative1;
m_iStream_Creative_Max = eStream_Overworld_Creative6;
m_iStream_Menu_Min = eStream_Overworld_Menu1;
m_iStream_Menu_Max = eStream_Overworld_Menu4;
#endif
m_musicID=getMusicID(LevelData::DIMENSION_OVERWORLD);
m_StreamingAudioInfo.bIs3D=false;
@@ -468,65 +476,69 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, floa
sprintf_s(basePath, "Windows64Media/Sound/%s", (char*)szSoundName);
char finalPath[256];
sprintf_s(finalPath, "%s.wav", basePath);
const char* extensions[] = { ".ogg", ".wav", ".mp3" };
size_t extCount = sizeof(extensions) / sizeof(extensions[0]);
bool found = false;
for (size_t extIdx = 0; extIdx < extCount; extIdx++)
// Check path cache first to avoid expensive filesystem probing
auto cacheIt = m_soundPathCache.find(iSound);
if (cacheIt != m_soundPathCache.end())
{
char basePlusExt[256];
sprintf_s(basePlusExt, "%s%s", basePath, extensions[extIdx]);
DWORD attr = GetFileAttributesA(basePlusExt);
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
{
sprintf_s(finalPath, "%s", basePlusExt);
found = true;
break;
}
const auto& paths = cacheIt->second;
if (paths.empty())
return; // previously probed, no files found
const std::string& chosen = paths[rand() % paths.size()];
sprintf_s(finalPath, "%s", chosen.c_str());
}
if (!found)
else
{
int count = 0;
// Cache miss — probe filesystem and store results
std::vector<std::string> validPaths;
const char* extensions[] = { ".ogg", ".wav", ".mp3" };
size_t extCount = sizeof(extensions) / sizeof(extensions[0]);
bool found = false;
// Check base name with each extension (non-numbered)
for (size_t extIdx = 0; extIdx < extCount; extIdx++)
{
for (size_t i = 1; i < 32; i++)
char basePlusExt[256];
sprintf_s(basePlusExt, "%s%s", basePath, extensions[extIdx]);
DWORD attr = GetFileAttributesA(basePlusExt);
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
{
char numberedPath[256];
sprintf_s(numberedPath, "%s%d%s", basePath, i, extensions[extIdx]);
DWORD attr = GetFileAttributesA(numberedPath);
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
validPaths.push_back(basePlusExt);
found = true;
break; // non-numbered: only one base file needed
}
}
if (!found)
{
// Check numbered variants (e.g. sound1.ogg, sound2.ogg, ...)
for (size_t extIdx = 0; extIdx < extCount; extIdx++)
{
for (int i = 1; i < 32; i++)
{
count = i;
char numberedPath[256];
sprintf_s(numberedPath, "%s%d%s", basePath, i, extensions[extIdx]);
DWORD attr = GetFileAttributesA(numberedPath);
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
{
validPaths.push_back(numberedPath);
}
}
}
}
if (count > 0)
m_soundPathCache[iSound] = validPaths;
if (validPaths.empty())
{
int chosen = (rand() % count) + 1;
for (size_t extIdx = 0; extIdx < extCount; extIdx++)
{
char numberedPath[256];
sprintf_s(numberedPath, "%s%d%s", basePath, chosen, extensions[extIdx]);
DWORD attr = GetFileAttributesA(numberedPath);
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
{
sprintf_s(finalPath, "%s", numberedPath);
found = true;
break;
}
}
if (!found)
{
sprintf_s(finalPath, "%s%d.wav", basePath, chosen);
}
sprintf_s(finalPath, "%s.wav", basePath); // fallback for debug print
}
else
{
const std::string& chosen = validPaths[rand() % validPaths.size()];
sprintf_s(finalPath, "%s", chosen.c_str());
}
}
@@ -546,7 +558,7 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, floa
if (ma_sound_init_from_file(
&m_engine,
finalPath,
MA_SOUND_FLAG_ASYNC,
MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC,
nullptr,
nullptr,
&s->sound) != MA_SUCCESS)
@@ -605,24 +617,40 @@ void SoundEngine::playUI(int iSound, float volume, float pitch)
sprintf_s(basePath, "Windows64Media/Sound/%s/%s", soundDir, ConvertSoundPathToName(name));
char finalPath[256];
sprintf_s(finalPath, "%s.wav", basePath);
const char* extensions[] = { ".ogg", ".wav", ".mp3" };
size_t count = sizeof(extensions) / sizeof(extensions[0]);
bool found = false;
for (size_t i = 0; i < count; i++)
// Check UI sound path cache first
auto cacheIt = m_uiSoundPathCache.find(iSound);
if (cacheIt != m_uiSoundPathCache.end())
{
sprintf_s(finalPath, "%s%s", basePath, extensions[i]);
if (FileExists(finalPath))
if (cacheIt->second.empty())
{
found = true;
break;
app.DebugPrintf("No sound file found for UI sound (cached): %s\n", basePath);
return;
}
sprintf_s(finalPath, "%s", cacheIt->second.c_str());
}
if (!found)
else
{
app.DebugPrintf("No sound file found for UI sound: %s\n", basePath);
return;
// Cache miss — probe filesystem and store result
const char* extensions[] = { ".ogg", ".wav", ".mp3" };
size_t count = sizeof(extensions) / sizeof(extensions[0]);
bool found = false;
for (size_t i = 0; i < count; i++)
{
sprintf_s(finalPath, "%s%s", basePath, extensions[i]);
if (FileExists(finalPath))
{
found = true;
break;
}
}
if (!found)
{
m_uiSoundPathCache[iSound] = ""; // cache negative result
app.DebugPrintf("No sound file found for UI sound: %s\n", basePath);
return;
}
m_uiSoundPathCache[iSound] = finalPath;
}
MiniAudioSound* s = new MiniAudioSound();
@@ -636,7 +664,7 @@ void SoundEngine::playUI(int iSound, float volume, float pitch)
if (ma_sound_init_from_file(
&m_engine,
finalPath,
MA_SOUND_FLAG_ASYNC,
MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC,
nullptr,
nullptr,
&s->sound) != MA_SUCCESS)
@@ -789,6 +817,46 @@ int SoundEngine::GetRandomishTrack(int iStart,int iEnd)
app.DebugPrintf("Select track %d\n",iVal);
return iVal;
}
/////////////////////////////////////////////
//
// getOverworldMusicID - selects overworld music based on game mode
//
/////////////////////////////////////////////
int SoundEngine::getOverworldMusicID(Minecraft *pMinecraft)
{
#ifndef _XBOX
// Check if any local player is in creative mode
bool isCreative = false;
for(unsigned int i = 0; i < MAX_LOCAL_PLAYERS; i++)
{
if(pMinecraft->localplayers[i] != nullptr && pMinecraft->localgameModes[i] != nullptr)
{
GameType *mode = pMinecraft->localgameModes[i]->getLocalPlayerMode();
if(mode != nullptr && mode->isCreative())
{
isCreative = true;
break;
}
}
}
if(isCreative)
{
// Creative: survival tracks + creative tracks
int survivalCount = m_iStream_Overworld_Max - m_iStream_Overworld_Min + 1;
int creativeCount = m_iStream_Creative_Max - m_iStream_Creative_Min + 1;
int pick = random->nextInt(survivalCount + creativeCount);
if(pick < survivalCount)
return GetRandomishTrack(m_iStream_Overworld_Min, m_iStream_Overworld_Max);
else
return GetRandomishTrack(m_iStream_Creative_Min, m_iStream_Creative_Max);
}
#endif
// Survival/Adventure: survival tracks only
return GetRandomishTrack(m_iStream_Overworld_Min, m_iStream_Overworld_Max);
}
/////////////////////////////////////////////
//
// getMusicID
@@ -796,29 +864,33 @@ int SoundEngine::GetRandomishTrack(int iStart,int iEnd)
/////////////////////////////////////////////
int SoundEngine::getMusicID(int iDomain)
{
int iRandomVal=0;
int result=-1;
Minecraft *pMinecraft=Minecraft::GetInstance();
// Before the game has started?
if(pMinecraft==nullptr)
{
// any track from the overworld
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
#ifndef _XBOX
// Title screen: play menu music
result = GetRandomishTrack(m_iStream_Menu_Min,m_iStream_Menu_Max);
#else
result = GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
#endif
}
if(pMinecraft->skins->isUsingDefaultSkin())
else if(pMinecraft->skins->isUsingDefaultSkin())
{
switch(iDomain)
{
case LevelData::DIMENSION_END:
// the end isn't random - it has different music depending on whether the dragon is alive or not, but we've not added the dead dragon music yet
return m_iStream_End_Min;
result = m_iStream_End_Min;
break;
case LevelData::DIMENSION_NETHER:
return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
//return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min);
result = GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
break;
default: //overworld
//return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min);
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
result = getOverworldMusicID(pMinecraft);
break;
}
}
else
@@ -827,15 +899,22 @@ int SoundEngine::getMusicID(int iDomain)
switch(iDomain)
{
case LevelData::DIMENSION_END:
return GetRandomishTrack(m_iStream_End_Min,m_iStream_End_Max);
result = GetRandomishTrack(m_iStream_End_Min,m_iStream_End_Max);
break;
case LevelData::DIMENSION_NETHER:
//return m_iStream_Nether_Min + random->nextInt(m_iStream_Nether_Max-m_iStream_Nether_Min);
return GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
result = GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
break;
default: //overworld
//return m_iStream_Overworld_Min + random->nextInt(m_iStream_Overworld_Max-m_iStream_Overworld_Min);
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
result = getOverworldMusicID(pMinecraft);
break;
}
}
#ifdef _DEBUG
if(result >= 0 && result < eStream_Max)
app.DebugPrintf("getMusicID: selected track '%s' (id=%d, domain=%d)\n", m_szStreamFileA[result], result, iDomain);
#endif
return result;
}
/////////////////////////////////////////////
@@ -1500,4 +1579,4 @@ char *SoundEngine::ConvertSoundPathToName(const wstring& name, bool bConvertSpac
return buf;
}
#endif
#endif
+15 -5
View File
@@ -1,10 +1,13 @@
#pragma once
class Minecraft;
class Mob;
class Options;
using namespace std;
#include "../../Minecraft.World/SoundTypes.h"
#include "..\..\Minecraft.World\SoundTypes.h"
#include "miniaudio.h"
#include <unordered_map>
#include <string>
constexpr float SFX_3D_MIN_DISTANCE = 1.0f;
constexpr float SFX_3D_MAX_DISTANCE = 16.0f;
@@ -23,8 +26,10 @@ enum eMUSICFILES
eStream_Overworld_hal4,
eStream_Overworld_nuance1,
eStream_Overworld_nuance2,
eStream_Overworld_piano1,
eStream_Overworld_piano2,
eStream_Overworld_piano3, // <-- make piano3 the last survival overworld one
#ifndef _XBOX
// Add the new music tracks
eStream_Overworld_Creative1,
eStream_Overworld_Creative2,
eStream_Overworld_Creative3,
@@ -36,9 +41,6 @@ enum eMUSICFILES
eStream_Overworld_Menu3,
eStream_Overworld_Menu4,
#endif
eStream_Overworld_piano1,
eStream_Overworld_piano2,
eStream_Overworld_piano3, // <-- make piano3 the last overworld one
// Nether
eStream_Nether1,
eStream_Nether2,
@@ -134,6 +136,7 @@ public:
bool isStreamingWavebankReady(); // 4J Added
int getMusicID(int iDomain);
int getMusicID(const wstring& name);
int getOverworldMusicID(Minecraft *pMinecraft);
void SetStreamingSounds(int iOverworldMin, int iOverWorldMax, int iNetherMin, int iNetherMax, int iEndMin, int iEndMax, int iCD1);
void updateMiniAudio();
void playMusicUpdate();
@@ -185,8 +188,15 @@ private:
int m_iStream_Nether_Min,m_iStream_Nether_Max;
int m_iStream_End_Min,m_iStream_End_Max;
int m_iStream_CD_1;
#ifndef _XBOX
int m_iStream_Creative_Min, m_iStream_Creative_Max;
int m_iStream_Menu_Min, m_iStream_Menu_Max;
#endif
bool *m_bHeardTrackA;
std::unordered_map<int, std::vector<std::string>> m_soundPathCache; // play(): sound ID → all valid variant paths
std::unordered_map<int, std::string> m_uiSoundPathCache; // playUI(): sound ID → resolved path
#ifdef __ORBIS__
int32_t m_hBGMAudio;
#endif
+40 -38
View File
@@ -6,14 +6,14 @@
const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]=
{
L"mob.chicken.say", // eSoundType_MOB_CHICKEN_AMBIENT
L"mob.chicken.hurt", // eSoundType_MOB_CHICKEN_HURT
L"mob.chicken.plop", // eSoundType_MOB_CHICKENPLOP
L"mob.cow.say", // eSoundType_MOB_COW_AMBIENT
L"mob.cow.hurt", // eSoundType_MOB_COW_HURT
L"mob.pig.say", // eSoundType_MOB_PIG_AMBIENT
L"mob.chicken.say", // eSoundType_MOB_CHICKEN_AMBIENT
L"mob.chicken.hurt", // eSoundType_MOB_CHICKEN_HURT
L"mob.chicken.plop", // eSoundType_MOB_CHICKENPLOP
L"mob.cow.say", // eSoundType_MOB_COW_AMBIENT
L"mob.cow.hurt", // eSoundType_MOB_COW_HURT
L"mob.pig.say", // eSoundType_MOB_PIG_AMBIENT
L"mob.pig.death", // eSoundType_MOB_PIG_DEATH
L"mob.sheep.say", // eSoundType_MOB_SHEEP_AMBIENT
L"mob.sheep.say", // eSoundType_MOB_SHEEP_AMBIENT
L"mob.wolf.growl", // eSoundType_MOB_WOLF_GROWL
L"mob.wolf.whine", // eSoundType_MOB_WOLF_WHINE
L"mob.wolf.panting", // eSoundType_MOB_WOLF_PANTING
@@ -43,15 +43,15 @@ const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]=
L"mob.silverfish.step", // eSoundType_MOB_SILVERFISH_STEP,
L"mob.skeleton", // eSoundType_MOB_SKELETON_AMBIENT,
L"mob.skeletonhurt", // eSoundType_MOB_SKELETON_HURT,
L"mob.spider.say", // eSoundType_MOB_SPIDER_AMBIENT,
L"mob.spider.death", // eSoundType_MOB_SPIDER_DEATH,
L"mob.spider.say", // eSoundType_MOB_SPIDER_AMBIENT,
L"mob.spider.death", // eSoundType_MOB_SPIDER_DEATH,
L"mob.slime", // eSoundType_MOB_SLIME,
L"mob.slime.attack", // eSoundType_MOB_SLIME_ATTACK,
L"mob.creeper.say", // eSoundType_MOB_CREEPER_HURT,
L"mob.slime.attack", // eSoundType_MOB_SLIME_ATTACK,
L"mob.creeper.say", // eSoundType_MOB_CREEPER_HURT,
L"mob.creeper.death", // eSoundType_MOB_CREEPER_DEATH,
L"mob.zombie.say", // eSoundType_MOB_ZOMBIE_AMBIENT,
L"mob.zombie.say", // eSoundType_MOB_ZOMBIE_AMBIENT,
L"mob.zombie.hurt", // eSoundType_MOB_ZOMBIE_HURT,
L"mob.zombie.death", // eSoundType_MOB_ZOMBIE_DEATH,
L"mob.zombie.death", // eSoundType_MOB_ZOMBIE_DEATH,
L"mob.zombie.wood", // eSoundType_MOB_ZOMBIE_WOOD,
L"mob.zombie.woodbreak", // eSoundType_MOB_ZOMBIE_WOOD_BREAK,
L"mob.zombie.metal", // eSoundType_MOB_ZOMBIE_METAL,
@@ -61,7 +61,7 @@ const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]=
L"mob.cat.purreow", // eSoundType_MOB_CAT_PURREOW
L"mob.cat.meow", // eSoundType_MOB_CAT_MEOW
// 4J-PB - correct the name of the event for hitting ocelots
L"mob.cat.hit", // eSoundType_MOB_CAT_HITT
L"mob.cat.hit", // eSoundType_MOB_CAT_HITT
// L"mob.irongolem.throw", // eSoundType_MOB_IRONGOLEM_THROW
// L"mob.irongolem.hit", // eSoundType_MOB_IRONGOLEM_HIT
// L"mob.irongolem.death", // eSoundType_MOB_IRONGOLEM_DEATH
@@ -86,7 +86,7 @@ const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]=
L"random.door_close", // eSoundType_RANDOM_DOOR_CLOSE,
L"ambient.weather.rain", // eSoundType_AMBIENT_WEATHER_RAIN,
L"ambient.weather.thunder", // eSoundType_AMBIENT_WEATHER_THUNDER,
L"ambient.cave", // eSoundType_CAVE_CAVE, DON'T USE FOR XBOX 360!!!
L"ambient.cave", // eSoundType_CAVE_CAVE, DON'T USE FOR XBOX 360!!!
#ifdef _XBOX
L"ambient.cave.cave2", // eSoundType_CAVE_CAVE2 - removed the two sounds that were at 192k in the first ambient cave event
#endif
@@ -187,30 +187,30 @@ const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]=
L"liquid.swim", //eSoundType_LIQUID_SWIM,
L"mob.horse.land", //eSoundType_MOB_HORSE_LAND,
L"mob.horse.armor", //eSoundType_MOB_HORSE_ARMOR,
L"mob.horse.leather", //eSoundType_MOB_HORSE_LEATHER,
L"mob.horse.zombie.death", //eSoundType_MOB_HORSE_ZOMBIE_DEATH,
L"mob.horse.skeleton.death", //eSoundType_MOB_HORSE_SKELETON_DEATH,
L"mob.horse.donkey.death", //eSoundType_MOB_HORSE_DONKEY_DEATH,
L"mob.horse.death", //eSoundType_MOB_HORSE_DEATH,
L"mob.horse.zombie.hit", //eSoundType_MOB_HORSE_ZOMBIE_HIT,
L"mob.horse.skeleton.hit", //eSoundType_MOB_HORSE_SKELETON_HIT,
L"mob.horse.donkey.hit", //eSoundType_MOB_HORSE_DONKEY_HIT,
L"mob.horse.hit", //eSoundType_MOB_HORSE_HIT,
L"mob.horse.zombie.idle", //eSoundType_MOB_HORSE_ZOMBIE_IDLE,
L"mob.horse.skeleton.idle", //eSoundType_MOB_HORSE_SKELETON_IDLE,
L"mob.horse.donkey.idle", //eSoundType_MOB_HORSE_DONKEY_IDLE,
L"mob.horse.idle", //eSoundType_MOB_HORSE_IDLE,
L"mob.horse.donkey.angry", //eSoundType_MOB_HORSE_DONKEY_ANGRY,
L"mob.horse.angry", //eSoundType_MOB_HORSE_ANGRY,
L"mob.horse.gallop", //eSoundType_MOB_HORSE_GALLOP,
L"mob.horse.breathe", //eSoundType_MOB_HORSE_BREATHE,
L"mob.horse.wood", //eSoundType_MOB_HORSE_WOOD,
L"mob.horse.soft", //eSoundType_MOB_HORSE_SOFT,
L"mob.horse.jump", //eSoundType_MOB_HORSE_JUMP,
L"Mob.horse.land", //eSoundType_MOB_HORSE_LAND,
L"Mob.horse.armor", //eSoundType_MOB_HORSE_ARMOR,
L"Mob.horse.leather", //eSoundType_MOB_HORSE_LEATHER,
L"Mob.horse.zombie.death", //eSoundType_MOB_HORSE_ZOMBIE_DEATH,
L"Mob.horse.skeleton.death", //eSoundType_MOB_HORSE_SKELETON_DEATH,
L"Mob.horse.donkey.death", //eSoundType_MOB_HORSE_DONKEY_DEATH,
L"Mob.horse.death", //eSoundType_MOB_HORSE_DEATH,
L"Mob.horse.zombie.hit", //eSoundType_MOB_HORSE_ZOMBIE_HIT,
L"Mob.horse.skeleton.hit", //eSoundType_MOB_HORSE_SKELETON_HIT,
L"Mob.horse.donkey.hit", //eSoundType_MOB_HORSE_DONKEY_HIT,
L"Mob.horse.hit", //eSoundType_MOB_HORSE_HIT,
L"Mob.horse.zombie.idle", //eSoundType_MOB_HORSE_ZOMBIE_IDLE,
L"Mob.horse.skeleton.idle", //eSoundType_MOB_HORSE_SKELETON_IDLE,
L"Mob.horse.donkey.idle", //eSoundType_MOB_HORSE_DONKEY_IDLE,
L"Mob.horse.idle", //eSoundType_MOB_HORSE_IDLE,
L"Mob.horse.donkey.angry", //eSoundType_MOB_HORSE_DONKEY_ANGRY,
L"Mob.horse.angry", //eSoundType_MOB_HORSE_ANGRY,
L"Mob.horse.gallop", //eSoundType_MOB_HORSE_GALLOP,
L"Mob.horse.breathe", //eSoundType_MOB_HORSE_BREATHE,
L"Mob.horse.wood", //eSoundType_MOB_HORSE_WOOD,
L"Mob.horse.soft", //eSoundType_MOB_HORSE_SOFT,
L"Mob.horse.jump", //eSoundType_MOB_HORSE_JUMP,
L"mob.witch.ambient", //eSoundType_MOB_WITCH_IDLE,
L"mob.witch.ambient", //eSoundType_MOB_WITCH_IDLE,
L"mob.witch.hurt", //eSoundType_MOB_WITCH_HURT,
L"mob.witch.death", //eSoundType_MOB_WITCH_DEATH,
@@ -223,6 +223,8 @@ const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]=
// 4J-PB - Some sounds were updated, but we can't do that for the 360 or we have to do a new sound bank
// instead, we'll add the sounds as new ones and change the code to reference them
L"fire.new_ignite",
L"damage.critical", //eSoundType_DAMAGE_CRITICAL,
};
@@ -45,6 +45,7 @@ enum eAward
eAward_bookcase,
#endif
eAward_adventuringTime,
eAward_repopulation,
//eAward_porkChop,
+122 -15
View File
@@ -188,6 +188,7 @@ CMinecraftApp::CMinecraftApp()
#endif
ZeroMemory(m_playerColours,MINECRAFT_NET_MAX_PLAYERS);
ZeroMemory(m_playerMapIcons,MINECRAFT_NET_MAX_PLAYERS);
m_iDLCOfferC=0;
m_bAllDLCContentRetrieved=true;
@@ -207,6 +208,8 @@ CMinecraftApp::CMinecraftApp()
m_dwRequiredTexturePackID=0;
m_bResetNether=false;
m_seedOverride = 0;
m_hasSeedOverride = false;
#ifdef _XBOX
// m_bTransferSavesToXboxOne=false;
@@ -788,7 +791,7 @@ static void Win64_GetSettingsPath(char *outPath, DWORD size)
GetModuleFileNameA(nullptr, outPath, size);
char *lastSlash = strrchr(outPath, '\\');
if (lastSlash) *(lastSlash + 1) = '\0';
strncat_s(outPath, size, "Windows64/Settings/settings.dat", _TRUNCATE);
strncat_s(outPath, size, "settings.dat", _TRUNCATE);
}
static void Win64_SaveSettings(GAME_SETTINGS *gs)
{
@@ -839,11 +842,8 @@ void CMinecraftApp::InitGameSettings()
memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS));
SetDefaultOptions(pProfileSettings,i);
Win64_LoadSettings(GameSettingsA[i]);
app.DebugPrintf("Loaded language: %d\n", GameSettingsA[i]->ucLanguage);
app.SetMinecraftLanguage(i, GameSettingsA[i]->ucLanguage);
app.SetMinecraftLocale(i, GameSettingsA[i]->ucLocale);
app.loadStringTable();
app.SetMinecraftLocale(i, GameSettingsA[i]->ucLocale);
app.loadStringTable();
ApplyGameSettingsChanged(i);
#elif defined __PS3__ || defined __ORBIS__ || defined _DURANGO || defined __PSVITA__
C4JStorage::PROFILESETTINGS *pProfileSettings=StorageManager.GetDashboardProfileSettings(i);
@@ -851,6 +851,12 @@ app.loadStringTable();
SetDefaultOptions(pProfileSettings,i,false);
#endif
Minecraft* minecraft = Minecraft::GetInstance();
if (minecraft != nullptr && minecraft->stats[i] != nullptr)
{
minecraft->stats[i]->clear();
minecraft->stats[i]->parse(GameSettingsA[i]);
}
}
}
@@ -860,7 +866,6 @@ int CMinecraftApp::SetDefaultOptions(C4JStorage::PROFILESETTINGS *pSettings,cons
int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,const int iPad)
#endif
{
app.DebugPrintf("SetDefaultOptions language BEFORE: %d\n", GameSettingsA[iPad]->ucLanguage);
SetGameSettings(iPad,eGameSetting_MusicVolume,DEFAULT_VOLUME_LEVEL);
SetGameSettings(iPad,eGameSetting_SoundFXVolume,DEFAULT_VOLUME_LEVEL);
SetGameSettings(iPad,eGameSetting_RenderDistance,16);
@@ -945,7 +950,6 @@ int CMinecraftApp::SetDefaultOptions(C_4JProfile::PROFILESETTINGS *pSettings,con
if (!app.GetGameStarted())
{
GameSettingsA[iPad]->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; // use the system language
app.DebugPrintf("SetDefaultOptions language AFTER: %d\n", GameSettingsA[iPad]->ucLanguage);
GameSettingsA[iPad]->ucLocale = MINECRAFT_LANGUAGE_DEFAULT; // use the system locale
}
@@ -1387,6 +1391,7 @@ void CMinecraftApp::ApplyGameSettingsChanged(int iPad)
ActionGameSettings(iPad,eGameSetting_AnimatedCharacter);
ActionGameSettings(iPad,eGameSetting_PS3_EULA_Read);
ActionGameSettings(iPad,eGameSetting_VSync);
}
@@ -1622,6 +1627,22 @@ void CMinecraftApp::ActionGameSettings(int iPad,eGameSetting eVal)
case eGameSetting_PSVita_NetworkModeAdhoc:
//nothing to do here
break;
case eGameSetting_VSync:
#ifdef _WINDOWS64
{
extern bool g_bVSync;
g_bVSync = (GetGameSettings(iPad, eGameSetting_VSync) != 0);
}
#endif
break;
case eGameSetting_ExclusiveFullscreen:
#ifdef _WINDOWS64
{
extern void SetExclusiveFullscreen(bool enabled);
SetExclusiveFullscreen(GetGameSettings(iPad, eGameSetting_ExclusiveFullscreen) != 0);
}
#endif
break;
}
}
@@ -2333,6 +2354,38 @@ void CMinecraftApp::SetGameSettings(int iPad,eGameSetting eVal,unsigned char ucV
}
break;
case eGameSetting_VSync:
if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24)!=(ucVal&0x01))
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_VSYNC;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_VSYNC;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
case eGameSetting_ExclusiveFullscreen:
if(((GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>25)!=(ucVal&0x01))
{
if(ucVal==1)
{
GameSettingsA[iPad]->uiBitmaskValues|=GAMESETTING_EXCLUSIVEFULLSCREEN;
}
else
{
GameSettingsA[iPad]->uiBitmaskValues&=~GAMESETTING_EXCLUSIVEFULLSCREEN;
}
ActionGameSettings(iPad,eVal);
GameSettingsA[iPad]->bSettingsChanged=true;
}
break;
}
}
@@ -2468,6 +2521,12 @@ unsigned char CMinecraftApp::GetGameSettings(int iPad,eGameSetting eVal)
case eGameSetting_PSVita_NetworkModeAdhoc:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_PSVITANETWORKMODEADHOC)>>17;
case eGameSetting_VSync:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_VSYNC)>>24;
case eGameSetting_ExclusiveFullscreen:
return (GameSettingsA[iPad]->uiBitmaskValues&GAMESETTING_EXCLUSIVEFULLSCREEN)>>25;
}
return 0;
}
@@ -4654,6 +4713,7 @@ int CMinecraftApp::SignoutExitWorldThreadProc( void* lpParameter )
break;
case DisconnectPacket::eDisconnect_OutdatedClient:
exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
break;
default:
exitReasonStringId = IDS_DISCONNECTED;
}
@@ -6603,12 +6663,11 @@ wstring CMinecraftApp::FormatHTMLString(int iPad, const wstring &desc, int shado
//found list of html escapes at https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-in-html
wstring CMinecraftApp::EscapeHTMLString(const wstring& desc)
{
static std::unordered_map<wchar_t, wchar_t*> replacementMap = {
{L'&', L"&amp;"},
{L'<', L"&lt;"},
{L'>', L"&gt;"},
{L'\"', L"&quot;"},
};
static std::unordered_map<wchar_t, wchar_t*> replacementMap = {
{L'&', L"&amp;"},
{L'<', L"&lt;"},
{L'>', L"&gt;"},
};
wstring finalString = L"";
for (int i = 0; i < desc.size(); i++) {
@@ -6679,6 +6738,8 @@ wstring CMinecraftApp::FormatChatMessage(const wstring& desc, bool applyStyling)
results = replaceAll(results, L"§f", replacements);
results = replaceAll(results, L"§r", replacements); //we only support color so reset is the same as white color
results = replaceAll(results, L"'", L"\u2019");
if (applyStyling) {
std::wsmatch match;
while (std::regex_search(results, match, IDS_Pattern)) {
@@ -8179,6 +8240,16 @@ void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOpt
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
break;
case eGameHostOption_Hardcore: // 4J Added - for hardcore mode
if(uiVal!=0)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_HARDCORE;
}
else
{
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HARDCORE;
}
break;
case eGameHostOption_All:
uiHostSettings=uiVal;
break;
@@ -8280,6 +8351,9 @@ unsigned int CMinecraftApp::GetGameHostOption(unsigned int uiHostSettings, eGame
case eGameHostOption_DoDaylightCycle:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE);
break;
case eGameHostOption_Hardcore: // 4J Added - for hardcore mode
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HARDCORE) ? 1 : 0;
break;
}
return false;
@@ -8558,6 +8632,39 @@ short CMinecraftApp::GetPlayerColour(BYTE networkSmallId)
return index;
}
void CMinecraftApp::SetPlayerMapIcon(const wchar_t* name, char icon)
{
if (name == nullptr) return;
// Update existing entry or use first empty slot
int emptySlot = -1;
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
{
if (m_playerMapIcons[i].name[0] != 0 && _wcsicmp(m_playerMapIcons[i].name, name) == 0)
{
m_playerMapIcons[i].icon = icon;
return;
}
if (emptySlot < 0 && m_playerMapIcons[i].name[0] == 0)
emptySlot = i;
}
if (emptySlot >= 0)
{
wcsncpy_s(m_playerMapIcons[emptySlot].name, 32, name, _TRUNCATE);
m_playerMapIcons[emptySlot].icon = icon;
}
}
char CMinecraftApp::GetPlayerMapIconByName(const wchar_t* name)
{
if (name == nullptr) return 0;
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i)
{
if (m_playerMapIcons[i].name[0] != 0 && _wcsicmp(m_playerMapIcons[i].name, name) == 0)
return m_playerMapIcons[i].icon;
}
return 0;
}
unsigned int CMinecraftApp::GetPlayerPrivileges(BYTE networkSmallId)
{
@@ -9699,7 +9806,7 @@ bool CMinecraftApp::IsLocalMultiplayerAvailable()
// 4J-PB - language and locale function
// getLocale from LCEN Client pasted ig
void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
{
#ifdef _WINDOWS64
+16 -1
View File
@@ -97,7 +97,7 @@ public:
*/
static const int GAME_DEFINED_PROFILE_DATA_BYTES = 2*972; // per user
#else
static const int GAME_DEFINED_PROFILE_DATA_BYTES = 3*972; // per user
static const int GAME_DEFINED_PROFILE_DATA_BYTES = 2*972; // per user
#endif
unsigned int uiGameDefinedDataChangedBitmask;
@@ -708,6 +708,8 @@ private:
bool m_bGameNewWorldSizeUseMoat;
unsigned int m_GameNewHellScale;
#endif
int64_t m_seedOverride;
bool m_hasSeedOverride;
unsigned int FromBigEndian(unsigned int uiValue);
public:
@@ -725,6 +727,10 @@ public:
void SetGameNewHellScale(unsigned int newScale) { m_GameNewHellScale = newScale; }
unsigned int GetGameNewHellScale() { return m_GameNewHellScale; }
#endif
void SetSeedOverride(int64_t seed) { m_seedOverride = seed; m_hasSeedOverride = true; }
bool HasSeedOverride() { return m_hasSeedOverride; }
int64_t GetSeedOverride() { return m_seedOverride; }
void SetResetNether(bool bResetNether) {m_bResetNether=bResetNether;}
bool GetResetNether() {return m_bResetNether;}
bool CanRecordStatsAndAchievements();
@@ -749,10 +755,14 @@ public:
private:
BYTE m_playerColours[MINECRAFT_NET_MAX_PLAYERS]; // An array of QNet small-id's
unsigned int m_playerGamePrivileges[MINECRAFT_NET_MAX_PLAYERS];
struct PlayerMapIconEntry { wchar_t name[32]; char icon; };
PlayerMapIconEntry m_playerMapIcons[MINECRAFT_NET_MAX_PLAYERS];
public:
void UpdatePlayerInfo(BYTE networkSmallId, SHORT playerColourIndex, unsigned int playerGamePrivileges);
short GetPlayerColour(BYTE networkSmallId);
void SetPlayerMapIcon(const wchar_t* name, char icon);
char GetPlayerMapIconByName(const wchar_t* name);
unsigned int GetPlayerPrivileges(BYTE networkSmallId);
wstring getEntityName(eINSTANCEOF type);
@@ -807,6 +817,10 @@ public:
void SetCorruptSaveDeleted(bool bVal) {m_bCorruptSaveDeleted=bVal;}
bool GetCorruptSaveDeleted(void) {return m_bCorruptSaveDeleted;}
// 4J Added: Store save folder name for hardcore world deletion on Win64
void SetCurrentSaveFolderName(const wstring& name) { m_currentSaveFolderName = name; }
const wstring& GetCurrentSaveFolderName() const { return m_currentSaveFolderName; }
void EnterSaveNotificationSection();
void LeaveSaveNotificationSection();
private:
@@ -828,6 +842,7 @@ private:
CRITICAL_SECTION csAdditionalSkinBoxes;
CRITICAL_SECTION csAnimOverrideBitmask;
bool m_bCorruptSaveDeleted;
wstring m_currentSaveFolderName; // 4J Added: for hardcore world deletion on Win64
DWORD m_dwAdditionalModelParts[XUSER_MAX_COUNT];
Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -38220,6 +38220,56 @@
<Time>19</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>NormalHardcore</Name>
<Time>20</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>HalfHardcore</Name>
<Time>21</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>FullHardcore</Name>
<Time>22</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>HalfPoisonHardcore</Name>
<Time>23</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>FullPoisonHardcore</Name>
<Time>24</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>NormalFlashHardcore</Name>
<Time>25</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>HalfFlashHardcore</Name>
<Time>26</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>FullFlashHardcore</Name>
<Time>27</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>HalfPoisonFlashHardcore</Name>
<Time>28</Time>
<Command>stop</Command>
</NamedFrame>
<NamedFrame>
<Name>FullPoisonFlashHardcore</Name>
<Time>29</Time>
<Command>stop</Command>
</NamedFrame>
</NamedFrames>
<Timeline>
<Id>Border</Id>
@@ -38274,6 +38324,16 @@
<Interpolation>0</Interpolation>
<Prop>Graphics\HUD\Health_Background_Flash.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>20</Time>
<Interpolation>0</Interpolation>
<Prop>Graphics\HUD\Health_Background_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>25</Time>
<Interpolation>0</Interpolation>
<Prop>Graphics\HUD\Health_Background_Hardcore_Flash.png</Prop>
</KeyFrame>
</Timeline>
<Timeline>
<Id>Heart</Id>
@@ -38399,6 +38459,66 @@
<Prop>true</Prop>
<Prop>Graphics\HUD\HorseHealth_Half_Flash.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>20</Time>
<Interpolation>0</Interpolation>
<Prop>false</Prop>
<Prop></Prop>
</KeyFrame>
<KeyFrame>
<Time>21</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Half_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>22</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Full_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>23</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Half_Poison_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>24</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Full_Poison_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>25</Time>
<Interpolation>0</Interpolation>
<Prop>false</Prop>
<Prop></Prop>
</KeyFrame>
<KeyFrame>
<Time>26</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Half_Flash_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>27</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Full_Flash_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>28</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Half_Poison_Flash_Hardcore.png</Prop>
</KeyFrame>
<KeyFrame>
<Time>29</Time>
<Interpolation>0</Interpolation>
<Prop>true</Prop>
<Prop>Graphics\HUD\Health_Full_Poison_Flash_Hardcore.png</Prop>
</KeyFrame>
</Timeline>
</Timelines>
</XuiVisual>
File diff suppressed because it is too large Load Diff
@@ -214,6 +214,7 @@ private:
int GetJoiningReadyPercentage();
bool m_bLastDisconnectWasLostRoomOnly;
bool m_bFullSessionMessageOnNextSessionChange;
bool m_bCancelRequested;
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
bool m_bSignedOutofPSN;
#endif
File diff suppressed because it is too large Load Diff
@@ -76,11 +76,8 @@ private:
bool m_bIsOfflineGame;
bool m_bIsPrivateGame;
int m_flagIndexSize;
#ifdef _WINDOWS64
bool m_bJoinPending;
int m_joinLocalUsersMask;
wchar_t m_joinHostName[32];
#endif
// This is only maintained by the host, and is not valid on client machines
+212
View File
@@ -0,0 +1,212 @@
#include "stdafx.h"
#include "StringUtils.h"
#include <cctype>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
namespace UtilityGame
{
namespace StringUtils
{
std::string WideToUtf8(const std::wstring &value)
{
if (value.empty())
{
return std::string();
}
int charCount = WideCharToMultiByte(CP_UTF8, 0, value.c_str(), (int)value.length(), NULL, 0, NULL, NULL);
if (charCount <= 0)
{
return std::string();
}
std::string utf8;
utf8.resize(charCount);
WideCharToMultiByte(CP_UTF8, 0, value.c_str(), (int)value.length(), &utf8[0], charCount, NULL, NULL);
return utf8;
}
std::wstring Utf8ToWide(const char *value)
{
if (value == NULL || value[0] == 0)
{
return std::wstring();
}
int wideCount = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
if (wideCount <= 0)
{
// Fall back to the current ANSI code page so legacy non-UTF-8 inputs remain readable.
wideCount = MultiByteToWideChar(CP_ACP, 0, value, -1, NULL, 0);
if (wideCount <= 0)
{
return std::wstring();
}
std::wstring wide;
wide.resize(wideCount - 1);
MultiByteToWideChar(CP_ACP, 0, value, -1, &wide[0], wideCount);
return wide;
}
std::wstring wide;
wide.resize(wideCount - 1);
MultiByteToWideChar(CP_UTF8, 0, value, -1, &wide[0], wideCount);
return wide;
}
std::wstring Utf8ToWide(const std::string &value)
{
return Utf8ToWide(value.c_str());
}
std::string StripUtf8Bom(const std::string &value)
{
if (value.size() >= 3 &&
(unsigned char)value[0] == 0xEF &&
(unsigned char)value[1] == 0xBB &&
(unsigned char)value[2] == 0xBF)
{
return value.substr(3);
}
return value;
}
std::string TrimAscii(const std::string &value)
{
size_t start = 0;
while (start < value.length() && std::isspace((unsigned char)value[start]))
{
++start;
}
size_t end = value.length();
while (end > start && std::isspace((unsigned char)value[end - 1]))
{
--end;
}
return value.substr(start, end - start);
}
std::string ToLowerAscii(const std::string &value)
{
std::string lowered = value;
for (size_t i = 0; i < lowered.length(); ++i)
{
lowered[i] = (char)std::tolower((unsigned char)lowered[i]);
}
return lowered;
}
std::string JoinTokens(const std::vector<std::string> &tokens, size_t startIndex, const char *separator)
{
if (startIndex >= tokens.size())
{
return std::string();
}
const auto joinSeparator = std::string((separator != nullptr) ? separator : " ");
size_t totalLength = 0;
for (size_t i = startIndex; i < tokens.size(); ++i)
{
totalLength += tokens[i].size();
}
totalLength += (tokens.size() - startIndex - 1) * joinSeparator.size();
std::string joined;
joined.reserve(totalLength);
for (size_t i = startIndex; i < tokens.size(); ++i)
{
if (!joined.empty())
{
joined += joinSeparator;
}
joined += tokens[i];
}
return joined;
}
bool StartsWithIgnoreCase(const std::string &value, const std::string &prefix)
{
if (prefix.size() > value.size())
{
return false;
}
for (size_t i = 0; i < prefix.size(); ++i)
{
unsigned char a = (unsigned char)value[i];
unsigned char b = (unsigned char)prefix[i];
if (std::tolower(a) != std::tolower(b))
{
return false;
}
}
return true;
}
bool TryParseUnsignedLongLong(const std::string &value, unsigned long long *outValue)
{
if (outValue == nullptr)
{
return false;
}
const std::string trimmed = TrimAscii(value);
if (trimmed.empty())
{
return false;
}
errno = 0;
char *end = nullptr;
const unsigned long long parsed = _strtoui64(trimmed.c_str(), &end, 0);
if (end == trimmed.c_str() || errno != 0)
{
return false;
}
while (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')
{
++end;
}
if (*end != 0)
{
return false;
}
*outValue = parsed;
return true;
}
std::string GetCurrentUtcTimestampIso8601()
{
SYSTEMTIME utc = {};
GetSystemTime(&utc);
char created[64] = {};
sprintf_s(
created,
sizeof(created),
"%04u-%02u-%02uT%02u:%02u:%02uZ",
(unsigned)utc.wYear,
(unsigned)utc.wMonth,
(unsigned)utc.wDay,
(unsigned)utc.wHour,
(unsigned)utc.wMinute,
(unsigned)utc.wSecond);
return created;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <string>
#include <vector>
namespace UtilityGame
{
namespace StringUtils
{
std::string WideToUtf8(const std::wstring &value);
std::wstring Utf8ToWide(const char *value);
std::wstring Utf8ToWide(const std::string &value);
std::string StripUtf8Bom(const std::string &value);
std::string TrimAscii(const std::string &value);
std::string ToLowerAscii(const std::string &value);
std::string JoinTokens(const std::vector<std::string> &tokens, size_t startIndex = 0, const char *separator = " ");
bool StartsWithIgnoreCase(const std::string &value, const std::string &prefix);
bool TryParseUnsignedLongLong(const std::string &value, unsigned long long *outValue);
std::string GetCurrentUtcTimestampIso8601();
}
}
@@ -29,6 +29,7 @@ IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu()
m_pointerPos.y = 0.0f;
m_bPointerDrivenByMouse = false;
m_iLastMouseTickTimeNs = -1;
}
IUIScene_AbstractContainerMenu::~IUIScene_AbstractContainerMenu()
@@ -266,6 +267,21 @@ void IUIScene_AbstractContainerMenu::UpdateTooltips()
void IUIScene_AbstractContainerMenu::onMouseTick()
{
// Frame-rate independent cursor input, normalized to a 60Hz reference frame.
const int64_t kRefFrameNs = 1000000000LL / 60;
const int64_t kMinDeltaNs = 1000000LL;
const int64_t kMaxDeltaNs = 100000000LL;
int64_t iNowNs = System::nanoTime();
float fFrameScale = 1.0f;
if ( m_iLastMouseTickTimeNs > 0 )
{
int64_t iDeltaNs = iNowNs - m_iLastMouseTickTimeNs;
if ( iDeltaNs < kMinDeltaNs ) iDeltaNs = kMinDeltaNs;
if ( iDeltaNs > kMaxDeltaNs ) iDeltaNs = kMaxDeltaNs;
fFrameScale = static_cast<float>(iDeltaNs) / static_cast<float>(kRefFrameNs);
}
m_iLastMouseTickTimeNs = iNowNs;
Minecraft *pMinecraft = Minecraft::GetInstance();
if( pMinecraft->localgameModes[getPad()] != nullptr)
{
@@ -422,10 +438,10 @@ void IUIScene_AbstractContainerMenu::onMouseTick()
// The SD/splitscreen scenes are approximately 0.6 times the size of the fullscreen on
if(!RenderManager.IsHiDef() || app.GetLocalPlayerCount() > 1) fInputScale *= 0.6f;
fInputX *= fInputScale;
fInputY *= fInputScale;
fInputX *= fInputScale * fFrameScale;
fInputY *= fInputScale * fFrameScale;
#ifdef USE_POINTER_ACCEL
#ifdef USE_POINTER_ACCEL
m_fPointerAccelX += fInputX / 50.0f;
m_fPointerAccelY += fInputY / 50.0f;
@@ -1269,36 +1285,8 @@ void IUIScene_AbstractContainerMenu::onMouseTick()
vPointerPos.x -= m_fPointerImageOffsetX;
vPointerPos.y -= m_fPointerImageOffsetY;
// Update pointer position.
// 4J-PB - do not allow sub pixel positions or we get broken lines in box edges
// problem here when sensitivity is low - we'll be moving a sub pixel size, so it'll clamp, and we'll never move. In that case, move 1 pixel
if(fInputDirX!=0.0f)
{
if(fInputDirX==1.0f)
{
vPointerPos.x+=0.999999f;
}
else
{
vPointerPos.x-=0.999999f;
}
}
if(fInputDirY!=0.0f)
{
if(fInputDirY==1.0f)
{
vPointerPos.y+=0.999999f;
}
else
{
vPointerPos.y-=0.999999f;
}
}
vPointerPos.x = static_cast<float>(floor(vPointerPos.x + 0.5f));
vPointerPos.y = static_cast<float>(floor(vPointerPos.y + 0.5f));
// Keep sub-pixel float state so deltas <1px accumulate across frames; the renderer
// truncates to integer pixels when emitting the Iggy mouse event.
m_pointerPos = vPointerPos;
adjustPointerForSafeZone();
@@ -145,6 +145,8 @@ protected:
int m_iConsectiveInputTicks;
int64_t m_iLastMouseTickTimeNs;
// Used for detecting quick "taps" in a direction, should jump cursor to next slot.
enum ETapState
{
@@ -210,6 +210,40 @@ void IUIScene_CreativeMenu::staticCtor()
ITEM_AUX(Tile::woolCarpet_Id,13) // Green
ITEM_AUX(Tile::woolCarpet_Id,12) // Brown
ITEM_AUX(Tile::stained_glass_Id,14) // Red
ITEM_AUX(Tile::stained_glass_Id,1) // Orange
ITEM_AUX(Tile::stained_glass_Id,4) // Yellow
ITEM_AUX(Tile::stained_glass_Id,5) // Lime
ITEM_AUX(Tile::stained_glass_Id,3) // Light Blue
ITEM_AUX(Tile::stained_glass_Id,9) // Cyan
ITEM_AUX(Tile::stained_glass_Id,11) // Blue
ITEM_AUX(Tile::stained_glass_Id,10) // Purple
ITEM_AUX(Tile::stained_glass_Id,2) // Magenta
ITEM_AUX(Tile::stained_glass_Id,6) // Pink
ITEM_AUX(Tile::stained_glass_Id,0) // White
ITEM_AUX(Tile::stained_glass_Id,8) // Light Gray
ITEM_AUX(Tile::stained_glass_Id,7) // Gray
ITEM_AUX(Tile::stained_glass_Id,15) // Black
ITEM_AUX(Tile::stained_glass_Id,13) // Green
ITEM_AUX(Tile::stained_glass_Id,12) // Brown
ITEM_AUX(Tile::stained_glass_pane_Id,14) // Red
ITEM_AUX(Tile::stained_glass_pane_Id,1) // Orange
ITEM_AUX(Tile::stained_glass_pane_Id,4) // Yellow
ITEM_AUX(Tile::stained_glass_pane_Id,5) // Lime
ITEM_AUX(Tile::stained_glass_pane_Id,3) // Light Blue
ITEM_AUX(Tile::stained_glass_pane_Id,9) // Cyan
ITEM_AUX(Tile::stained_glass_pane_Id,11) // Blue
ITEM_AUX(Tile::stained_glass_pane_Id,10) // Purple
ITEM_AUX(Tile::stained_glass_pane_Id,2) // Magenta
ITEM_AUX(Tile::stained_glass_pane_Id,6) // Pink
ITEM_AUX(Tile::stained_glass_pane_Id,0) // White
ITEM_AUX(Tile::stained_glass_pane_Id,8) // Light Gray
ITEM_AUX(Tile::stained_glass_pane_Id,7) // Gray
ITEM_AUX(Tile::stained_glass_pane_Id,15) // Black
ITEM_AUX(Tile::stained_glass_pane_Id,13) // Green
ITEM_AUX(Tile::stained_glass_pane_Id,12) // Brown
#ifndef _CONTENT_PACKAGE
DEF(eCreativeInventory_ArtToolsDecorations)
if(app.DebugSettingsOn())
@@ -458,6 +492,16 @@ void IUIScene_CreativeMenu::staticCtor()
list->push_back(Item::enchantedBook->createForEnchantment(new EnchantmentInstance(enchantment, enchantment->getMaxLevel())));
}
#ifndef _CONTENT_PACKAGE
if(app.DebugSettingsOn())
{
shared_ptr<ItemInstance> debugSword = std::make_shared<ItemInstance>(Item::sword_diamond_Id, 1, 0);
debugSword->enchant( Enchantment::damageBonus, 50 );
debugSword->setHoverName(L"Sword of Debug");
list->push_back(debugSword);
}
#endif
// Materials
DEF(eCreativeInventory_Materials)
ITEM(Item::coal_Id)
+12 -2
View File
@@ -5,6 +5,8 @@
#include "../../../Minecraft.World/net.minecraft.world.item.h"
#include "../../../Minecraft.World/net.minecraft.world.entity.ai.attributes.h"
#include "../../../Minecraft.World/net.minecraft.world.entity.monster.h"
#include "../../MultiPlayerLevel.h"
#include "../../../Minecraft.World/LevelData.h"
#include "IUIScene_HUD.h"
#include "UI.h"
@@ -20,6 +22,7 @@ IUIScene_HUD::IUIScene_HUD()
m_lastMaxHealth = 20;
m_lastHealthBlink = false;
m_lastHealthPoison = false;
m_lastHealthHardcore = false;
m_iCurrentFood = -1;
m_lastFoodPoison = false;
m_lastAir = 10;
@@ -94,9 +97,10 @@ void IUIScene_HUD::updateFrameTick()
ShowHealth(false);
ShowFood(false);
ShowAir(false);
ShowArmour(false);
ShowArmour(false);
ShowExpBar(false);
SetHealthAbsorb(0);
SetHealthAbsorb(0);
SetHardcoreMode(false);
}
if(pMinecraft->localplayers[iPad]->isRidingJumpable())
@@ -206,6 +210,12 @@ void IUIScene_HUD::renderPlayerHealth()
// Update armour
int armor = pMinecraft->localplayers[iPad]->getArmorValue();
// Check hardcore mode
bool bHardcore = pMinecraft->level != nullptr
&& pMinecraft->level->getLevelData() != nullptr
&& pMinecraft->level->getLevelData()->isHardcore();
SetHardcoreMode(bHardcore);
SetHealth(currentHealth, oldHealth, blink, bHasPoison || bHasWither, bHasWither);
SetHealthAbsorb(totalAbsorption);
@@ -11,6 +11,7 @@ protected:
int m_iCurrentHealth;
int m_lastMaxHealth;
bool m_lastHealthBlink, m_lastHealthPoison, m_lastHealthWither;
bool m_lastHealthHardcore;
int m_iCurrentFood;
bool m_lastFoodPoison;
int m_lastAir, m_currentExtraAir;
@@ -46,6 +47,7 @@ protected:
virtual void SetActiveSlot(int slot) = 0;
virtual void SetHealth(int iHealth, int iLastHealth, bool bBlink, bool bPoison, bool bWither) = 0;
virtual void SetHardcoreMode(bool bHardcore) = 0;
virtual void SetFood(int iFood, int iLastFood, bool bPoison) = 0;
virtual void SetAir(int iAir, int extra) = 0;
virtual void SetArmour(int iArmour) = 0;
@@ -410,11 +410,72 @@ int IUIScene_PauseMenu::ExitWorldThreadProc( void* lpParameter )
return S_OK;
}
#ifdef _WINDOWS64
static bool Win64_DeleteSaveDirectory(const wchar_t* wPath)
{
wchar_t wSearch[MAX_PATH];
swprintf_s(wSearch, MAX_PATH, L"%s\\*", wPath);
WIN32_FIND_DATAW fd;
HANDLE hFind = FindFirstFileW(wSearch, &fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0) continue;
wchar_t wChild[MAX_PATH];
swprintf_s(wChild, MAX_PATH, L"%s\\%s", wPath, fd.cFileName);
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
Win64_DeleteSaveDirectory(wChild);
else
DeleteFileW(wChild);
} while (FindNextFileW(hFind, &fd));
FindClose(hFind);
}
return RemoveDirectoryW(wPath) != 0;
}
#endif // _WINDOWS64
// This function performs the meat of exiting from a level. It should be called from a thread other than the main thread.
void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
{
Minecraft *pMinecraft=Minecraft::GetInstance();
// 4J Added: Capture hardcore delete info before the server is destroyed
#ifdef _WINDOWS64
bool shouldDeleteHardcoreWorld = false;
wstring hardcoreSaveFolderName;
if (MinecraftServer::getInstance() != nullptr && MinecraftServer::getInstance()->getDeleteWorldOnExit())
{
shouldDeleteHardcoreWorld = true;
// Try 1: Use the save folder name stored by UIScene_LoadMenu::StartGameFromSave (works for existing saves)
hardcoreSaveFolderName = app.GetCurrentSaveFolderName();
if (!hardcoreSaveFolderName.empty())
{
app.DebugPrintf("Hardcore mode: save folder from app = '%ls'\n", hardcoreSaveFolderName.c_str());
}
// Try 2: StorageManager (may work for new saves after first autosave)
if (hardcoreSaveFolderName.empty())
{
char szSaveFolder[MAX_SAVEFILENAME_LENGTH] = {};
StorageManager.GetSaveUniqueFilename(szSaveFolder);
if (szSaveFolder[0] != '\0')
{
wchar_t wSaveFolder[MAX_SAVEFILENAME_LENGTH] = {};
mbstowcs(wSaveFolder, szSaveFolder, MAX_SAVEFILENAME_LENGTH - 1);
hardcoreSaveFolderName = wSaveFolder;
app.DebugPrintf("Hardcore mode: save folder from StorageManager = '%s'\n", szSaveFolder);
}
}
// Try 3: Stored during loadLevel
if (hardcoreSaveFolderName.empty())
{
hardcoreSaveFolderName = MinecraftServer::getInstance()->getSaveFolderName();
app.DebugPrintf("Hardcore mode: save folder from server = '%ls'\n", hardcoreSaveFolderName.c_str());
}
MinecraftServer::getInstance()->setDeleteWorldOnExit(false);
}
#endif
int exitReasonStringId = pMinecraft->progressRenderer->getCurrentTitle();
int exitReasonTitleId = IDS_CONNECTION_LOST;
@@ -625,6 +686,17 @@ void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
{
Sleep(1);
}
// 4J Added: Hardcore mode — delete world save data now that the server is fully stopped
#ifdef _WINDOWS64
if (shouldDeleteHardcoreWorld && !hardcoreSaveFolderName.empty())
{
wchar_t wFolderPath[MAX_PATH] = {};
swprintf_s(wFolderPath, MAX_PATH, L"Windows64\\GameHDD\\%s", hardcoreSaveFolderName.c_str());
app.DebugPrintf("Hardcore mode: Deleting world save folder '%ls'\n", wFolderPath);
Win64_DeleteSaveDirectory(wFolderPath);
}
#endif
pMinecraft->setLevel(nullptr,exitReasonStringId,nullptr,saveStats);
TelemetryManager->Flush();
+3 -13
View File
@@ -141,6 +141,9 @@ S32 UIBitmapFont::GetCodepointGlyph(U32 codepoint)
// 4J-JEV: Change "right single quotation marks" to apostrophies.
if (codepoint == 0x2019) codepoint = 0x27;
if (!m_cFontData->hasGlyph(codepoint))
return IGGY_GLYPH_INVALID;
return m_cFontData->getGlyphId(codepoint);
}
@@ -253,19 +256,6 @@ rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacte
while ( (0.5f + glyphScale) * truePixelScale < pixel_scale)
glyphScale++;
// Debug: log each unique (font, pixel_scale) pair
{
static std::unordered_set<int> s_loggedScaleKeys;
// Encode font pointer + quantized scale into a key to log each combo once
int scaleKey = (int)(pixel_scale * 100.0f) ^ (int)(uintptr_t)m_cFontData;
if (s_loggedScaleKeys.find(scaleKey) == s_loggedScaleKeys.end() && s_loggedScaleKeys.size() < 50) {
s_loggedScaleKeys.insert(scaleKey);
float tps = truePixelScale;
app.DebugPrintf("[FONT-DBG] GetGlyphBitmap: font=%s glyph=%d pixel_scale=%.3f truePixelScale=%.1f glyphScale=%.0f\n",
m_cFontData->getFontName().c_str(), glyph, pixel_scale, tps, glyphScale);
}
}
// 4J-JEV: Debug code to check which font sizes are being used.
#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0)
@@ -120,7 +120,7 @@ void UIComponent_PressStartToPlay::handleTimerComplete(int id)
for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i)
{
m_showingPressStart[i] = false;
if (id == 1) {
if (id == 1) {
HideAchievementToast();
killTimer(id);
ui.toastOn = false;
@@ -3,6 +3,7 @@
#include "UIScene.h"
#include "UIControl_Label.h"
class UIComponent_PressStartToPlay : public UIScene
{
private:
@@ -50,7 +51,7 @@ public:
// Returns true if lower scenes in this scenes layer, or in any layer below this scenes layers should be hidden
virtual bool hidesLowerScenes() { return false; }
void ShowAchievementToast(string achievementName, string achievementDescription, string achT = "");
void ShowAchievementToast(string achievementName, string achievementDescription, string achT = "");
void HideAchievementToast();
virtual void handleReload();
@@ -3,41 +3,41 @@
#include "UIComponent_Tooltips.h"
#include "UISplitScreenHelpers.h"
UIComponent_Tooltips::UIComponent_Tooltips(int iPad, void* initData, UILayer* parentLayer) : UIScene(iPad, parentLayer)
UIComponent_Tooltips::UIComponent_Tooltips(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
for (int i = 0; i < XUSER_MAX_COUNT; i++)
for(int i=0;i<XUSER_MAX_COUNT;i++)
{
for (int j = 0; j < ACTION_MAX_MENU; j++)
for(int j=0;j<ACTION_MAX_MENU;j++)
{
m_overrideSFX[i][j] = false;
m_overrideSFX[i][j]=false;
}
}
}
// Setup all the Iggy references we need for this scene
initialiseMovie();
#ifdef __PSVITA__
// initialise vita touch controls with ids
for (unsigned int i = 0; i < ETouchInput_Count; ++i)
for(unsigned int i = 0; i < ETouchInput_Count; ++i)
{
m_TouchController[i].init(i);
}
#endif
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
if (InputManager.IsCircleCrossSwapped())
if(InputManager.IsCircleCrossSwapped())
{
IggyDataValue result;
IggyDataValue value[1];
value[0].type = IGGY_DATATYPE_boolean;
value[0].boolval = true;
IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcSetABSwap, 1, value);
IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetABSwap , 1 , value );
}
#endif
}
wstring UIComponent_Tooltips::getMoviePath()
{
switch (m_parentLayer->getViewport())
switch( m_parentLayer->getViewport() )
{
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
@@ -66,7 +66,7 @@ F64 UIComponent_Tooltips::getSafeZoneHalfWidth()
#ifndef __PSVITA__
// 85% safezone for tooltips in either SD mode
if (!RenderManager.IsHiDef())
if( !RenderManager.IsHiDef() )
{
// 85% safezone
safeWidth = m_movieWidth * (0.15f / 2);
@@ -88,23 +88,27 @@ void UIComponent_Tooltips::updateSafeZone()
F64 safeLeft = 0.0;
F64 safeRight = 0.0;
switch (m_parentLayer->getViewport())
switch( m_parentLayer->getViewport() )
{
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
safeTop = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
safeBottom = getSafeZoneHalfHeight();
safeTop = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
safeLeft = getSafeZoneHalfWidth();
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
safeRight = getSafeZoneHalfWidth();
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
safeTop = getSafeZoneHalfHeight();
@@ -112,22 +116,22 @@ void UIComponent_Tooltips::updateSafeZone()
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
safeTop = getSafeZoneHalfHeight();
safeRight = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
safeBottom = getSafeZoneHalfHeight();
safeTop = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
safeBottom = getSafeZoneHalfHeight();
safeRight = getSafeZoneHalfWidth();
safeTop = getSafeZoneHalfHeight();
break;
case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
default:
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
safeRight = getSafeZoneHalfWidth();
break;
}
setSafeZone(safeTop, safeBottom, safeLeft, safeRight);
@@ -138,54 +142,54 @@ void UIComponent_Tooltips::tick()
UIScene::tick();
// set the opacity of the tooltip items
unsigned char ucAlpha = app.GetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_InterfaceOpacity);
unsigned char ucAlpha=app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_InterfaceOpacity);
float fVal;
if (ucAlpha < 80)
if(ucAlpha<80)
{
// if we are in a menu, set the minimum opacity for tooltips to 15%
if (ui.GetMenuDisplayed(m_iPad) && (ucAlpha < 15))
if(ui.GetMenuDisplayed(m_iPad) && (ucAlpha<15))
{
ucAlpha = 15;
ucAlpha=15;
}
// check if we have the timer running for the opacity
unsigned int uiOpacityTimer = app.GetOpacityTimer(m_iPad);
if (uiOpacityTimer != 0)
unsigned int uiOpacityTimer=app.GetOpacityTimer(m_iPad);
if(uiOpacityTimer!=0)
{
if (uiOpacityTimer < 10)
if(uiOpacityTimer<10)
{
float fStep = (80.0f - static_cast<float>(ucAlpha)) / 10.0f;
fVal = 0.01f * (80.0f - ((10.0f - static_cast<float>(uiOpacityTimer)) * fStep));
float fStep=(80.0f-static_cast<float>(ucAlpha))/10.0f;
fVal=0.01f*(80.0f-((10.0f-static_cast<float>(uiOpacityTimer))*fStep));
}
else
{
fVal = 0.01f * 80.0f;
fVal=0.01f*80.0f;
}
}
else
{
fVal = 0.01f * static_cast<float>(ucAlpha);
fVal=0.01f*static_cast<float>(ucAlpha);
}
}
else
{
// if we are in a menu, set the minimum opacity for tooltips to 15%
if (ui.GetMenuDisplayed(m_iPad) && (ucAlpha < 15))
if(ui.GetMenuDisplayed(m_iPad) && (ucAlpha<15))
{
ucAlpha = 15;
ucAlpha=15;
}
fVal = 0.01f * static_cast<float>(ucAlpha);
fVal=0.01f*static_cast<float>(ucAlpha);
}
setOpacity(fVal);
bool layoutChanges = false;
for (int i = 0; i < eToolTipNumButtons; i++)
{
if (!ui.IsReloadingSkin() && m_tooltipValues[i].show && m_tooltipValues[i].label.needsUpdating())
if ( !ui.IsReloadingSkin() && m_tooltipValues[i].show && m_tooltipValues[i].label.needsUpdating() )
{
layoutChanges = true;
_SetTooltip(i, m_tooltipValues[i].label, m_tooltipValues[i].show, true);
_SetTooltip(i, m_tooltipValues[i].label, m_tooltipValues[i].show, true);
m_tooltipValues[i].label.setUpdated();
}
}
@@ -194,29 +198,16 @@ void UIComponent_Tooltips::tick()
void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportType viewport)
{
//This is the proper flag for single player, NOT for all players
bool renderTooltipsOK = !((ProfileManager.GetLockedProfile() == -1) || (app.GetGameSettings(m_iPad, eGameSetting_Tooltips) == 0 || app.GetGameSettings(m_iPad, eGameSetting_DisplayHUD) == 0));
// However, if we are in the menu, we want to show the tooltips regardless of the tooltip setting so that players can navigate the menu and change the setting if they want to. So we will override the renderTooltipsOK flag if we are in a menu.
bool menuOKoverride = false;
Minecraft* pMinecraft = Minecraft::GetInstance();
if (pMinecraft != nullptr)
if((ProfileManager.GetLockedProfile()!=-1) && !ui.GetMenuDisplayed(m_iPad) && (app.GetGameSettings(m_iPad,eGameSetting_Tooltips)==0 || app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD)==0))
{
if (pMinecraft->level == nullptr || pMinecraft->player == nullptr)
{
menuOKoverride = true;
}
return;
}
if (m_bSplitscreen) {
//Individiualize the flags for each viewport :)
if(m_bSplitscreen)
{
S32 xPos = 0;
S32 yPos = 0;
switch (viewport)
switch( viewport )
{
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
@@ -231,7 +222,6 @@ void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportTyp
yPos = static_cast<S32>(ui.getScreenHeight() / 2);
break;
}
ui.setupRenderPosition(xPos, yPos);
S32 tileXStart = 0;
@@ -240,7 +230,7 @@ void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportTyp
S32 tileHeight = height;
bool needsYTile = false;
switch (viewport)
switch( viewport )
{
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
@@ -258,127 +248,88 @@ void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportTyp
needsYTile = true;
break;
}
// I'm not sure if this is a good way to iterate pads...
//Anyways, new pad based on render settings to differentiate splitscreen players
int plr_pad;
switch (viewport)
{
//Player zero;
case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
case C4JRender::VIEWPORT_TYPE_SPLIT_TOP:
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
plr_pad = m_iPad;
break;
//Player one;
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
plr_pad = 1;
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
plr_pad = 2;
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
plr_pad = 3;
break;
default:
plr_pad = -1;
break;
}
if (plr_pad == -1) {
renderTooltipsOK = false;
}
else {
renderTooltipsOK = (app.GetGameSettings(plr_pad, eGameSetting_Tooltips) != 0) && (app.GetGameSettings(plr_pad, eGameSetting_DisplayHUD) != 0);
}
m_renderWidth = tileWidth;
m_renderHeight = tileHeight;
F32 scale;
ComputeTileScale(tileWidth, tileHeight, m_movieWidth, m_movieHeight, needsYTile, scale, tileYStart);
// For vertical split, scale down to fit the full SWF height when the
// window is shorter than the movie (same fix as HUD).
if (!needsYTile && m_movieHeight > 0)
if(!needsYTile && m_movieHeight > 0)
{
F32 scaleH = (F32)tileHeight / (F32)m_movieHeight;
if (scaleH < scale)
if(scaleH < scale)
scale = scaleH;
}
IggyPlayerSetDisplaySize(getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale));
IggyPlayerSetDisplaySize( getMovie(), (S32)(m_movieWidth * scale), (S32)(m_movieHeight * scale) );
if (!renderTooltipsOK && !menuOKoverride) return;
IggyPlayerDrawTilesStart(getMovie());
IggyPlayerDrawTile(getMovie(),
tileXStart,
tileYStart,
tileXStart + tileWidth,
tileYStart + tileHeight,
0);
IggyPlayerDrawTilesEnd(getMovie());
IggyPlayerDrawTilesStart ( getMovie() );
m_renderWidth = tileWidth;
m_renderHeight = tileHeight;
IggyPlayerDrawTile ( getMovie() ,
tileXStart ,
tileYStart ,
tileXStart + tileWidth ,
tileYStart + tileHeight ,
0 );
IggyPlayerDrawTilesEnd ( getMovie() );
}
else
{
if (!renderTooltipsOK && !menuOKoverride) return;
UIScene::render(width, height, viewport);
}
}
void UIComponent_Tooltips::SetTooltipText(unsigned int tooltip, int iTextID)
void UIComponent_Tooltips::SetTooltipText( unsigned int tooltip, int iTextID )
{
if (_SetTooltip(tooltip, iTextID)) _Relayout();
if( _SetTooltip(tooltip, iTextID) ) _Relayout();
}
void UIComponent_Tooltips::SetEnableTooltips(bool bVal)
void UIComponent_Tooltips::SetEnableTooltips( bool bVal )
{
}
void UIComponent_Tooltips::ShowTooltip(unsigned int tooltip, bool show)
void UIComponent_Tooltips::ShowTooltip( unsigned int tooltip, bool show )
{
if (show != m_tooltipValues[tooltip].show)
if(show != m_tooltipValues[tooltip].show)
{
_SetTooltip(tooltip, L"", show);
_Relayout();
}
}
void UIComponent_Tooltips::SetTooltips(int iA, int iB, int iX, int iY, int iLT, int iRT, int iLB, int iRB, int iLS, int iRS, int iBack, bool forceUpdate)
void UIComponent_Tooltips::SetTooltips( int iA, int iB, int iX, int iY , int iLT, int iRT, int iLB, int iRB, int iLS, int iRS, int iBack, bool forceUpdate)
{
bool needsRelayout = false;
needsRelayout = _SetTooltip(eToolTipButtonA, iA) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonB, iB) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonX, iX) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonY, iY) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonLT, iLT) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonRT, iRT) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonLB, iLB) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonRB, iRB) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonLS, iLS) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonRS, iRS) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonRS, iRS) || needsRelayout;
needsRelayout = _SetTooltip(eToolTipButtonBack, iBack) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonA, iA ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonB, iB ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonX, iX ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonY, iY ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonLT, iLT ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonRT, iRT ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonLB, iLB ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonRB, iRB ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonLS, iLS ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonRS, iRS ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonRS, iRS ) || needsRelayout;
needsRelayout = _SetTooltip( eToolTipButtonBack, iBack ) || needsRelayout;
if (needsRelayout) _Relayout();
}
void UIComponent_Tooltips::EnableTooltip(unsigned int tooltip, bool enable)
void UIComponent_Tooltips::EnableTooltip( unsigned int tooltip, bool enable )
{
}
bool UIComponent_Tooltips::_SetTooltip(unsigned int iToolTip, int iTextID)
{
bool changed = false;
if (iTextID != m_tooltipValues[iToolTip].iString || (iTextID > -1 && !m_tooltipValues[iToolTip].show))
if(iTextID != m_tooltipValues[iToolTip].iString || (iTextID > -1 && !m_tooltipValues[iToolTip].show))
{
m_tooltipValues[iToolTip].iString = iTextID;
changed = true;
if (iTextID > -1) _SetTooltip(iToolTip, iTextID, true);
else if (iTextID == -2) _SetTooltip(iToolTip, L"", true);
if(iTextID > -1) _SetTooltip(iToolTip, iTextID, true);
else if(iTextID == -2) _SetTooltip(iToolTip, L"", true);
else _SetTooltip(iToolTip, L"", false);
}
return changed;
@@ -386,7 +337,7 @@ bool UIComponent_Tooltips::_SetTooltip(unsigned int iToolTip, int iTextID)
void UIComponent_Tooltips::_SetTooltip(unsigned int iToolTipId, UIString label, bool show, bool force)
{
if (!force && !show && !m_tooltipValues[iToolTipId].show)
if(!force && !show && !m_tooltipValues[iToolTipId].show)
{
return;
}
@@ -407,7 +358,7 @@ void UIComponent_Tooltips::_SetTooltip(unsigned int iToolTipId, UIString label,
value[2].type = IGGY_DATATYPE_boolean;
value[2].boolval = show;
IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcSetTooltip, 3, value);
IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetTooltip , 3 , value );
//app.DebugPrintf("Actual tooltip update!\n");
}
@@ -415,7 +366,7 @@ void UIComponent_Tooltips::_SetTooltip(unsigned int iToolTipId, UIString label,
void UIComponent_Tooltips::_Relayout()
{
IggyDataValue result;
IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcUpdateLayout, 0, nullptr);
IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcUpdateLayout, 0 , nullptr );
#ifdef __PSVITA__
// rebuild touchboxes
@@ -430,64 +381,64 @@ void UIComponent_Tooltips::handleTouchInput(unsigned int iPad, S32 x, S32 y, int
bool handled = false;
// 4J - TomK no tooltips no touch!
if ((!ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad())) && (app.GetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_Tooltips) == 0))
if((!ui.GetMenuDisplayed(ProfileManager.GetPrimaryPad())) && (app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Tooltips) == 0))
return;
// perform action on release
if (bReleased)
if(bReleased)
{
switch (iId)
switch(iId)
{
case ETouchInput_Touch_A:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_X\n", iId);
if (InputManager.IsCircleCrossSwapped())
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_O);
else
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_X);
break;
case ETouchInput_Touch_B:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_O\n", iId);
if (InputManager.IsCircleCrossSwapped())
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_X);
else
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_O);
break;
case ETouchInput_Touch_X:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_SQUARE\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_SQUARE);
break;
case ETouchInput_Touch_Y:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_TRIANGLE\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_TRIANGLE);
break;
case ETouchInput_Touch_LT:
/* not in use on vita */
app.DebugPrintf("ToolTip no action\n", iId);
break;
case ETouchInput_Touch_RightTrigger:
app.DebugPrintf("ToolTip no action\n", iId);
/* no action */
break;
case ETouchInput_Touch_LeftBumper:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_L1\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_L1);
break;
case ETouchInput_Touch_RightBumper:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_R1\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_R1);
break;
case ETouchInput_Touch_LeftStick:
app.DebugPrintf("ToolTip no action\n", iId);
/* no action */
break;
case ETouchInput_Touch_RightStick:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_DPAD_DOWN\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_DPAD_DOWN);
break;
case ETouchInput_Touch_Select:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_SELECT\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_SELECT);
break;
case ETouchInput_Touch_A:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_X\n", iId);
if(InputManager.IsCircleCrossSwapped())
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_O);
else
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_X);
break;
case ETouchInput_Touch_B:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_O\n", iId);
if(InputManager.IsCircleCrossSwapped())
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_X);
else
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_O);
break;
case ETouchInput_Touch_X:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_SQUARE\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_SQUARE);
break;
case ETouchInput_Touch_Y:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_TRIANGLE\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_TRIANGLE);
break;
case ETouchInput_Touch_LT:
/* not in use on vita */
app.DebugPrintf("ToolTip no action\n", iId);
break;
case ETouchInput_Touch_RightTrigger:
app.DebugPrintf("ToolTip no action\n", iId);
/* no action */
break;
case ETouchInput_Touch_LeftBumper:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_L1\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_L1);
break;
case ETouchInput_Touch_RightBumper:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_R1\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_R1);
break;
case ETouchInput_Touch_LeftStick:
app.DebugPrintf("ToolTip no action\n", iId);
/* no action */
break;
case ETouchInput_Touch_RightStick:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_DPAD_DOWN\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_DPAD_DOWN);
break;
case ETouchInput_Touch_Select:
app.DebugPrintf("ToolTip Map Touch to _PSV_JOY_BUTTON_SELECT\n", iId);
InputManager.MapTouchInput(iPad, _PSV_JOY_BUTTON_SELECT);
break;
}
}
}
@@ -498,29 +449,29 @@ void UIComponent_Tooltips::handleReload()
app.DebugPrintf("UIComponent_Tooltips::handleReload\n");
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
if (InputManager.IsCircleCrossSwapped())
if(InputManager.IsCircleCrossSwapped())
{
IggyDataValue result;
IggyDataValue value[1];
value[0].type = IGGY_DATATYPE_boolean;
value[0].boolval = true;
IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcSetABSwap, 1, value);
IggyResult out = IggyPlayerCallMethodRS ( getMovie() , &result, IggyPlayerRootPath( getMovie() ), m_funcSetABSwap , 1 , value );
}
#endif
for (unsigned int i = 0; i < eToolTipNumButtons; ++i)
for(unsigned int i = 0; i < eToolTipNumButtons; ++i)
{
_SetTooltip(i, m_tooltipValues[i].iString, m_tooltipValues[i].show, true);
}
_Relayout();
}
void UIComponent_Tooltips::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool& handled)
void UIComponent_Tooltips::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
{
if ((0 <= iPad) && (iPad <= 3) && m_overrideSFX[iPad][key])
if( (0 <= iPad) && (iPad <= 3) && m_overrideSFX[iPad][key] )
{
// don't play a sound for this action
switch (key)
switch(key)
{
case ACTION_MENU_A:
case ACTION_MENU_OK:
@@ -542,7 +493,7 @@ void UIComponent_Tooltips::handleInput(int iPad, int key, bool repeat, bool pres
}
else
{
switch (key)
switch(key)
{
case ACTION_MENU_OK:
case ACTION_MENU_CANCEL:
@@ -567,7 +518,7 @@ void UIComponent_Tooltips::handleInput(int iPad, int key, bool repeat, bool pres
/*if(pressed)
{
ui.PlayUISFX(eSFX_Back);
}*/
}*/
sendInputToMovie(key, repeat, pressed, released);
break;
@@ -594,5 +545,5 @@ void UIComponent_Tooltips::handleInput(int iPad, int key, bool repeat, bool pres
void UIComponent_Tooltips::overrideSFX(int iPad, int key, bool bVal)
{
m_overrideSFX[iPad][key] = bVal;
}
m_overrideSFX[iPad][key]=bVal;
}
+11 -4
View File
@@ -3,6 +3,7 @@
#include "UIControl.h"
#include "../../../Minecraft.World/StringHelpers.h"
#include "../../../Minecraft.World/JavaMath.h"
#include "../../../Minecraft.World/ArabicShaping.h"
UIControl_Base::UIControl_Base()
{
@@ -32,13 +33,16 @@ void UIControl_Base::tick()
//app.DebugPrintf("Calling SetLabel - '%ls'\n", m_label.c_str());
m_bLabelChanged = false;
// Shape the text before sending to Iggy; m_label stays unshaped for future updates
wstring shaped = shapeArabicText(m_label.getString());
IggyDataValue result;
IggyDataValue value[1];
value[0].type = IGGY_DATATYPE_string_UTF16;
IggyStringUTF16 stringVal;
stringVal.string = (IggyUTF16*) m_label.c_str();
stringVal.length = m_label.length();
stringVal.string = (IggyUTF16*) shaped.c_str();
stringVal.length = (int)shaped.length();
value[0].string16 = stringVal;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
@@ -56,13 +60,16 @@ void UIControl_Base::setLabel(UIString label, bool instant, bool force)
{
m_bLabelChanged = false;
// Shape the text before sending to Iggy; m_label stays unshaped for future updates
wstring shaped = shapeArabicText(m_label.getString());
IggyDataValue result;
IggyDataValue value[1];
value[0].type = IGGY_DATATYPE_string_UTF16;
IggyStringUTF16 stringVal;
stringVal.string = (IggyUTF16*)m_label.c_str();
stringVal.length = m_label.length();
stringVal.string = (IggyUTF16*) shaped.c_str();
stringVal.length = (int)shaped.length();
value[0].string16 = stringVal;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
@@ -9,6 +9,7 @@ UIControl_BeaconEffectButton::UIControl_BeaconEffectButton()
m_selected = false;
m_active = false;
m_focus = false;
m_lastState = eState_Disabled;
}
bool UIControl_BeaconEffectButton::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName)
@@ -2,6 +2,7 @@
#include "UI.h"
#include "UIControl_Label.h"
#include "../../../Minecraft.World/StringHelpers.h"
#include "../../../Minecraft.World/ArabicShaping.h"
UIControl_Label::UIControl_Label()
{
@@ -22,13 +23,15 @@ void UIControl_Label::init(UIString label)
{
m_label = label;
wstring shaped = shapeArabicText(m_label.getString());
IggyDataValue result;
IggyDataValue value[1];
value[0].type = IGGY_DATATYPE_string_UTF16;
IggyStringUTF16 stringVal;
stringVal.string = (IggyUTF16*)label.c_str();
stringVal.length = label.length();
stringVal.string = (IggyUTF16*)shaped.c_str();
stringVal.length = (int)shaped.length();
value[0].string16 = stringVal;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value );
}
@@ -13,6 +13,56 @@
//#define SKIN_PREVIEW_BOB_ANIM
#define SKIN_PREVIEW_WALKING_ANIM
#ifdef _WINDOWS64
// Frame-rate-independent animation scaling.
// The skin preview animations were designed for ~60fps (VSync on).
// With uncapped FPS, each frame's contribution must be scaled down.
// The scale is computed once per frame (keyed by frame counter) so
// that multiple skin previews rendered in the same frame all use the
// same value instead of measuring near-zero deltas between each other.
static float s_skinAnimCachedScale = 1.0f;
static double s_skinAnimLastTime = 0.0;
static double s_skinAnimFreqInv = 0.0;
static float GetSkinAnimDeltaScale()
{
// Use the main loop's frame counter to detect a new frame.
// GetTickCount changes every ~16ms, but we need per-frame detection.
// Use a simple time threshold: if <0.1ms since last call, same frame.
if (s_skinAnimFreqInv == 0.0)
{
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
s_skinAnimFreqInv = 1.0 / (double)freq.QuadPart;
}
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
double currentTime = (double)now.QuadPart * s_skinAnimFreqInv;
// If less than 0.5ms since last call, assume same frame -- reuse cached scale
double elapsed = currentTime - s_skinAnimLastTime;
if (s_skinAnimLastTime != 0.0 && elapsed < 0.0005)
{
return s_skinAnimCachedScale;
}
if (s_skinAnimLastTime == 0.0)
{
s_skinAnimLastTime = currentTime;
s_skinAnimCachedScale = 1.0f;
return 1.0f;
}
s_skinAnimLastTime = currentTime;
const double kBaselineFrameTime = 1.0 / 60.0;
float scale = static_cast<float>(elapsed / kBaselineFrameTime);
if (scale > 3.0f) scale = 3.0f;
s_skinAnimCachedScale = scale;
return scale;
}
#endif
UIControl_PlayerSkinPreview::UIControl_PlayerSkinPreview()
{
UIControl::setControlType(UIControl::ePlayerSkinPreview);
@@ -287,7 +337,11 @@ void UIControl_PlayerSkinPreview::render(EntityRenderer *renderer, double x, dou
break;
case e_SkinPreviewAnimation_Attacking:
model->holdingRightHand = true;
#ifdef _WINDOWS64
m_swingTime += GetSkinAnimDeltaScale();
#else
m_swingTime++;
#endif
if (m_swingTime >= (Player::SWING_DURATION * 3) )
{
m_swingTime = 0;
@@ -340,8 +394,16 @@ void UIControl_PlayerSkinPreview::render(EntityRenderer *renderer, double x, dou
#ifdef SKIN_PREVIEW_WALKING_ANIM
m_walkAnimSpeedO = m_walkAnimSpeed;
#ifdef _WINDOWS64
{
float animScale = GetSkinAnimDeltaScale();
m_walkAnimSpeed += (0.1f - m_walkAnimSpeed) * 0.4f * animScale;
m_walkAnimPos += m_walkAnimSpeed * animScale;
}
#else
m_walkAnimSpeed += (0.1f - m_walkAnimSpeed) * 0.4f;
m_walkAnimPos += m_walkAnimSpeed;
#endif
float ws = m_walkAnimSpeedO + (m_walkAnimSpeed - m_walkAnimSpeedO) * a;
float wp = m_walkAnimPos - m_walkAnimSpeed * (1 - a);
#else
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIControl_SaveList.h"
#include "../../../Minecraft.World/ArabicShaping.h"
bool UIControl_SaveList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName)
{
@@ -69,12 +70,14 @@ void UIControl_SaveList::addItem(const string &label, const wstring &iconName, i
void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName, int data)
{
wstring shaped = shapeArabicText(label);
IggyDataValue result;
IggyDataValue value[3];
IggyStringUTF16 stringVal;
stringVal.string = (IggyUTF16*)label.c_str();
stringVal.length = static_cast<S32>(label.length());
stringVal.string = (IggyUTF16*)shaped.c_str();
stringVal.length = static_cast<S32>(shaped.length());
value[0].type = IGGY_DATATYPE_string_UTF16;
value[0].string16 = stringVal;
@@ -220,7 +220,7 @@ UIControl_TextInput::EDirectEditResult UIControl_TextInput::tickDirectEdit()
sanitized.reserve(pasted.length());
for (wchar_t pc : pasted)
{
{
if (pc >= 0x20) // Keep printable characters
{
if (m_iCharLimit > 0 && (m_editBuffer.length() + sanitized.length()) >= (size_t)m_iCharLimit)
+15 -12
View File
@@ -16,6 +16,7 @@
#include "../../EnderDragonRenderer.h"
#include "../../MultiPlayerLocalPlayer.h"
#include "UIFontData.h"
#include "UIUnicodeBitmapFont.h"
#include "UISplitScreenHelpers.h"
#ifdef _WINDOWS64
#include "../../Windows64/KeyboardMouseInput.h"
@@ -196,6 +197,7 @@ UIController::UIController()
m_mcTTFFont = nullptr;
m_moj7 = nullptr;
m_moj11 = nullptr;
m_unicodeBitmapFont = nullptr;
// 4J-JEV: It's important that these remain the same, unless updateCurrentLanguage is going to be called.
m_eCurrentFont = m_eTargetFont = eFont_NotLoaded;
@@ -310,6 +312,14 @@ void UIController::postInit()
IggySetAS3ExternalFunctionCallbackUTF16 ( &UIController::ExternalFunctionCallback, this );
IggySetTextureSubstitutionCallbacks ( &UIController::TextureSubstitutionCreateCallback , &UIController::TextureSubstitutionDestroyCallback, this );
// Load a unicode bitmap font as Iggy's global fallback for characters not
// covered by the Mojangles bitmap font (CJK, Thai, Arabic, Korean, etc.).
// Uses the same glyph page PNGs as the legacy Font class, with matching
// Mojangles metrics for correct vertical alignment.
m_unicodeBitmapFont = new UIUnicodeBitmapFont("Mojangles_Unicode_Bitmap", SFontData::Mojangles_7);
m_unicodeBitmapFont->registerFont();
IggyFontSetFallbackFontUTF8("Mojangles_Unicode_Bitmap", -1, IGGY_FONTFLAG_none);
SetupFont();
//
loadSkins();
@@ -582,9 +592,6 @@ void UIController::loadSkins()
m_iggyLibraries[eLibrary_HUD] = loadSkin(L"skinHDHud.swf", L"skinHDHud.swf");
m_iggyLibraries[eLibrary_Tooltips] = loadSkin(L"skinHDTooltips.swf", L"skinHDTooltips.swf");
m_iggyLibraries[eLibrary_Default] = loadSkin(L"skinHD.swf", L"skinHD.swf");
//Load skins specifcally edited for use on achievements, if we
//used these as skin.swf and skinInGame.swf it breaks some other things
m_iggyLibraries[eLibrary_LCDefault] = loadSkin(L"skinLC.swf", L"skinLC.swf");
m_iggyLibraries[eLibrary_LCInGame] = loadSkin(L"skinInGameLC.swf", L"skinInGameLC.swf");
@@ -931,7 +938,7 @@ void UIController::tickInput()
UIControl::eUIControlType type = ctrl->getControlType();
if (type != UIControl::eButton && type != UIControl::eTextInput &&
type != UIControl::eCheckBox && type != UIControl::eSlider &&
type != UIControl::eButtonList && type != UIControl::eTexturePackList && type != UIControl::eAchievementList)
type != UIControl::eButtonList && type != UIControl::eAchievementList)
continue;
// If the scene has an active panel (e.g. tab menus),
@@ -965,7 +972,7 @@ void UIController::tickInput()
hitCtrl = NULL;
break; // ButtonList takes priority
}
if (type == UIControl::eAchievementList)
if (type == UIControl::eAchievementList)
{
auto t = (UIScene_AchievementsMenu*)pScene;
static_cast<UIControl_AchievementsList*>(ctrl)->SetTouchFocus(
@@ -1848,11 +1855,9 @@ GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void *
image.preMultiplyAlpha();
Textures *t = Minecraft::GetInstance()->textures;
int id = t->getTexture(&image,C4JRender::TEXTURE_FORMAT_RxGyBzAw,false);
std::string result(texture_name, texture_name + wcslen(texture_name));
std::string result(texture_name, texture_name + wcslen(texture_name));
bool isSub = result.find("sub") != std::string::npos;
// 4J Stu - All our flash controls that allow replacing textures use a special 64x64 symbol
// Force this size here so that our images don't get scaled wildly
#if (defined __ORBIS__ || defined _DURANGO )
@@ -1866,15 +1871,13 @@ GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void *
#if defined _WINDOWS64
// Only set the size to 96x96 for 1080p on Windows
UIScene *scene = uiController->GetTopScene(0);
//Fix for icon size changing on Achievements
if (scene) {
if (scene->getSceneResolution() == UIScene::eSceneResolution_1080 && (scene->getSceneType() != eUIScene_PauseMenu && scene->getSceneType() != eUIScene_MainMenu && scene->getSceneType() != eUIScene_AchievementsMenu) && isSub == false)
if (scene) {
if (scene->getSceneResolution() == UIScene::eSceneResolution_1080 && (scene->getSceneType() != eUIScene_PauseMenu && scene->getSceneType() != eUIScene_MainMenu && scene->getSceneType() != eUIScene_AchievementsMenu) && isSub == false)
{
*width = 96;
*height = 96;
}
}
#endif
*destroy_callback_data = (void *)id;
+3 -2
View File
@@ -7,6 +7,7 @@ using namespace std;
class UIAbstractBitmapFont;
class UIBitmapFont;
class UIUnicodeBitmapFont;
class UITTFFont;
class UIComponent_DebugUIConsole;
class UIComponent_DebugUIMarketingGuide;
@@ -19,7 +20,6 @@ public:
static int64_t iggyAllocCount;
bool toastOn = false;
// MGH - added to prevent crash loading Iggy movies while the skins were being reloaded
static CRITICAL_SECTION ms_reloadSkinCS;
static bool ms_bReloadSkinCSInitialised;
@@ -65,6 +65,7 @@ private:
UIAbstractBitmapFont *m_mcBitmapFont;
UITTFFont *m_mcTTFFont;
UIBitmapFont *m_moj7, *m_moj11;
UIUnicodeBitmapFont *m_unicodeBitmapFont;
std::mt19937 m_randomGenerator;
std::uniform_real_distribution<float> m_randomDistribution;
@@ -102,6 +103,7 @@ private:
eLibrary_HUD,
eLibrary_Tooltips,
eLibrary_Default,
eLibrary_LCDefault,
eLibrary_LCInGame,
@@ -204,7 +206,6 @@ protected:
public:
auto& getGroups() { return m_groups; }
void showComponent(int iPad, EUIScene scene, EUILayer layer, EUIGroup group, bool show)
{
m_groups[group]->showComponent(iPad, scene, layer, show);
@@ -335,6 +335,11 @@ bool CFontData::unicodeIsWhitespace(unsigned int unicode)
return false;
}
bool CFontData::hasGlyph(unsigned int unicodepoint)
{
return m_unicodeMap.find(unicodepoint) != m_unicodeMap.end();
}
void CFontData::moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy)
{
cursor += (dy * m_sFontData->m_uiGlyphMapX) + dx;
+3
View File
@@ -125,6 +125,9 @@ public:
// Returns true if this unicodepoint is whitespace
bool unicodeIsWhitespace(unsigned int unicodepoint);
// Returns true if this unicodepoint exists in the font's glyph map.
bool hasGlyph(unsigned int unicodepoint);
private:
// Move a pointer in an image dx pixels right and dy pixels down, wrap around in either dimension leads to unknown behaviour.
+12 -5
View File
@@ -2,7 +2,6 @@
#include "UI.h"
#include "UIScene.h"
#include "UISplitScreenHelpers.h"
#include "../../Lighting.h"
#include "../../LocalPlayer.h"
#include "../../ItemRenderer.h"
@@ -310,19 +309,27 @@ void UIScene::loadMovie()
if(!app.hasArchiveFile(moviePath))
{
app.DebugPrintf("WARNING: Could not find iggy movie %ls, falling back on 720\n", moviePath.c_str());
app.DebugPrintf("WARNING: Could not find iggy movie %ls, trying other resolutions\n", moviePath.c_str());
// Try 720 first, then 1080 as final fallback
moviePath = getMoviePath();
moviePath.append(L"720.swf");
m_loadedResolution = eSceneResolution_720;
if(!app.hasArchiveFile(moviePath))
{
app.DebugPrintf("ERROR: Could not find any iggy movie for %ls!\n", moviePath.c_str());
moviePath = getMoviePath();
moviePath.append(L"1080.swf");
m_loadedResolution = eSceneResolution_1080;
if(!app.hasArchiveFile(moviePath))
{
app.DebugPrintf("ERROR: Could not find any iggy movie for %ls!\n", moviePath.c_str());
#ifndef _CONTENT_PACKAGE
DEBUG_BREAK();
DEBUG_BREAK();
#endif
app.FatalLoadError();
app.FatalLoadError();
}
}
}
@@ -8,12 +8,15 @@
#include "StatsCounter.h"
#include "MultiPlayerLocalPlayer.h"
#include "Windows64/KeyboardMouseInput.h"
#include "UIControl_Label.h"
extern HWND g_hWnd;
UIScene_AchievementsMenu::UIScene_AchievementsMenu(int iPad, void* _initData, UILayer* parentLayer) : UIScene(iPad, parentLayer)
{
// Setup all the Iggy references we need for this scene
initialiseMovie();
/*RECT rc;
GetClientRect(g_hWnd, &rc);
POINT center;
@@ -21,7 +24,8 @@ UIScene_AchievementsMenu::UIScene_AchievementsMenu(int iPad, void* _initData, UI
center.y = rc.top;
ClientToScreen(g_hWnd, &center);
SetCursorPos(center.x, center.y);*/
m_labelAchievements.init(app.GetString(IDS_ACHIEVEMENTS));
m_labelAchievements.init(L"Achievements");
//m_labelDesc.init(L"");
m_labelName.init(L"");
m_achievementsList.init(0);
@@ -31,16 +35,19 @@ UIScene_AchievementsMenu::UIScene_AchievementsMenu(int iPad, void* _initData, UI
{
std::wstring iconStr(Achievements::achievements->at(i)->iconInt.begin(),
Achievements::achievements->at(i)->iconInt.end());
path = L"Graphics\\Achievements\\TROP" +
(iconStr.empty() ? L"000" : iconStr) +
L".png";
byteArray ba = app.getArchiveFile(path);
registerSubstitutionTexture(path, ba.data, ba.length);
}
std::string result = "Graphics\\Achievements\\" "TROP" + Achievements::achievements->at(i)->iconInt + ".png"; //media\\
m_achievementsList.addnewItem(i+1, path);
int newPad = 0;
int newPad = 0;
if (Minecraft::GetInstance()->player != nullptr) {
newPad = Minecraft::GetInstance()->player->GetXboxPad();
}
@@ -54,21 +61,27 @@ UIScene_AchievementsMenu::UIScene_AchievementsMenu(int iPad, void* _initData, UI
}
}
m_funcSetDesc = registerFastName(L"SetAchievementDescription");
m_achievementsList.setCurrentSelection(Minecraft::GetInstance()->achID + 1);
m_achievementsList.m_iCurrentSelection = Minecraft::GetInstance()->achID + 1;
}
void UIScene_AchievementsMenu::handleDestroy()
{
m_parentLayer->showComponent(m_iPad, eUIComponent_MenuBackground, false);
m_parentLayer->showComponent(m_iPad, eUIComponent_MenuBackground, false);
}
void UIScene_AchievementsMenu::SetAchievementDescription(wstring desc) {
wstring desc2 = L"";
if (desc != L"") {
HtmlString test = HtmlString(desc, eHTMLColor_White);
vector<HtmlString>* lines = new vector<HtmlString>();
lines->push_back(test);
desc2 = HtmlString::Compose(lines);
}
IggyDataValue result;
IggyDataValue value[1];
IggyStringUTF16 stringVal1;
@@ -76,8 +89,10 @@ void UIScene_AchievementsMenu::SetAchievementDescription(wstring desc) {
stringVal1.string = (IggyUTF16*)desc2.c_str();
stringVal1.length = desc2.length();
value[0].string16 = stringVal1;
IggyResult out = IggyPlayerCallMethodRS(getMovie(), &result, IggyPlayerRootPath(getMovie()), m_funcSetDesc, 1, value);
}
wstring UIScene_AchievementsMenu::getMoviePath()
{
if (app.GetLocalPlayerCount() > 1)
@@ -89,6 +104,7 @@ wstring UIScene_AchievementsMenu::getMoviePath()
return L"AchievementsMenu";
}
}
void UIScene_AchievementsMenu::updateComponents()
{
bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
@@ -97,7 +113,9 @@ void UIScene_AchievementsMenu::updateComponents()
m_parentLayer->showComponent(m_iPad, eUIComponent_MenuBackground, true);
}
m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, false);
}
void UIScene_AchievementsMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool& handled)
{
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
@@ -109,6 +127,7 @@ void UIScene_AchievementsMenu::handleInput(int iPad, int key, bool repeat, bool
case ACTION_MENU_Y:
if (pressed) {
showDescription = !showDescription;
if (showDescription) {
SetAchievementDescription(app.GetString(Achievements::achievements->at(m_achievementsList.m_iCurrentSelection - 1)->descID));
}
@@ -156,8 +175,10 @@ void UIScene_AchievementsMenu::handleInput(int iPad, int key, bool repeat, bool
handled = true;
break;
}
//m_achievementsList.updateChildFocus(static_cast<int>(childId));
};
void UIScene_AchievementsMenu::getMouseToSWFScale(float& scaleX, float& scaleY)
{
extern HWND g_hWnd;
@@ -166,16 +187,19 @@ void UIScene_AchievementsMenu::getMouseToSWFScale(float& scaleX, float& scaleY)
int winW = rc.right - rc.left;
int winH = rc.bottom - rc.top;
if (winW <= 0 || winH <= 0) { scaleX = 1.0f; scaleY = 1.0f; return; }
S32 renderW, renderH;
C4JRender::eViewportType vp = GetParentLayer()->getViewport();
ui.getRenderDimensions(vp, renderW, renderH);
if (vp != C4JRender::VIEWPORT_TYPE_FULLSCREEN)
Fit16x9(renderW, renderH);
float screenW = (float)ui.getScreenWidth();
float screenH = (float)ui.getScreenHeight();
scaleX = static_cast<float>(m_movieWidth) * screenW / (static_cast<float>(renderW) * static_cast<float>(winW));
scaleY = static_cast<float>(m_movieHeight) * screenH / (static_cast<float>(renderH) * static_cast<float>(winH));
}
void UIScene_AchievementsMenu::tick()
{
UIScene::tick();
@@ -183,6 +207,7 @@ void UIScene_AchievementsMenu::tick()
//m_cursorPath1.setVisible(g_KBMInput.IsKBMActive());
//g_KBMInput.SetMouseGrabbed(false);
if (m_achievementsList.m_iCurrentSelection != selection && m_achievementsList.m_iCurrentSelection != 0) {
m_achievementsList.setCurrentSelection(m_achievementsList.m_iCurrentSelection - 1);
m_labelName.setLabel(app.GetString(Achievements::achievements->at(m_achievementsList.m_iCurrentSelection - 1)->nameID));
@@ -193,20 +218,24 @@ void UIScene_AchievementsMenu::tick()
SetAchievementDescription(L"");
}
}
// Apply mouse delta
/*int deltaX = g_KBMInput.GetMouseDeltaX();
int deltaY = g_KBMInput.GetMouseDeltaY();
if (deltaX != 0 || deltaY != 0)
{
float scaleX, scaleY;
getMouseToSWFScale(scaleX, scaleY);
m_pointerPos.x += static_cast<float>(deltaX) * scaleX / 2;
m_pointerPos.y += static_cast<float>(deltaY) * scaleY / 2;
if (m_pointerPos.x < 0.0f) m_pointerPos.x = 0.0f;
if (m_pointerPos.x > static_cast<float>(m_movieWidth)) m_pointerPos.x = static_cast<float>(m_movieWidth);
if (m_pointerPos.y < 0.0f) m_pointerPos.y = 0.0f;
if (m_pointerPos.y > static_cast<float>(m_movieHeight)) m_pointerPos.y = static_cast<float>(m_movieHeight);
}
IggyEvent mouseEvent;
S32 width, height;
m_parentLayer->getRenderDimensions(width, height);
@@ -217,12 +246,15 @@ void UIScene_AchievementsMenu::tick()
IggyMakeEventMouseMove(&mouseEvent, x, y);
IggyEventResult result;
IggyPlayerDispatchEventRS(getMovie(), &mouseEvent, &result);*/
selection = m_achievementsList.m_iCurrentSelection;
}
void UIScene_AchievementsMenu::updateTooltips()
{
ui.SetTooltips(m_iPad, -1, IDS_TOOLTIPS_CANCEL, -1, IDS_TOOLTIPS_SHOW_DESCRIPTION);
}
void UIScene_AchievementsMenu::handleFocusChange(F64 controlId, F64 childId)
{
switch (static_cast<int>(controlId))
@@ -1,13 +1,16 @@
#pragma once
#include <string>
#include "Common/UI/UIScene.h"
#include "Common/UI/UIControl_Button.h"
#include "Common/UI/UIControl_Cursor.h"
#include "UIControl_AchievementsList.h"
#include "Common/UI/UIControl_Label.h"
#include "UIControl_Label.h"
class UIScene_AchievementsMenu : public UIScene
{
private:
enum EControls
{
eControl_AchievementsLabel,
@@ -33,8 +36,10 @@ private:
UI_MAP_ELEMENT(m_achievementsList, "AchievementsList")
UI_END_MAP_CHILD_ELEMENTS()
UI_END_MAP_ELEMENTS_AND_NAMES()
bool showDescription = false;
public:
struct SceneMousePos
{
@@ -57,7 +62,8 @@ public:
virtual void handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool& handled);
virtual void handleFocusChange(F64 controlId, F64 childId);
virtual void updateComponents();
virtual void updateTooltips();
protected:
virtual wstring getMoviePath();
};
};
@@ -4,7 +4,6 @@
#include "../../Minecraft.h"
#ifdef _WINDOWS64
#include "../../Windows64/Network/WinsockNetLayer.h"
#include "../../../Minecraft.World/DisconnectPacket.h"
static int ConnectingProgress_OnRejectedDialogOK(LPVOID, int iPad, const C4JStorage::EMessageResult)
{
@@ -53,10 +52,10 @@ UIScene_ConnectingProgress::UIScene_ConnectingProgress(int iPad, void *_initData
m_cancelFuncParam = param->cancelFuncParam;
m_removeLocalPlayer = false;
m_showingButton = false;
#ifdef _WINDOWS64
WinsockNetLayer::eJoinState initState = WinsockNetLayer::GetJoinState();
m_asyncJoinActive = (initState != WinsockNetLayer::eJoinState_Idle && initState != WinsockNetLayer::eJoinState_Cancelled);
m_asyncJoinActive = (initState == WinsockNetLayer::eJoinState_Connecting ||
initState == WinsockNetLayer::eJoinState_Success);
m_asyncJoinFailed = false;
#endif
}
@@ -72,12 +71,12 @@ void UIScene_ConnectingProgress::updateTooltips()
#ifdef _WINDOWS64
if (m_asyncJoinActive)
{
ui.SetTooltips( m_iPad, -1, IDS_TOOLTIPS_BACK);
ui.SetTooltips(m_iPad, -1, IDS_TOOLTIPS_BACK);
return;
}
if (m_asyncJoinFailed)
{
ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT, -1);
ui.SetTooltips(m_iPad, IDS_TOOLTIPS_SELECT, -1);
return;
}
#endif
@@ -94,78 +93,54 @@ void UIScene_ConnectingProgress::tick()
if (m_asyncJoinActive)
{
WinsockNetLayer::eJoinState state = WinsockNetLayer::GetJoinState();
if (state == WinsockNetLayer::eJoinState_Connecting)
switch (state)
{
case WinsockNetLayer::eJoinState_Connecting:
{
// connecting.............
int attempt = WinsockNetLayer::GetJoinAttempt();
int maxAttempts = WinsockNetLayer::GetJoinMaxAttempts();
char buf[128];
if (attempt <= 1)
sprintf_s(buf, "Connecting...");
wchar_t buf[128];
if (attempt > 1)
swprintf_s(buf, L"Connecting... (attempt %d/%d)", attempt, maxAttempts);
else
sprintf_s(buf, "Connecting failed, trying again (%d/%d)", attempt, maxAttempts);
wchar_t wbuf[128];
mbstowcs(wbuf, buf, 128);
m_labelTitle.setLabel(wstring(wbuf));
swprintf_s(buf, L"Connecting...");
m_labelTitle.setLabel(buf);
break;
}
else if (state == WinsockNetLayer::eJoinState_Success)
{
case WinsockNetLayer::eJoinState_Success:
m_asyncJoinActive = false;
// go go go
}
else if (state == WinsockNetLayer::eJoinState_Cancelled)
{
// cancel
m_labelTitle.setLabel(L"Joining world...");
break;
case WinsockNetLayer::eJoinState_Cancelled:
m_asyncJoinActive = false;
navigateBack();
}
else if (state == WinsockNetLayer::eJoinState_Rejected)
break;
case WinsockNetLayer::eJoinState_Rejected:
{
// server full and banned are passed differently compared to other disconnects it seems
m_asyncJoinActive = false;
DisconnectPacket::eDisconnectReason reason = WinsockNetLayer::GetJoinRejectReason();
int exitReasonStringId;
switch (reason)
{
case DisconnectPacket::eDisconnect_ServerFull:
exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL;
break;
case DisconnectPacket::eDisconnect_Banned:
exitReasonStringId = IDS_DISCONNECTED_KICKED;
break;
default:
exitReasonStringId = IDS_CONNECTION_LOST_SERVER;
break;
}
int reasonStringId = IDS_CONNECTION_LOST_SERVER;
if (reason == DisconnectPacket::eDisconnect_ServerFull)
reasonStringId = IDS_DISCONNECTED_SERVER_FULL;
else if (reason == DisconnectPacket::eDisconnect_Kicked)
reasonStringId = IDS_DISCONNECTED_KICKED;
UINT uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_CONNECTION_FAILED, exitReasonStringId, uiIDA, 1, ProfileManager.GetPrimaryPad(), ConnectingProgress_OnRejectedDialogOK, nullptr, nullptr);
ui.RequestErrorMessage(IDS_CONNECTION_FAILED, reasonStringId, uiIDA, 1, m_iPad, ConnectingProgress_OnRejectedDialogOK, nullptr);
break;
}
else if (state == WinsockNetLayer::eJoinState_Failed)
{
// FAIL
case WinsockNetLayer::eJoinState_Failed:
m_asyncJoinActive = false;
m_asyncJoinFailed = true;
int maxAttempts = WinsockNetLayer::GetJoinMaxAttempts();
char buf[256];
sprintf_s(buf, "Failed to connect after %d attempts. The server may be unavailable.", maxAttempts);
wchar_t wbuf[256];
mbstowcs(wbuf, buf, 256);
// TIL that these exist
// not going to use a actual popup due to it requiring messing with strings which can really mess things up
// i dont trust myself with that
// these need to be touched up later as teh button is a bit offset
m_labelTitle.setLabel(L"Unable to connect to server");
m_progressBar.setLabel(wstring(wbuf));
m_progressBar.showBar(false);
m_progressBar.setVisible(true);
m_labelTitle.setLabel(app.GetString(IDS_CONNECTION_FAILED));
m_buttonConfirm.setVisible(true);
m_showingButton = true;
m_controlTimer.setVisible(false);
updateTooltips();
break;
default:
break;
}
return;
}
#endif
@@ -202,7 +177,6 @@ void UIScene_ConnectingProgress::handleGainFocus(bool navBack)
void UIScene_ConnectingProgress::handleLoseFocus()
{
if (!m_runFailTimer) return;
int millisecsLeft = getTimer(0)->targetTime - System::currentTimeMillis();
int millisecsTaken = getTimer(0)->duration - millisecsLeft;
app.DebugPrintf("\n");
@@ -316,7 +290,6 @@ void UIScene_ConnectingProgress::handleInput(int iPad, int key, bool repeat, boo
switch(key)
{
// 4J-PB - Removed the option to cancel join - it didn't work anyway
#ifdef _WINDOWS64
case ACTION_MENU_CANCEL:
if (pressed && m_asyncJoinActive)
@@ -325,9 +298,11 @@ void UIScene_ConnectingProgress::handleInput(int iPad, int key, bool repeat, boo
WinsockNetLayer::CancelJoinGame();
navigateBack();
handled = true;
return;
}
break;
#endif
// 4J-PB - Removed the option to cancel join - it didn't work anyway
// case ACTION_MENU_CANCEL:
// {
// if(m_cancelFunc != nullptr)
@@ -374,8 +349,8 @@ void UIScene_ConnectingProgress::handlePress(F64 controlId, F64 childId)
if (m_asyncJoinFailed)
{
navigateBack();
break;
}
else
#endif
if( m_iPad != ProfileManager.GetPrimaryPad() && g_NetworkManager.IsInSession() )
{
@@ -12,7 +12,6 @@ private:
bool m_showingButton;
void (*m_cancelFunc)(LPVOID param);
LPVOID m_cancelFuncParam;
#ifdef _WINDOWS64
bool m_asyncJoinActive;
bool m_asyncJoinFailed;
@@ -26,6 +26,9 @@
#define GAME_CREATE_ONLINE_TIMER_ID 0
#define GAME_CREATE_ONLINE_TIMER_TIME 100
// byte added: fuck hardcore
//static bool s_bHardcore = false; // 4J Added: tracks when difficulty slider is at Hardcore position (file-scope to avoid header layout changes)
int UIScene_CreateWorldMenu::m_iDifficultyTitleSettingA[4]=
{
IDS_DIFFICULTY_TITLE_PEACEFUL,
@@ -470,7 +473,7 @@ void UIScene_CreateWorldMenu::handlePress(F64 controlId, F64 childId)
m_iGameModeId = GameType::ADVENTURE->getId();
m_bGameModeCreative = false;
break;
case 2: // Survival
case 2: // Survival
m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_SURVIVAL));
m_iGameModeId = GameType::SURVIVAL->getId();
m_bGameModeCreative = false;
@@ -654,9 +657,14 @@ void UIScene_CreateWorldMenu::handleSliderMove(F64 sliderId, F64 currentValue)
case eControl_Difficulty:
m_sliderDifficulty.handleSliderMove(value);
app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value);
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
m_sliderDifficulty.setLabel(TempString);
// 4J Added: Difficulty value 4 = Hardcore (store actual difficulty as Hard, track hardcore separately)
app.SetGameSettings(m_iPad, eGameSetting_Difficulty, value);
swprintf((WCHAR*)TempString, 256, L"%ls: %ls",
app.GetString(IDS_SLIDER_DIFFICULTY),
app.GetString(m_iDifficultyTitleSettingA[value]));
m_sliderDifficulty.setLabel(TempString);
break;
}
}
@@ -823,7 +831,7 @@ void UIScene_CreateWorldMenu::checkStateAndStartGame()
// 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK
UINT uiIDA[1];
uiIDA[0]=IDS_OK;
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
ui.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
}
else
{
@@ -1113,6 +1121,10 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
StorageManager.ResetSaveData();
// Make our next save default to the name of the level
StorageManager.SetSaveTitle((wchar_t *)wWorldName.c_str());
#ifdef _WINDOWS64
// New world — save folder doesn't exist yet, clear for now (will be set after first autosave)
app.SetCurrentSaveFolderName(L"");
#endif
wstring wSeed;
if(!pClass->m_MoreOptionsParams.seed.empty() )
@@ -1179,7 +1191,8 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
Minecraft *pMinecraft = Minecraft::GetInstance();
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
app.SetGameHostOption(eGameHostOption_Difficulty,Minecraft::GetInstance()->options->difficulty);
// 4J Added: If hardcore was selected on difficulty slider, set difficulty to Hard and enable hardcore flag
app.SetGameHostOption(eGameHostOption_Difficulty, Minecraft::GetInstance()->options->difficulty);
app.SetGameHostOption(eGameHostOption_FriendsOfFriends,pClass->m_MoreOptionsParams.bAllowFriendsOfFriends);
app.SetGameHostOption(eGameHostOption_Gamertags,app.GetGameSettings(pClass->m_iPad,eGameSetting_GamertagsVisible)?1:0);
+10 -9
View File
@@ -490,20 +490,21 @@ SCreditTextItemDef UIScene_Credits::gs_aCreditDefs[MAX_CREDIT_STRINGS] =
#endif
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eExtraLargeText},
{L"LCE-Revelations", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eExtraLargeText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Project Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"codeHusky", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Project Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"codeHusky", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"mattsumi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"itsRevela", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Former Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"smartcmd", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Patoke", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"rtm516", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Former Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"smartcmd", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Patoke", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"rtm516", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Thank you to our 120+ contributors on GitHub!", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
{L"github.com/MCLCE/MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"(formerly smartcmd/MinecraftConsoles)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"(formerly smartcmd/MinecraftConsoles)", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
{L"Additional Thanks", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
@@ -3,24 +3,42 @@
#include "UIScene_DeathMenu.h"
#include "IUIScene_PauseMenu.h"
#include "../../Minecraft.h"
#include "../../MultiPlayerLevel.h"
#include "../../MultiPlayerLocalPlayer.h"
#include "../../MinecraftServer.h"
#include "../../../Minecraft.World/net.minecraft.world.level.storage.h"
UIScene_DeathMenu::UIScene_DeathMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
// Setup all the Iggy references we need for this scene
initialiseMovie();
m_buttonRespawn.init(app.GetString(IDS_RESPAWN),eControl_Respawn);
m_buttonExitGame.init(app.GetString(IDS_EXIT_GAME),eControl_ExitGame);
m_labelTitle.setLabel(app.GetString(IDS_YOU_DIED));
// 4J Added: In hardcore mode, disable respawn and show hardcore death message
Minecraft *pMC = Minecraft::GetInstance();
bool isHardcore = false;
if (pMC != nullptr && pMC->level != nullptr)
{
isHardcore = pMC->level->getLevelData()->isHardcore();
}
if (isHardcore)
{
m_buttonRespawn.setVisible(false);
}
else
{
m_buttonRespawn.init(app.GetString(IDS_RESPAWN), eControl_Respawn);
}
m_bIgnoreInput = false;
Minecraft *pMinecraft = Minecraft::GetInstance();
if(pMinecraft != nullptr && pMinecraft->localgameModes[iPad] != nullptr )
if(pMC != nullptr && pMC->localgameModes[iPad] != nullptr )
{
TutorialMode *gameMode = static_cast<TutorialMode *>(pMinecraft->localgameModes[iPad]);
TutorialMode *gameMode = static_cast<TutorialMode *>(pMC->localgameModes[iPad]);
// This just allows it to be shown
gameMode->getTutorial()->showTutorialPopup(false);
@@ -84,8 +102,16 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
switch(static_cast<int>(controlId))
{
case eControl_Respawn:
m_bIgnoreInput = true;
app.SetAction(m_iPad,eAppAction_Respawn);
{
// 4J Added: Safeguard - don't respawn in hardcore mode
Minecraft *pMC = Minecraft::GetInstance();
if (pMC != nullptr && pMC->level != nullptr && pMC->level->getLevelData()->isHardcore())
{
break;
}
m_bIgnoreInput = true;
app.SetAction(m_iPad,eAppAction_Respawn);
}
#ifdef _DURANGO
//InputManager.SetEnabledGtcButtons(_360_GTC_MENU|_360_GTC_PAUSE|_360_GTC_VIEW);
#endif
@@ -109,7 +135,16 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
playTime = static_cast<int>(pMinecraft->localplayers[m_iPad]->getSessionTimer());
}
TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Failed);
// 4J Added: Hardcore mode — skip save dialog, exit without saving, delete world
if (pMinecraft->level != nullptr && pMinecraft->level->getLevelData()->isHardcore() && g_NetworkManager.IsHost())
{
MinecraftServer::getInstance()->setSaveOnExit(false);
MinecraftServer::getInstance()->setDeleteWorldOnExit(true);
app.SetAction(m_iPad, eAppAction_ExitWorld);
break;
}
#if defined (_XBOX_ONE) || defined(__ORBIS__)
if(g_NetworkManager.IsHost() && StorageManager.GetSaveDisabled())
{
@@ -188,4 +223,4 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
}
break;
}
}
}
@@ -240,13 +240,17 @@ void UIScene_DebugOverlay::handlePress(F64 controlId, F64 childId)
case eControl_SetDay:
{
ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad());
conn->send( TimeCommand::preparePacket(false) );
conn->send(
TimeCommand::preparePacket(L"set", L"day")
);
}
break;
case eControl_SetNight:
{
ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad());
conn->send( TimeCommand::preparePacket(true) );
conn->send(
TimeCommand::preparePacket(L"set", L"night")
);
}
break;
};
+13 -1
View File
@@ -50,7 +50,19 @@ UIScene_EndPoem::UIScene_EndPoem(int iPad, void *initData, UILayer *parentLayer)
Minecraft *pMinecraft = Minecraft::GetInstance();
wstring playerName = L"";
playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() );
unsigned int winIdx = ui.GetWinUserIndex();
if(winIdx < XUSER_MAX_COUNT && pMinecraft->localplayers[winIdx] != nullptr)
{
playerName = escapeXML( pMinecraft->localplayers[winIdx]->getDisplayName() );
}
else if(pMinecraft->localplayers[ProfileManager.GetPrimaryPad()] != nullptr)
{
playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() );
}
else
{
playerName = L"Player";
}
noNoiseString = replaceAll(noNoiseString,L"{*PLAYER*}",playerName);
Random random(8124371);
@@ -287,7 +287,11 @@ void UIScene_FullscreenProgress::handleInput(int iPad, int key, bool repeat, boo
case ACTION_MENU_CANCEL:
if( pressed && m_cancelFunc != nullptr && !m_bWasCancelled )
{
m_cancelText = -1;
updateTooltips();
m_bWasCancelled = true;
m_cancelFunc( m_cancelFuncParam );
}
break;
File diff suppressed because it is too large Load Diff
+4
View File
@@ -25,6 +25,7 @@ protected:
IggyName m_funcRepositionHud, m_funcSetDisplayName, m_funcSetTooltipsEnabled;
IggyName m_funcSetRidingHorse, m_funcSetHorseHealth, m_funcSetHorseJumpBarProgress;
IggyName m_funcSetHealthAbsorb;
IggyName m_funcSetHardcore;
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT(m_labelChatText[0],"Label1")
UI_MAP_ELEMENT(m_labelChatText[1],"Label2")
@@ -89,6 +90,7 @@ protected:
UI_MAP_NAME(m_funcSetHorseJumpBarProgress, L"SetHorseJumpBarProgress")
UI_MAP_NAME(m_funcSetHealthAbsorb, L"SetHealthAbsorb")
UI_MAP_NAME(m_funcSetHardcore, L"SetHardcore")
UI_END_MAP_ELEMENTS_AND_NAMES()
public:
@@ -159,6 +161,8 @@ private:
void SetHealthAbsorb(int healthAbsorb);
void SetHardcoreMode(bool bHardcore);
public:
void SetSelectedLabel(const wstring &label);
void ShowDisplayName(bool show);
@@ -27,8 +27,15 @@ UIScene_InGameInfoMenu::UIScene_InGameInfoMenu(int iPad, void *initData, UILayer
{
PlayerInfo *info = BuildPlayerInfo(player);
// Skip the dedicated server's phantom host entry (slot 0, empty name)
if (info->m_smallId == 0 && info->m_name.empty())
{
delete info;
continue;
}
m_players.push_back(info);
m_playerList.addItem(info->m_name, info->m_colorState, info->m_voiceStatus);
m_playerList.addItem(info->m_name, info->m_colorState, info->m_voiceStatus);
}
}
@@ -174,8 +181,15 @@ void UIScene_InGameInfoMenu::handleReload()
{
PlayerInfo *info = BuildPlayerInfo(player);
// Skip the dedicated server's phantom host entry (slot 0, empty name)
if (info->m_smallId == 0 && info->m_name.empty())
{
delete info;
continue;
}
m_players.push_back(info);
m_playerList.addItem(info->m_name, info->m_colorState, info->m_voiceStatus);
m_playerList.addItem(info->m_name, info->m_colorState, info->m_voiceStatus);
}
}
@@ -202,23 +216,22 @@ void UIScene_InGameInfoMenu::tick()
{
UIScene::tick();
// Update players by index
// Update players by their stored smallId (not sequential index, which can mismatch
// when entries like the dedicated server host are filtered from the UI list)
for(DWORD i = 0; i < m_players.size(); ++i)
{
INetworkPlayer *player = g_NetworkManager.GetPlayerByIndex( i );
INetworkPlayer *player = g_NetworkManager.GetPlayerBySmallId( m_players[i]->m_smallId );
if(player != nullptr)
{
PlayerInfo *info = BuildPlayerInfo(player);
m_players[i]->m_smallId = info->m_smallId;
if(info->m_voiceStatus != m_players[i]->m_voiceStatus)
{
m_players[i]->m_voiceStatus = info->m_voiceStatus;
m_playerList.setVOIPIcon(i, info->m_voiceStatus);
}
if(info->m_colorState != m_players[i]->m_colorState)
{
m_players[i]->m_colorState = info->m_colorState;
@@ -424,11 +437,19 @@ void UIScene_InGameInfoMenu::OnPlayerChanged(void *callbackParam, INetworkPlayer
// If the player is joining
if(!leaving)
{
PlayerInfo *info = scene->BuildPlayerInfo(pPlayer);
// Skip the dedicated server's phantom host entry (slot 0, empty name)
if (pPlayer->GetSmallId() == 0 && info->m_name.empty())
{
delete info;
return;
}
app.DebugPrintf("<UIScene_InGameInfoMenu::OnPlayerChanged> Player \"%ls\" not found, adding\n", pPlayer->GetOnlineName());
PlayerInfo *info = scene->BuildPlayerInfo(pPlayer);
scene->m_players.push_back(info);
// Note that the tick updates buttons every tick so it's only really important that we
// add the button (not the order or content)
scene->m_playerList.addItem(info->m_name, info->m_colorState, info->m_voiceStatus);
@@ -491,7 +512,7 @@ UIScene_InGameInfoMenu::PlayerInfo *UIScene_InGameInfoMenu::BuildPlayerInfo(INet
}
info->m_voiceStatus = voiceStatus;
info->m_colorState = app.GetPlayerColour(info->m_smallId);
info->m_colorState = app.GetPlayerMapIconByName(player->GetOnlineName());
info->m_name = playerName;
return info;
+360 -11
View File
@@ -1,12 +1,15 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene_JoinMenu.h"
#include "..\..\Minecraft.h"
#include "..\..\TexturePackRepository.h"
#include "..\..\Options.h"
#include "..\..\MinecraftServer.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.h"
#include "../../Minecraft.h"
#include "../../TexturePackRepository.h"
#include "../../Options.h"
#include "../../MinecraftServer.h"
#include "../../../Minecraft.World/net.minecraft.world.level.h"
#include "../../../Minecraft.World/net.minecraft.world.h"
#ifdef _WINDOWS64
#include "../../Windows64/Network/WinsockNetLayer.h"
#endif
#define UPDATE_PLAYERS_TIMER_ID 0
#define UPDATE_PLAYERS_TIMER_TIME 30000
@@ -21,6 +24,12 @@ UIScene_JoinMenu::UIScene_JoinMenu(int iPad, void *_initData, UILayer *parentLay
m_friendInfoUpdatedOK = false;
m_friendInfoUpdatedERROR = false;
m_friendInfoRequestIssued = false;
#ifdef _WINDOWS64
m_serverIndex = initData->serverIndex;
m_editServerPhase = eEditServer_Idle;
m_editServerButtonIndex = -1;
m_deleteServerButtonIndex = -1;
#endif
}
void UIScene_JoinMenu::updateTooltips()
@@ -116,6 +125,16 @@ void UIScene_JoinMenu::tick()
}
#endif
#ifdef _WINDOWS64
if (m_serverIndex >= 0)
{
m_editServerButtonIndex = m_buttonListPlayers.getItemCount();
m_buttonListPlayers.addItem(L"Edit Server");
m_deleteServerButtonIndex = m_buttonListPlayers.getItemCount();
m_buttonListPlayers.addItem(L"Delete Server");
}
#endif
m_labelLabels[eLabel_Difficulty].init(app.GetString(IDS_LABEL_DIFFICULTY));
m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE));
m_labelLabels[eLabel_GamertagsOn].init(app.GetString(IDS_LABEL_GAMERTAGS));
@@ -287,12 +306,38 @@ void UIScene_JoinMenu::handleInput(int iPad, int key, bool repeat, bool pressed,
if( uid != INVALID_XUID ) ProfileManager.ShowProfileCard(ProfileManager.GetLockedProfile(),uid);
}
break;
#endif
#ifdef _WINDOWS64
case ACTION_MENU_X:
if(pressed && m_serverIndex >= 0)
{
BeginDeleteServer();
handled = true;
}
break;
case ACTION_MENU_Y:
if(pressed && m_serverIndex >= 0)
{
BeginEditServer();
handled = true;
}
break;
#endif
case ACTION_MENU_OK:
if (getControlFocus() != eControl_GamePlayers)
{
sendInputToMovie(key, repeat, pressed, released);
}
#ifdef _WINDOWS64
else if (pressed && m_serverIndex >= 0)
{
int sel = m_buttonListPlayers.getCurrentSelection();
if (sel == m_editServerButtonIndex)
BeginEditServer();
else if (sel == m_deleteServerButtonIndex)
BeginDeleteServer();
}
#endif
handled = true;
break;
#ifdef __ORBIS__
@@ -327,6 +372,16 @@ void UIScene_JoinMenu::handlePress(F64 controlId, F64 childId)
}
break;
case eControl_GamePlayers:
#ifdef _WINDOWS64
if (m_serverIndex >= 0)
{
int sel = (int)childId;
if (sel == m_editServerButtonIndex)
BeginEditServer();
else if (sel == m_deleteServerButtonIndex)
BeginDeleteServer();
}
#endif
break;
};
}
@@ -531,6 +586,23 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass)
// Alert the app the we no longer want to be informed of ethernet connections
app.SetLiveLinkRequired( false );
#ifdef _WINDOWS64
if (result == CGameNetworkManager::JOINGAME_PENDING)
{
pClass->m_bIgnoreInput = false;
ConnectionProgressParams *param = new ConnectionProgressParams();
param->iPad = ProfileManager.GetPrimaryPad();
param->stringId = IDS_PROGRESS_CONNECTING;
param->showTooltips = true;
param->setFailTimer = false;
param->timerTime = 0;
param->cancelFunc = nullptr;
param->cancelFuncParam = nullptr;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_ConnectingProgress, param);
return;
}
#endif
if( result != CGameNetworkManager::JOINGAME_SUCCESS )
{
int exitReasonStringId = -1;
@@ -585,16 +657,18 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass)
if( exitReasonStringId == -1 )
{
ui.NavigateBack(pClass->m_iPad);
// No specific disconnect reason was set — the server was likely
// unreachable. Show a "Connection Failed" dialog instead of
// silently navigating back so the user knows what happened.
exitReasonStringId = IDS_CONNECTION_LOST_SERVER;
}
else
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage( IDS_CONNECTION_FAILED, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad());
exitReasonStringId = -1;
ui.NavigateToHomeMenu();
pClass->m_bIgnoreInput = false;
}
}
}
@@ -644,4 +718,279 @@ void UIScene_JoinMenu::handleTimerComplete(int id)
}
break;
};
}
}
#ifdef _WINDOWS64
void UIScene_JoinMenu::BeginDeleteServer()
{
m_bIgnoreInput = true;
UINT uiIDA[2];
uiIDA[0] = IDS_CONFIRM_CANCEL;
uiIDA[1] = IDS_CONFIRM_OK;
ui.RequestAlertMessage(IDS_TOOLTIPS_DELETE, IDS_TEXT_DELETE_SAVE, uiIDA, 2, m_iPad, &UIScene_JoinMenu::DeleteServerDialogReturned, this);
}
int UIScene_JoinMenu::DeleteServerDialogReturned(void *pParam, int iPad, C4JStorage::EMessageResult result)
{
UIScene_JoinMenu* pClass = (UIScene_JoinMenu*)pParam;
if (result == C4JStorage::EMessage_ResultDecline)
{
pClass->RemoveServerFromFile();
g_NetworkManager.ForceFriendsSessionRefresh();
pClass->navigateBack();
}
else
{
pClass->m_bIgnoreInput = false;
}
return 0;
}
void UIScene_JoinMenu::BeginEditServer()
{
m_bIgnoreInput = true;
m_editServerPhase = eEditServer_IP;
m_editServerIP.clear();
m_editServerPort.clear();
wchar_t wDefaultIP[64] = {};
mbstowcs(wDefaultIP, m_selectedSession->data.hostIP, 63);
UIKeyboardInitData kbData;
kbData.title = L"Server Address";
kbData.defaultText = wDefaultIP;
kbData.maxChars = 128;
kbData.callback = &UIScene_JoinMenu::EditServerKeyboardCallback;
kbData.lpParam = this;
kbData.pcMode = g_KBMInput.IsKBMActive();
ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData);
}
int UIScene_JoinMenu::EditServerKeyboardCallback(LPVOID lpParam, bool bRes)
{
UIScene_JoinMenu *pClass = (UIScene_JoinMenu *)lpParam;
if (!bRes)
{
pClass->m_editServerPhase = eEditServer_Idle;
pClass->m_bIgnoreInput = false;
return 0;
}
uint16_t ui16Text[256];
ZeroMemory(ui16Text, sizeof(ui16Text));
Win64_GetKeyboardText(ui16Text, 256);
wchar_t wBuf[256] = {};
for (int k = 0; k < 255 && ui16Text[k]; k++)
wBuf[k] = (wchar_t)ui16Text[k];
if (wBuf[0] == 0)
{
pClass->m_editServerPhase = eEditServer_Idle;
pClass->m_bIgnoreInput = false;
return 0;
}
switch (pClass->m_editServerPhase)
{
case eEditServer_IP:
{
pClass->m_editServerIP = wBuf;
pClass->m_editServerPhase = eEditServer_Port;
wchar_t wDefaultPort[16] = {};
swprintf(wDefaultPort, 16, L"%d", pClass->m_selectedSession->data.hostPort);
UIKeyboardInitData kbData;
kbData.title = L"Server Port";
kbData.defaultText = wDefaultPort;
kbData.maxChars = 6;
kbData.callback = &UIScene_JoinMenu::EditServerKeyboardCallback;
kbData.lpParam = pClass;
kbData.pcMode = g_KBMInput.IsKBMActive();
ui.NavigateToScene(pClass->m_iPad, eUIScene_Keyboard, &kbData);
break;
}
case eEditServer_Port:
{
pClass->m_editServerPort = wBuf;
pClass->m_editServerPhase = eEditServer_Name;
wchar_t wDefaultName[64] = {};
if (pClass->m_selectedSession->displayLabel)
wcsncpy(wDefaultName, pClass->m_selectedSession->displayLabel, 63);
UIKeyboardInitData kbData;
kbData.title = L"Server Name";
kbData.defaultText = wDefaultName;
kbData.maxChars = 64;
kbData.callback = &UIScene_JoinMenu::EditServerKeyboardCallback;
kbData.lpParam = pClass;
kbData.pcMode = g_KBMInput.IsKBMActive();
ui.NavigateToScene(pClass->m_iPad, eUIScene_Keyboard, &kbData);
break;
}
case eEditServer_Name:
{
wstring newName = wBuf;
pClass->UpdateServerInFile(pClass->m_editServerIP, pClass->m_editServerPort, newName);
pClass->m_editServerPhase = eEditServer_Idle;
pClass->m_bIgnoreInput = false;
g_NetworkManager.ForceFriendsSessionRefresh();
pClass->navigateBack();
break;
}
default:
pClass->m_editServerPhase = eEditServer_Idle;
pClass->m_bIgnoreInput = false;
break;
}
return 0;
}
void UIScene_JoinMenu::UpdateServerInFile(const wstring& newIP, const wstring& newPort, const wstring& newName)
{
char narrowNewIP[256] = {};
char narrowNewPort[16] = {};
char narrowNewName[256] = {};
wcstombs(narrowNewIP, newIP.c_str(), sizeof(narrowNewIP) - 1);
wcstombs(narrowNewPort, newPort.c_str(), sizeof(narrowNewPort) - 1);
wcstombs(narrowNewName, newName.c_str(), sizeof(narrowNewName) - 1);
uint16_t newPortNum = (uint16_t)atoi(narrowNewPort);
struct ServerEntry { std::string ip; uint16_t port; std::string name; };
std::vector<ServerEntry> entries;
FILE* file = fopen("servers.db", "rb");
if (file)
{
char magic[4] = {};
if (fread(magic, 1, 4, file) == 4 && memcmp(magic, "MCSV", 4) == 0)
{
uint32_t version = 0, count = 0;
fread(&version, sizeof(uint32_t), 1, file);
fread(&count, sizeof(uint32_t), 1, file);
if (version == 1)
{
for (uint32_t s = 0; s < count; s++)
{
uint16_t ipLen = 0, p = 0, nameLen = 0;
if (fread(&ipLen, sizeof(uint16_t), 1, file) != 1) break;
if (ipLen == 0 || ipLen > 256) break;
char ipBuf[257] = {};
if (fread(ipBuf, 1, ipLen, file) != ipLen) break;
if (fread(&p, sizeof(uint16_t), 1, file) != 1) break;
if (fread(&nameLen, sizeof(uint16_t), 1, file) != 1) break;
if (nameLen > 256) break;
char nameBuf[257] = {};
if (nameLen > 0 && fread(nameBuf, 1, nameLen, file) != nameLen) break;
entries.push_back({std::string(ipBuf), p, std::string(nameBuf)});
}
}
}
fclose(file);
}
// Find and update the matching entry by original IP and port
int idx = m_serverIndex;
if (idx >= 0 && idx < (int)entries.size())
{
entries[idx].ip = std::string(narrowNewIP);
entries[idx].port = newPortNum;
entries[idx].name = std::string(narrowNewName);
}
file = fopen("servers.db", "wb");
if (file)
{
fwrite("MCSV", 1, 4, file);
uint32_t version = 1;
uint32_t count = (uint32_t)entries.size();
fwrite(&version, sizeof(uint32_t), 1, file);
fwrite(&count, sizeof(uint32_t), 1, file);
for (size_t i = 0; i < entries.size(); i++)
{
uint16_t ipLen = (uint16_t)entries[i].ip.length();
fwrite(&ipLen, sizeof(uint16_t), 1, file);
fwrite(entries[i].ip.c_str(), 1, ipLen, file);
fwrite(&entries[i].port, sizeof(uint16_t), 1, file);
uint16_t nameLen = (uint16_t)entries[i].name.length();
fwrite(&nameLen, sizeof(uint16_t), 1, file);
fwrite(entries[i].name.c_str(), 1, nameLen, file);
}
fclose(file);
}
}
void UIScene_JoinMenu::RemoveServerFromFile()
{
struct ServerEntry { std::string ip; uint16_t port; std::string name; };
std::vector<ServerEntry> entries;
FILE* file = fopen("servers.db", "rb");
if (file)
{
char magic[4] = {};
if (fread(magic, 1, 4, file) == 4 && memcmp(magic, "MCSV", 4) == 0)
{
uint32_t version = 0, count = 0;
fread(&version, sizeof(uint32_t), 1, file);
fread(&count, sizeof(uint32_t), 1, file);
if (version == 1)
{
for (uint32_t s = 0; s < count; s++)
{
uint16_t ipLen = 0, p = 0, nameLen = 0;
if (fread(&ipLen, sizeof(uint16_t), 1, file) != 1) break;
if (ipLen == 0 || ipLen > 256) break;
char ipBuf[257] = {};
if (fread(ipBuf, 1, ipLen, file) != ipLen) break;
if (fread(&p, sizeof(uint16_t), 1, file) != 1) break;
if (fread(&nameLen, sizeof(uint16_t), 1, file) != 1) break;
if (nameLen > 256) break;
char nameBuf[257] = {};
if (nameLen > 0 && fread(nameBuf, 1, nameLen, file) != nameLen) break;
entries.push_back({std::string(ipBuf), p, std::string(nameBuf)});
}
}
}
fclose(file);
}
// Remove the entry at m_serverIndex
int idx = m_serverIndex;
if (idx >= 0 && idx < (int)entries.size())
{
entries.erase(entries.begin() + idx);
}
file = fopen("servers.db", "wb");
if (file)
{
fwrite("MCSV", 1, 4, file);
uint32_t version = 1;
uint32_t count = (uint32_t)entries.size();
fwrite(&version, sizeof(uint32_t), 1, file);
fwrite(&count, sizeof(uint32_t), 1, file);
for (size_t i = 0; i < entries.size(); i++)
{
uint16_t ipLen = (uint16_t)entries[i].ip.length();
fwrite(&ipLen, sizeof(uint16_t), 1, file);
fwrite(entries[i].ip.c_str(), 1, ipLen, file);
fwrite(&entries[i].port, sizeof(uint16_t), 1, file);
uint16_t nameLen = (uint16_t)entries[i].name.length();
fwrite(&nameLen, sizeof(uint16_t), 1, file);
fwrite(entries[i].name.c_str(), 1, nameLen, file);
}
fclose(file);
}
}
#endif // _WINDOWS64
+10 -1
View File
@@ -105,4 +105,13 @@ protected:
static int StartGame_SignInReturned(void *pParam, bool, int);
static void JoinGame(UIScene_JoinMenu* pClass);
};
#ifdef _WINDOWS64
void BeginEditServer();
void BeginDeleteServer();
static int EditServerKeyboardCallback(LPVOID lpParam, bool bRes);
static int DeleteServerDialogReturned(void *pParam, int iPad, C4JStorage::EMessageResult result);
void UpdateServerInFile(const wstring& newIP, const wstring& newPort, const wstring& newName);
void RemoveServerFromFile();
#endif
};
@@ -1,7 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene_LanguageSelector.h"
// pasted from lcen client aswell
// strings for buttons in the list
const unsigned int UIScene_LanguageSelector::m_uiHTPButtonNameA[]=
{
@@ -1052,4 +1052,4 @@ int UIScene_LeaderboardsMenu::ExitLeaderboards(void *pParam,int iPad,C4JStorage:
int UIScene_LeaderboardsMenu::GetEntryStartIndex()
{
return m_leaderboard.m_entries.size() == 0 ? 0 : m_leaderboard.m_entries[0].m_row;
}
}
+81 -26
View File
@@ -24,7 +24,7 @@
#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50
#endif
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[4]=
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[5]=
{
IDS_DIFFICULTY_TITLE_PEACEFUL,
IDS_DIFFICULTY_TITLE_EASY,
@@ -53,6 +53,7 @@ int UIScene_LoadMenu::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumb
app.DebugPrintf("Thumbnail data is nullptr, or has size 0\n");
pClass->m_bThumbnailGetFailed = true;
}
pClass->m_bRetrievingSaveThumbnail = false;
}
return 0;
@@ -99,6 +100,7 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
m_bIsSaveOwner = true;
m_bSaveThumbnailReady = false;
m_bRetrievingSaveThumbnail = true;
m_bShowTimer = false;
m_pDLCPack = nullptr;
m_bAvailableTexturePacksChecked=false;
@@ -108,8 +110,7 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
m_bThumbnailGetFailed = false;
m_seed = 0;
m_bIsCorrupt = false;
m_pbThumbnailData = nullptr;
m_uiThumbnailSize = 0;
m_bHardcore = false;
m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
// 4J-PB - read the settings for the online flag. We'll only save this setting if the user changed it.
@@ -249,17 +250,17 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
#endif
#endif
#ifdef _WINDOWS64
if (params->saveDetails != nullptr && params->saveDetails->UTF8SaveName[0] != '\0')
{
wchar_t wSaveName[128];
ZeroMemory(wSaveName, sizeof(wSaveName));
MultiByteToWideChar(CP_UTF8, 0, params->saveDetails->UTF8SaveName, -1, wSaveName, 127);
m_levelName = wstring(wSaveName);
m_labelGameName.init(m_levelName);
}
if (params->saveDetails != nullptr)
{
if (params->saveDetails->UTF8SaveName[0] != '\0')
{
wchar_t wSaveName[128];
ZeroMemory(wSaveName, sizeof(wSaveName));
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, 127);
m_levelName = wstring(wSaveName);
m_labelGameName.init(m_levelName);
}
// Set thumbnail name from save filename (needed for texture display in tick)
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
ZeroMemory(wFilename, sizeof(wFilename));
mbstowcs(wFilename, params->saveDetails->UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
@@ -267,14 +268,24 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
if (params->saveDetails->pbThumbnailData && params->saveDetails->dwThumbnailSize > 0)
{
// save list already loaded this, register and display it
registerSubstitutionTexture(wFilename, params->saveDetails->pbThumbnailData, params->saveDetails->dwThumbnailSize);
m_bitmapIcon.setTextureName(wFilename);
m_pbThumbnailData = params->saveDetails->pbThumbnailData;
m_uiThumbnailSize = params->saveDetails->dwThumbnailSize;
m_bSaveThumbnailReady = true;
m_bRetrievingSaveThumbnail = false;
}
m_bHardcore = params->saveDetails->isHardcore;
if (m_bHardcore)
{
WCHAR TempString[256];
swprintf((WCHAR *)TempString, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_DIFFICULTY), L"Hardcore");
m_sliderDifficulty.init(TempString, eControl_Difficulty, 0, 4, 4);
// Hardcore locks game mode to Survival
m_iGameModeId = GameType::SURVIVAL->getId();
m_bGameModeCreative = false;
m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_SURVIVAL));
}
}
#endif
}
@@ -414,15 +425,7 @@ void UIScene_LoadMenu::updateTooltips()
void UIScene_LoadMenu::updateComponents()
{
m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true);
if(RenderManager.IsWidescreen())
{
m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true);
}
else
{
m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false);
}
m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false);
}
wstring UIScene_LoadMenu::getMoviePath()
@@ -507,6 +510,17 @@ void UIScene_LoadMenu::tick()
m_MoreOptionsParams.bNaturalRegeneration = app.GetGameHostOption(uiHostOptions, eGameHostOption_NaturalRegeneration);
m_MoreOptionsParams.bDoDaylightCycle = app.GetGameHostOption(uiHostOptions, eGameHostOption_DoDaylightCycle);
unsigned int saveDifficulty = app.GetGameHostOption(uiHostOptions, eGameHostOption_Difficulty);
if (saveDifficulty <= 3)
{
m_CurrentDifficulty = static_cast<unsigned char>(saveDifficulty);
app.SetGameSettings(m_iPad, eGameSetting_Difficulty, m_CurrentDifficulty);
WCHAR difficultyLabel[256];
swprintf((WCHAR*)difficultyLabel, 256, L"%ls: %ls", app.GetString(IDS_SLIDER_DIFFICULTY), app.GetString(m_iDifficultyTitleSettingA[m_CurrentDifficulty]));
m_sliderDifficulty.init(difficultyLabel, eControl_Difficulty, 0, 3, m_CurrentDifficulty);
}
bool cheatsOn = m_MoreOptionsParams.bHostPrivileges;
if (!cheatsOn)
{
@@ -565,6 +579,21 @@ void UIScene_LoadMenu::tick()
{
m_MoreOptionsParams.bAllowFriendsOfFriends = TRUE;
}
// Use thumbnail host options if available, otherwise preserve the level.dat value
if (app.GetGameHostOption(uiHostOptions, eGameHostOption_Hardcore) > 0)
m_bHardcore = true;
if (m_bHardcore)
{
WCHAR TempString[256];
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ), L"Hardcore");
m_sliderDifficulty.init(TempString, eControl_Difficulty, 0, 4, 4);
// Hardcore locks game mode to Survival
m_iGameModeId = GameType::SURVIVAL->getId();
m_bGameModeCreative = false;
m_buttonGamemode.setLabel(app.GetString(IDS_GAMEMODE_SURVIVAL));
}
}
Minecraft *pMinecraft = Minecraft::GetInstance();
@@ -718,6 +747,8 @@ void UIScene_LoadMenu::handlePress(F64 controlId, F64 childId)
switch(static_cast<int>(controlId))
{
case eControl_GameMode:
if (m_bHardcore)
break; // Hardcore mode locks game mode to Survival
switch(m_iGameModeId)
{
case 0: // Survival
@@ -969,10 +1000,15 @@ void UIScene_LoadMenu::handleSliderMove(F64 sliderId, F64 currentValue)
switch(static_cast<int>(sliderId))
{
case eControl_Difficulty:
if (m_bHardcore)
{
m_sliderDifficulty.handleSliderMove(4);
break;
}
m_sliderDifficulty.handleSliderMove(value);
app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value);
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
m_sliderDifficulty.setLabel(TempString);
break;
}
@@ -1186,7 +1222,7 @@ void UIScene_LoadMenu::LaunchGame(void)
#if TO_BE_IMPLEMENTED
if(eLoadStatus==C4JStorage::ELoadGame_DeviceRemoved)
{
// disable saving
// disable saving
StorageManager.SetSaveDisabled(true);
StorageManager.SetSaveDeviceSelected(m_iPad,false);
UINT uiIDA[1];
@@ -1599,6 +1635,24 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
#ifdef _WINDOWS64
// 4J Added: Store save folder name for potential hardcore world deletion
app.DebugPrintf("StartGameFromSave: pSaveDetails=%p, levelGen=%p, saveInfoIndex=%d\n", pSaveDetails, pClass->m_levelGen, pClass->m_iSaveGameInfoIndex);
if (pSaveDetails != nullptr && pClass->m_levelGen == nullptr)
{
app.DebugPrintf("StartGameFromSave: UTF8SaveFilename='%s'\n", pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex].UTF8SaveFilename);
wchar_t wFolder[MAX_SAVEFILENAME_LENGTH] = {};
mbstowcs(wFolder, pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
app.SetCurrentSaveFolderName(wFolder);
app.DebugPrintf("StartGameFromSave: stored folder name '%ls'\n", wFolder);
}
else
{
app.DebugPrintf("StartGameFromSave: no save details or is levelGen, clearing folder name\n");
app.SetCurrentSaveFolderName(L"");
}
#endif
NetworkGameInitData *param = new NetworkGameInitData();
param->seed = pClass->m_seed;
param->saveData = nullptr;
@@ -1631,6 +1685,7 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
app.SetGameHostOption(eGameHostOption_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
app.SetGameHostOption(eGameHostOption_Hardcore, pClass->m_bHardcore ? 1 : 0);
#ifdef _LARGE_WORLDS
app.SetGameHostOption(eGameHostOption_WorldSize, pClass->m_MoreOptionsParams.worldSize+1 ); // 0 is GAME_HOST_OPTION_WORLDSIZE_UNKNOWN
@@ -15,7 +15,7 @@ private:
eControl_OnlineGame,
};
static int m_iDifficultyTitleSettingA[4];
static int m_iDifficultyTitleSettingA[5];
UIControl m_controlMainPanel;
UIControl_Label m_labelGameName, m_labelSeed, m_labelCreatedMode;
@@ -50,6 +50,7 @@ private:
int m_iGameModeId;
bool m_bHasBeenInCreative;
bool m_bIsSaveOwner;
bool m_bRetrievingSaveThumbnail;
bool m_bSaveThumbnailReady;
bool m_bMultiplayerAllowed;
bool m_bShowTimer;
@@ -70,6 +71,7 @@ private:
wstring m_thumbnailName;
bool m_bRebuildTouchBoxes;
bool m_bHardcore;
public:
UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLayer);
@@ -2,20 +2,20 @@
#include "UI.h"
#include "UIScene_LoadOrJoinMenu.h"
#include "..\..\..\Minecraft.World\StringHelpers.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.level.h"
#include "..\..\..\Minecraft.World\net.minecraft.world.level.chunk.storage.h"
#include "..\..\..\Minecraft.World\ConsoleSaveFile.h"
#include "..\..\..\Minecraft.World\ConsoleSaveFileOriginal.h"
#include "..\..\ProgressRenderer.h"
#include "..\..\MinecraftServer.h"
#include "..\..\TexturePackRepository.h"
#include "..\..\TexturePack.h"
#include "..\Network\SessionInfo.h"
#include "../../../Minecraft.World/StringHelpers.h"
#include "../../../Minecraft.World/net.minecraft.world.item.h"
#include "../../../Minecraft.World/net.minecraft.world.level.h"
#include "../../../Minecraft.World/net.minecraft.world.level.chunk.storage.h"
#include "../../../Minecraft.World/ConsoleSaveFile.h"
#include "../../../Minecraft.World/ConsoleSaveFileOriginal.h"
#include "../../ProgressRenderer.h"
#include "../../MinecraftServer.h"
#include "../../TexturePackRepository.h"
#include "../../TexturePack.h"
#include "../Network/SessionInfo.h"
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
#include "Common\Network\Sony\SonyHttp.h"
#include "Common\Network\Sony\SonyRemoteStorage.h"
#include "Common/Network/Sony/SonyHttp.h"
#include "Common/Network/Sony/SonyRemoteStorage.h"
#include "DLCTexturePack.h"
#endif
#if defined(__ORBIS__) || defined(__PSVITA__)
@@ -26,12 +26,13 @@
#endif
#ifdef _WINDOWS64
#include "..\..\..\Minecraft.World\NbtIo.h"
#include "..\..\..\Minecraft.World\compression.h"
#include "../../../Minecraft.World/NbtIo.h"
#include "../../../Minecraft.World/compression.h"
static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardcore = nullptr)
{
// Check for a worldname.txt sidecar written by the rename feature first
wstring sidecarName = L"";
size_t slashPos = filePath.rfind(L'\\');
if (slashPos != wstring::npos)
{
@@ -49,8 +50,8 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
if (len > 0)
{
wchar_t wbuf[128] = {};
mbstowcs(wbuf, buf, 127);
return wstring(wbuf);
MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, 127);
sidecarName = wbuf;
}
}
else fclose(fr);
@@ -58,10 +59,10 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
}
HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
if (hFile == INVALID_HANDLE_VALUE) return L"";
if (hFile == INVALID_HANDLE_VALUE) return sidecarName;
DWORD fileSize = GetFileSize(hFile, nullptr);
if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); return L""; }
if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); return sidecarName; }
unsigned char *rawData = new unsigned char[fileSize];
DWORD bytesRead = 0;
@@ -69,7 +70,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
{
CloseHandle(hFile);
delete[] rawData;
return L"";
return sidecarName;
}
CloseHandle(hFile);
@@ -84,7 +85,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
if (decompSize == 0 || decompSize > 128 * 1024 * 1024)
{
delete[] rawData;
return L"";
return sidecarName;
}
saveData = new unsigned char[decompSize];
Compression::getCompression()->Decompress(saveData, &decompSize, rawData + 8, fileSize - 8);
@@ -124,7 +125,11 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
{
CompoundTag *dataTag = root->getCompound(L"Data");
if (dataTag != nullptr)
{
result = dataTag->getString(L"LevelName");
if (outHardcore)
*outHardcore = dataTag->getBoolean(L"hardcore");
}
delete root;
}
}
@@ -136,6 +141,10 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
if (freeSaveData) delete[] saveData;
delete[] rawData;
// Prefer the sidecar name (user-renamed) over the level.dat name
if (!sidecarName.empty()) return sidecarName;
// "world" is the engine default - it means no real name was ever set,
// so return empty to let the caller fall back to the save filename (timestamp).
if (result == L"world") result = L"";
@@ -527,6 +536,9 @@ void UIScene_LoadOrJoinMenu::Initialise()
{
m_iSaveListIndex = 0;
m_iGameListIndex = 0;
#ifdef _WINDOWS64
m_addServerPhase = eAddServer_Idle;
#endif
m_iDefaultButtonsC = 0;
m_iMashUpButtonsC=0;
@@ -630,6 +642,11 @@ void UIScene_LoadOrJoinMenu::handleGainFocus(bool navBack)
if( m_bMultiplayerAllowed )
{
#ifdef _WINDOWS64
// Refresh the games list immediately so that any server
// edits/deletions made in the JoinMenu are visible now.
UpdateGamesList();
#endif
#if TO_BE_IMPLEMENTED
HXUICLASS hClassFullscreenProgress = XuiFindClass( L"CScene_FullscreenProgress" );
HXUICLASS hClassConnectingProgress = XuiFindClass( L"CScene_ConnectingProgress" );
@@ -762,7 +779,16 @@ void UIScene_LoadOrJoinMenu::tick()
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
ZeroMemory(wFilename, sizeof(wFilename));
mbstowcs(wFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
wstring filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\saveData.ms");
wchar_t wTitle[MAX_DISPLAYNAME_LENGTH];
ZeroMemory(wTitle, sizeof(wTitle));
mbstowcs(wTitle, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveTitle, MAX_DISPLAYNAME_LENGTH - 1);
wstring filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\") + wstring(wTitle) + wstring(L".ms");
// Fallback to legacy saveData.ms if new-style filename doesn't exist
{
DWORD attrs = GetFileAttributesW(filePath.c_str());
if (attrs == INVALID_FILE_ATTRIBUTES)
filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\saveData.ms");
}
HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
DWORD fileSize = 0;
@@ -785,13 +811,17 @@ void UIScene_LoadOrJoinMenu::tick()
#else
#ifdef _WINDOWS64
{
wstring levelName = ReadLevelNameFromSaveFile(filePath);
bool saveHardcore = false;
wstring levelName = ReadLevelNameFromSaveFile(filePath, &saveHardcore);
m_saveDetails[i].isHardcore = saveHardcore;
if (!levelName.empty())
{
m_buttonListSaves.addItem(levelName, wstring(L""));
wcstombs(m_saveDetails[i].UTF8SaveName, levelName.c_str(), 127);
m_saveDetails[i].UTF8SaveName[127] = '\0';
{
int n = WideCharToMultiByte(CP_UTF8, 0, levelName.c_str(), -1, m_saveDetails[i].UTF8SaveName, 127, nullptr, nullptr);
if (n <= 0) m_saveDetails[i].UTF8SaveName[0] = '\0';
m_saveDetails[i].UTF8SaveName[127] = '\0';
}
}
else
{
@@ -1436,9 +1466,9 @@ int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,boo
for (int k = 0; k < 127 && ui16Text[k]; k++)
wNewName[k] = static_cast<wchar_t>(ui16Text[k]);
// Convert to narrow for storage and in-memory update
char narrowName[128] = {};
wcstombs(narrowName, wNewName, 127);
// Convert to narrow for storage and in-memory update (UTF-8 to preserve Unicode)
char narrowName[256] = {};
WideCharToMultiByte(CP_UTF8, 0, wNewName, -1, narrowName, 255, nullptr, nullptr);
// Build the sidecar path: Windows64\GameHDD\{folder}\worldname.txt
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH] = {};
@@ -1454,7 +1484,7 @@ int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,boo
// Update the in-memory display name so the list reflects it immediately
strncpy_s(pClass->m_saveDetails[listPos].UTF8SaveName, narrowName, 127);
pClass->m_saveDetails[listPos].UTF8SaveName[127] = '\0';
pClass->m_saveDetails[listPos].UTF8SaveName[127] = '\0'; // UTF8SaveName is still 128 bytes; narrowName fits as Arabic is <=2 bytes/char in UTF-8
// Reuse the existing callback to trigger the list repopulate
UIScene_LoadOrJoinMenu::RenameSaveDataReturned(pClass, true);
@@ -1489,6 +1519,10 @@ void UIScene_LoadOrJoinMenu::handleFocusChange(F64 controlId, F64 childId)
{
case eControl_GamesList:
m_iGameListIndex = childId;
#ifdef _WINDOWS64
// Offset past the "Add Server" button so m_iGameListIndex is a session index
m_iGameListIndex -= 1;
#endif
m_buttonListGames.updateChildFocus( static_cast<int>(childId) );
break;
case eControl_SavesList:
@@ -1616,6 +1650,14 @@ void UIScene_LoadOrJoinMenu::handlePress(F64 controlId, F64 childId)
break;
case eControl_GamesList:
{
#ifdef _WINDOWS64
if (static_cast<int>(childId) == ADD_SERVER_BUTTON_INDEX)
{
ui.PlayUISFX(eSFX_Press);
BeginAddServer();
break;
}
#endif
m_bIgnoreInput=true;
m_eAction = eAction_JoinGame;
@@ -1625,7 +1667,10 @@ void UIScene_LoadOrJoinMenu::handlePress(F64 controlId, F64 childId)
{
int nIndex = static_cast<int>(childId);
#ifdef _WINDOWS64
// Offset by 1 because the "Add Server" button is at index 0
nIndex -= 1;
#endif
m_iGameListIndex = nIndex;
CheckAndJoinGame(nIndex);
}
@@ -1933,7 +1978,13 @@ void UIScene_LoadOrJoinMenu::UpdateGamesList()
if(DoesGamesListHaveFocus() && m_buttonListGames.getItemCount() > 0)
{
unsigned int nIndex = m_buttonListGames.getCurrentSelection();
#ifdef _WINDOWS64
// Offset past the "Add Server" button
if (nIndex > 0)
pSelectedSession = m_currentSessions->at( nIndex - 1 );
#else
pSelectedSession = m_currentSessions->at( nIndex );
#endif
}
SessionID selectedSessionId;
@@ -2015,6 +2066,11 @@ void UIScene_LoadOrJoinMenu::UpdateGamesList()
// clear out the games list and re-fill
m_buttonListGames.clearList();
#ifdef _WINDOWS64
// Always add the "Add Server" button as the first entry in the games list
m_buttonListGames.addItem(wstring(L"Add Server"));
#endif
if( filteredListSize > 0 )
{
// Reset the focus to the selected session if it still exists
@@ -2080,7 +2136,12 @@ void UIScene_LoadOrJoinMenu::UpdateGamesList()
if(memcmp( &selectedSessionId, &sessionInfo->sessionId, sizeof(SessionID) ) == 0)
{
#ifdef _WINDOWS64
// Offset past the "Add Server" button
m_buttonListGames.setCurrentSelection(sessionIndex + 1);
#else
m_buttonListGames.setCurrentSelection(sessionIndex);
#endif
break;
}
++sessionIndex;
@@ -2491,7 +2552,7 @@ int UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad,C4JS
{
wchar_t wSaveName[128];
ZeroMemory(wSaveName, 128 * sizeof(wchar_t));
mbstowcs_s(nullptr, wSaveName, 128, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, _TRUNCATE);
MultiByteToWideChar(CP_UTF8, 0, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, -1, wSaveName, 127);
UIKeyboardInitData kbData;
kbData.title = app.GetString(IDS_RENAME_WORLD_TITLE);
kbData.defaultText = wSaveName;
@@ -4116,4 +4177,169 @@ int UIScene_LoadOrJoinMenu::CopySaveErrorDialogFinishedCallback(void *pParam,int
return 0;
}
#endif // _XBOX_ONE
#endif // _XBOX_ONE
#ifdef _WINDOWS64
// adding servers bellow
void UIScene_LoadOrJoinMenu::BeginAddServer()
{
m_addServerPhase = eAddServer_IP;
m_addServerIP.clear();
m_addServerPort.clear();
UIKeyboardInitData kbData;
kbData.title = L"Server Address";
kbData.defaultText = L"";
kbData.maxChars = 128;
kbData.callback = &UIScene_LoadOrJoinMenu::AddServerKeyboardCallback;
kbData.lpParam = this;
kbData.pcMode = g_KBMInput.IsKBMActive();
ui.NavigateToScene(m_iPad, eUIScene_Keyboard, &kbData);
}
int UIScene_LoadOrJoinMenu::AddServerKeyboardCallback(LPVOID lpParam, bool bRes)
{
UIScene_LoadOrJoinMenu *pClass = static_cast<UIScene_LoadOrJoinMenu*>(lpParam);
if (!bRes)
{
pClass->m_addServerPhase = eAddServer_Idle;
pClass->m_bIgnoreInput = false;
return 0;
}
uint16_t ui16Text[256];
ZeroMemory(ui16Text, sizeof(ui16Text));
Win64_GetKeyboardText(ui16Text, 256);
wchar_t wBuf[256] = {};
for (int k = 0; k < 255 && ui16Text[k]; k++)
wBuf[k] = static_cast<wchar_t>(ui16Text[k]);
if (wBuf[0] == 0)
{
pClass->m_addServerPhase = eAddServer_Idle;
pClass->m_bIgnoreInput = false;
return 0;
}
switch (pClass->m_addServerPhase)
{
case eAddServer_IP:
{
pClass->m_addServerIP = wBuf;
pClass->m_addServerPhase = eAddServer_Port;
UIKeyboardInitData kbData;
kbData.title = L"Server Port";
kbData.defaultText = L"25565";
kbData.maxChars = 6;
kbData.callback = &UIScene_LoadOrJoinMenu::AddServerKeyboardCallback;
kbData.lpParam = pClass;
kbData.pcMode = g_KBMInput.IsKBMActive();
ui.NavigateToScene(pClass->m_iPad, eUIScene_Keyboard, &kbData);
break;
}
case eAddServer_Port:
{
pClass->m_addServerPort = wBuf;
pClass->m_addServerPhase = eAddServer_Name;
UIKeyboardInitData kbData;
kbData.title = L"Server Name";
kbData.defaultText = L"Minecraft Server";
kbData.maxChars = 64;
kbData.callback = &UIScene_LoadOrJoinMenu::AddServerKeyboardCallback;
kbData.lpParam = pClass;
kbData.pcMode = g_KBMInput.IsKBMActive();
ui.NavigateToScene(pClass->m_iPad, eUIScene_Keyboard, &kbData);
break;
}
case eAddServer_Name:
{
wstring name = wBuf;
pClass->AppendServerToFile(pClass->m_addServerIP, pClass->m_addServerPort, name);
pClass->m_addServerPhase = eAddServer_Idle;
pClass->m_bIgnoreInput = false;
g_NetworkManager.ForceFriendsSessionRefresh();
break;
}
default:
pClass->m_addServerPhase = eAddServer_Idle;
pClass->m_bIgnoreInput = false;
break;
}
return 0;
}
void UIScene_LoadOrJoinMenu::AppendServerToFile(const wstring& ip, const wstring& port, const wstring& name)
{
char narrowIP[256] = {};
char narrowPort[16] = {};
char narrowName[256] = {};
wcstombs(narrowIP, ip.c_str(), sizeof(narrowIP) - 1);
wcstombs(narrowPort, port.c_str(), sizeof(narrowPort) - 1);
wcstombs(narrowName, name.c_str(), sizeof(narrowName) - 1);
uint16_t portNum = static_cast<uint16_t>(atoi(narrowPort));
struct ServerEntry { std::string ip; uint16_t port; std::string name; };
std::vector<ServerEntry> entries;
FILE* file = fopen("servers.db", "rb");
if (file)
{
char magic[4] = {};
if (fread(magic, 1, 4, file) == 4 && memcmp(magic, "MCSV", 4) == 0)
{
uint32_t version = 0, count = 0;
fread(&version, sizeof(uint32_t), 1, file);
fread(&count, sizeof(uint32_t), 1, file);
if (version == 1)
{
for (uint32_t s = 0; s < count; s++)
{
uint16_t ipLen = 0, p = 0, nameLen = 0;
if (fread(&ipLen, sizeof(uint16_t), 1, file) != 1) break;
if (ipLen == 0 || ipLen > 256) break;
char ipBuf[257] = {};
if (fread(ipBuf, 1, ipLen, file) != ipLen) break;
if (fread(&p, sizeof(uint16_t), 1, file) != 1) break;
if (fread(&nameLen, sizeof(uint16_t), 1, file) != 1) break;
if (nameLen > 256) break;
char nameBuf[257] = {};
if (nameLen > 0 && fread(nameBuf, 1, nameLen, file) != nameLen) break;
entries.push_back({std::string(ipBuf), p, std::string(nameBuf)});
}
}
}
fclose(file);
}
entries.push_back({std::string(narrowIP), portNum, std::string(narrowName)});
file = fopen("servers.db", "wb");
if (file)
{
fwrite("MCSV", 1, 4, file);
uint32_t version = 1;
uint32_t count = static_cast<uint32_t>(entries.size());
fwrite(&version, sizeof(uint32_t), 1, file);
fwrite(&count, sizeof(uint32_t), 1, file);
for (size_t i = 0; i < entries.size(); i++)
{
uint16_t ipLen = static_cast<uint16_t>(entries[i].ip.length());
fwrite(&ipLen, sizeof(uint16_t), 1, file);
fwrite(entries[i].ip.c_str(), 1, ipLen, file);
fwrite(&entries[i].port, sizeof(uint16_t), 1, file);
uint16_t nameLen = static_cast<uint16_t>(entries[i].name.length());
fwrite(&nameLen, sizeof(uint16_t), 1, file);
fwrite(entries[i].name.c_str(), 1, nameLen, file);
}
fclose(file);
}
}
#endif // _WINDOWS64
@@ -176,6 +176,17 @@ public:
private:
void CheckAndJoinGame(int gameIndex);
#ifdef _WINDOWS64
static const int ADD_SERVER_BUTTON_INDEX = 0;
enum eAddServerPhase { eAddServer_Idle, eAddServer_IP, eAddServer_Port, eAddServer_Name };
eAddServerPhase m_addServerPhase;
wstring m_addServerIP;
wstring m_addServerPort;
void BeginAddServer();
void AppendServerToFile(const wstring& ip, const wstring& port, const wstring& name);
static int AddServerKeyboardCallback(LPVOID lpParam, bool bRes);
#endif
#if defined(__PS3__) || defined(__PSVITA__) || defined(__ORBIS__)
static int MustSignInReturnedPSN(void *pParam,int iPad,C4JStorage::EMessageResult result);
static int PSN_SignInReturned(void *pParam,bool bContinue, int iPad);
@@ -619,9 +619,24 @@ void UIScene_PauseMenu::handlePress(F64 controlId, F64 childId)
Windows::Xbox::ApplicationModel::Help::Show(user);
}
break;
#endif
#elif TO_BE_IMPLEMENTED
case BUTTON_PAUSE_ACHIEVEMENTS:
// guests can't look at achievements
if(ProfileManager.IsGuest(pNotifyPressData->UserIndex))
{
UINT uiIDA[1];
uiIDA[0]=IDS_OK;
ui.RequestAlertMessage(IDS_PRO_GUESTPROFILE_TITLE, IDS_PRO_GUESTPROFILE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad());
}
else
{
XShowAchievementsUI( pNotifyPressData->UserIndex );
}
break;
#endif
case BUTTON_PAUSE_ACHIEVEMENTS:
// guests can't look at achievements
/*if(ProfileManager.IsGuest(pNotifyPressData->UserIndex))
{
@@ -632,11 +647,9 @@ void UIScene_PauseMenu::handlePress(F64 controlId, F64 childId)
else
{
XShowAchievementsUI( pNotifyPressData->UserIndex );
}
}*/
ui.NavigateToScene(m_iPad, eUIScene_AchievementsMenu);
break;
case BUTTON_PAUSE_HELPANDOPTIONS:
ui.NavigateToScene(m_iPad,eUIScene_HelpAndOptionsMenu);
break;
@@ -5,6 +5,11 @@
#include "../../Options.h"
#include "../../GameRenderer.h"
#ifdef _WINDOWS64
extern bool g_bVSync;
extern void SetExclusiveFullscreen(bool enabled);
#endif
namespace
{
constexpr int FOV_MIN = 70;
@@ -62,12 +67,14 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD
m_checkboxClouds.init(app.GetString(IDS_CHECKBOX_RENDER_CLOUDS),eControl_Clouds,(app.GetGameSettings(m_iPad,eGameSetting_Clouds)!=0));
m_checkboxBedrockFog.init(app.GetString(IDS_CHECKBOX_RENDER_BEDROCKFOG),eControl_BedrockFog,(app.GetGameSettings(m_iPad,eGameSetting_BedrockFog)!=0));
m_checkboxCustomSkinAnim.init(app.GetString(IDS_CHECKBOX_CUSTOM_SKIN_ANIM),eControl_CustomSkinAnim,(app.GetGameSettings(m_iPad,eGameSetting_CustomSkinAnim)!=0));
m_checkboxVSync.init(L"VSync",eControl_VSync,(app.GetGameSettings(m_iPad,eGameSetting_VSync)!=0));
m_checkboxExclusiveFullscreen.init(L"Fullscreen",eControl_ExclusiveFullscreen,(app.GetGameSettings(m_iPad,eGameSetting_ExclusiveFullscreen)!=0));
WCHAR TempString[256];
swprintf(TempString, 256, L"Render Distance: %d",app.GetGameSettings(m_iPad,eGameSetting_RenderDistance));
m_sliderRenderDistance.init(TempString,eControl_RenderDistance,0,5,DistanceToLevel(app.GetGameSettings(m_iPad,eGameSetting_RenderDistance)));
m_sliderRenderDistance.init(TempString,eControl_RenderDistance,0,3,DistanceToLevel(app.GetGameSettings(m_iPad,eGameSetting_RenderDistance)));
swprintf( TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),app.GetGameSettings(m_iPad,eGameSetting_Gamma));
m_sliderGamma.init(TempString,eControl_Gamma,0,100,app.GetGameSettings(m_iPad,eGameSetting_Gamma));
@@ -82,28 +89,50 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD
doHorizontalResizeCheck();
#ifndef _WINDOWS64
// VSync and Exclusive Fullscreen are only available on PC
removeControl(&m_checkboxVSync, true);
removeControl(&m_checkboxExclusiveFullscreen, true);
#else
// The SWF's original focus chain skips VSync, Fullscreen, and RenderDistance
// (CustomSkinAnim -> Gamma). Rewire the navigation so all controls are reachable:
// CustomSkinAnim -> VSync -> Fullscreen -> RenderDistance -> Gamma
{
IggyName navDown = registerFastName(L"m_objNavDown");
IggyName navUp = registerFastName(L"m_objNavUp");
IggyValueSetStringUTF8RS(m_checkboxCustomSkinAnim.getIggyValuePath(), navDown, nullptr, "VSync", -1);
IggyValueSetStringUTF8RS(m_checkboxVSync.getIggyValuePath(), navUp, nullptr, "CustomSkinAnim", -1);
IggyValueSetStringUTF8RS(m_checkboxVSync.getIggyValuePath(), navDown, nullptr, "ExclusiveFullscreen", -1);
IggyValueSetStringUTF8RS(m_checkboxExclusiveFullscreen.getIggyValuePath(), navUp, nullptr, "VSync", -1);
IggyValueSetStringUTF8RS(m_checkboxExclusiveFullscreen.getIggyValuePath(), navDown, nullptr, "RenderDistance", -1);
IggyValueSetStringUTF8RS(m_sliderRenderDistance.getIggyValuePath(), navUp, nullptr, "ExclusiveFullscreen", -1);
}
#endif
const bool bInGame=(Minecraft::GetInstance()->level!=nullptr);
const bool bIsPrimaryPad=(ProfileManager.GetPrimaryPad()==m_iPad);
// if we're not in the game, we need to use basescene 0
// if we're not in the game, we need to use basescene 0
if(bInGame)
{
// If the game has started, then you need to be the host to change the in-game gamertags
#ifndef _WINDOWS64
// Console splitscreen: non-host and non-primary players can't change world-level settings
if(bIsPrimaryPad)
{
// we are the primary player on this machine, but not the game host
// are we the game host? If not, we need to remove the bedrockfog setting
{
if(!g_NetworkManager.IsHost())
{
// hide the in-game bedrock fog setting
removeControl(&m_checkboxBedrockFog, true);
}
}
else
{
// We shouldn't have the bedrock fog option, or the m_CustomSkinAnim option
removeControl(&m_checkboxBedrockFog, true);
removeControl(&m_checkboxCustomSkinAnim, true);
}
#endif
}
if(app.GetLocalPlayerCount()>1)
@@ -165,6 +194,12 @@ void UIScene_SettingsGraphicsMenu::handleInput(int iPad, int key, bool repeat, b
app.SetGameSettings(m_iPad,eGameSetting_Clouds,m_checkboxClouds.IsChecked()?1:0);
app.SetGameSettings(m_iPad,eGameSetting_BedrockFog,m_checkboxBedrockFog.IsChecked()?1:0);
app.SetGameSettings(m_iPad,eGameSetting_CustomSkinAnim,m_checkboxCustomSkinAnim.IsChecked()?1:0);
app.SetGameSettings(m_iPad,eGameSetting_VSync,m_checkboxVSync.IsChecked()?1:0);
app.SetGameSettings(m_iPad,eGameSetting_ExclusiveFullscreen,m_checkboxExclusiveFullscreen.IsChecked()?1:0);
#ifdef _WINDOWS64
g_bVSync = m_checkboxVSync.IsChecked();
SetExclusiveFullscreen(m_checkboxExclusiveFullscreen.IsChecked());
#endif
navigateBack();
handled = true;
@@ -12,18 +12,22 @@ private:
eControl_Clouds,
eControl_BedrockFog,
eControl_CustomSkinAnim,
eControl_VSync,
eControl_ExclusiveFullscreen,
eControl_RenderDistance,
eControl_Gamma,
eControl_FOV,
eControl_InterfaceOpacity
};
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim, m_checkboxVSync, m_checkboxExclusiveFullscreen; // Checkboxes
UIControl_Slider m_sliderRenderDistance, m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity; // Sliders
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_checkboxClouds, "Clouds")
UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog")
UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim")
UI_MAP_ELEMENT( m_checkboxVSync, "VSync")
UI_MAP_ELEMENT( m_checkboxExclusiveFullscreen, "ExclusiveFullscreen")
UI_MAP_ELEMENT( m_sliderRenderDistance, "RenderDistance")
UI_MAP_ELEMENT( m_sliderGamma, "Gamma")
UI_MAP_ELEMENT(m_sliderFOV, "FOV")
@@ -1,7 +1,7 @@
#include "stdafx.h"
#include "UI.h"
#include "UIScene_SettingsOptionsMenu.h"
// pasted legit out of lcen client lol
#define _ENABLE_LANGUAGE_SELECT
int UIScene_SettingsOptionsMenu::m_iDifficultySettingA[4]=
@@ -193,12 +193,12 @@ void UIScene_TeleportMenu::tick()
{
m_players[i] = player->GetSmallId();
short icon = app.GetPlayerColour( m_players[i] );
short icon = static_cast<short>(app.GetPlayerMapIconByName(player->GetOnlineName()));
if(icon != m_playersColourState[i])
{
m_playersColourState[i] = icon;
m_playerList.setPlayerIcon( i, (int)app.GetPlayerColour( m_players[i] ) );
m_playerList.setPlayerIcon( i, (int)icon );
}
wstring playerName = L"";
+3
View File
@@ -247,11 +247,14 @@ typedef struct _SaveListDetails
#endif
#endif
bool isHardcore;
_SaveListDetails()
{
saveId = 0;
pbThumbnailData = nullptr;
dwThumbnailSize = 0;
isHardcore = false;
#ifdef _DURANGO
ZeroMemory(UTF16SaveName,sizeof(wchar_t)*128);
ZeroMemory(UTF16SaveFilename,sizeof(wchar_t)*MAX_SAVEFILENAME_LENGTH);

Some files were not shown because too many files have changed in this diff Show More