Author SHA1 Message Date
str1k3r 9dc7353939 push something i forgot on my macbook for a month 2026-06-28 14:44:19 -04:00
Byte 3e8284ace8 fix: Minecraft Store 1; feat: Community-Made Packs integration 2026-06-25 23:04:35 +02:00
Byte e7a44db374 fix: achievements crashes 2026-06-24 22:27:22 +02:00
Byte 028dcdce41 feat: achievements, minecraft store, languages, auto lb sendStats, more Language Strings 2026-06-23 20:40:27 +02:00
Byte 658849b427 add the shitty lcen code 2026-06-22 07:25:49 +02:00
str1k3r 8a6d21779d Fix Sending Auth Token Over Header & Update Leaderboard 2026-06-20 03:01:29 -04:00
str1k3r a9e98d3c03 Send Token Over Header 2026-06-19 20:23:13 -04:00
str1k3r 7f72bf5549 Fix Not Building 2026-06-18 14:35:11 -04:00
str1k3r 584d2a517f Feat: Add Leaderboard 2026-06-18 05:50:13 -04:00
str1k3r 525c5170b9 Give WinsockNetLayer::DoWinHttpRequest a url instead of it just being 1 2026-06-15 22:38:00 -04:00
str1k3r fc93ed09bf Fix Strings 2026-06-06 13:22:21 -04:00
str1k3r eec0e6bdc4 Update: Modify submodule URL for 4JLibs and add .idea to .gitignore 2026-06-05 11:58:50 -04:00
str1k3r 39cb8cbc54 Fix: Game not launching with launcher 2026-06-03 11:03:07 -04:00
str1k3r e44a98b518 Update to new Paths 2026-06-02 13:46:50 -04:00
str1k3r 0002344ea3 Remove RapidJson 2026-05-28 01:18:46 -04:00
str1k3r 9795b96e8f Feat: Allow Launching from launchers 2026-05-27 08:21:56 -04:00
str1k3r 77b5b16de4 Fix: Splitscreen for proper backend detection 2026-05-25 05:04:04 -04:00
str1k3r ed0823fe95 Fix: add the discordgamesdk dll to fix the newest build 😭 2026-05-22 03:02:32 -04:00
str1k3r 62fdc45d3f Feat: update to Game SDK, add Discord Login
This is honestly shitty code that works imo
2026-05-21 23:11:34 -04:00
str1k3r 02f1e14855 Remove Critical Hit Sound to Be Accurate to TU19/24 2026-05-13 06:36:55 -04:00
str1k3r d6232544ca Remove Stained Glass, Sword of Debug & Updated PORTING.md
Remove stained glass as its not accurate to TU19 up to TU24, Update PORTING.md to include versions we are trying to achieve & Remove the sword of debug as it was a debug item thats not needed.
2026-05-13 05:49:50 -04:00
str1k3randGitHub fb83868d25 Update server release tags link in README 2026-05-13 02:35:52 -04:00
str1k3r e3056038b9 Add Banner to Readme 2026-05-13 02:31:27 -04:00
str1k3r 80bc1e74d8 Update COMPILE.md & CONTRIBUTING.md 2026-05-13 02:24:43 -04:00
str1k3r 0fc8b1ef44 fix README.md 2026-05-13 02:20:21 -04:00
str1k3r 5f79f00dd2 Add all .md files needed 2026-05-13 02:16:10 -04:00
str1k3randGitHub 568e5a5a7f Change trigger branch from 'main' to 'TU19' 2026-05-13 01:17:01 -04:00
str1k3r 590556ae49 Move all settings to Windows64/Settings & Ensure the folder exists 2026-05-13 01:11:43 -04:00
str1k3randGitHub e0c09e7afb Update TU31.yml 2026-05-12 22:59:48 -04:00
str1k3randGitHub 84a59834a7 Add nightly release workflow for TU31 2026-05-12 22:58:49 -04:00
str1k3r 70086d3b28 New Repo Initial Commit
Add Discord RPC back with new features, add beta splitscreen support,

PR's from MCLCE used in this
https://github.com/MCLCE/MinecraftConsoles/pull/1044
https://github.com/MCLCE/MinecraftConsoles/pull/1136
https://github.com/MCLCE/MinecraftConsoles/pull/1245
2026-05-12 20:57:36 -04:00
str1k3randGitHub cbe40abcdb Initial commit 2026-05-12 20:34:42 -04:00
842 changed files with 115927 additions and 169223 deletions
-3
View File
@@ -1,3 +0,0 @@
.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.

Before

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 KiB

+107
View File
@@ -0,0 +1,107 @@
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-*
+63 -169
View File
@@ -1,213 +1,107 @@
name: Nightly Release
on:
workflow_dispatch:
workflow_dispatch:
push:
branches:
- 'TU19'
paths:
- '**'
- '!.gitignore'
- '!*.md'
- '!.github/**'
- '.github/workflows/nightly.yml'
permissions:
contents: write
id-token: write
attestations: write
packages: write
concurrency:
group: nightly
cancel-in-progress: true
jobs:
build-client:
name: Build Client
runs-on: [self-hosted, windows]
build:
runs-on: windows-latest
strategy:
matrix:
platform: [Windows64]
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v6
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: https://github.com/ilammy/msvc-dev-cmd@v1
uses: ilammy/msvc-dev-cmd@v1
- name: Setup CMake
uses: https://github.com/lukka/get-cmake@latest
uses: lukka/get-cmake@latest
- name: Run CMake
uses: https://github.com/lukka/run-cmake@v10
uses: lukka/run-cmake@v10
env:
VCPKG_ROOT: ""
VCPKG_ROOT: "" # Disable vcpkg for CI builds
with:
configurePreset: windows64
buildPreset: windows64-release
configurePreset: ${{ env.MATRIX_PLATFORM }}
buildPreset: ${{ env.MATRIX_PLATFORM }}-release
buildPresetAdditionalArgs: "['--target', 'Minecraft.Client']"
- name: Zip Build
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"
run: 7z a -r LCE${{ matrix.platform }}.zip ./build/${{ env.MATRIX_PLATFORM }}/Minecraft.Client/Release/* "-x!*.ipdb" "-x!*.iobj"
- name: Stage artifacts
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path 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/
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: https://github.com/actions/upload-artifact@v3
uses: actions/upload-artifact@v6
with:
name: client-build
name: build-${{ matrix.platform }}
path: staging/*
release-client:
name: Release Client
needs: build-client
runs-on: [self-hosted, linux]
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v6
- name: Download client artifacts
uses: https://github.com/actions/download-artifact@v3
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
name: client-build
path: artifacts
merge-multiple: true
- 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
- name: Update release
uses: andelf/nightly-release@main
env:
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
- name: Import GPG key
uses: https://github.com/crazy-max/ghaction-import-gpg@v6
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_user_signingkey: true
git_tag_gpgsign: true
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/*
- 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
cleanup:
needs: [build, release]
if: always()
runs-on: ubuntu-latest
steps:
- name: Cleanup artifacts
uses: geekyeggo/delete-artifact@v5
with:
name: build-*
+12 -15
View File
@@ -4,34 +4,31 @@ on:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize]
paths-ignore:
- '.gitignore'
- '*.md'
- '.github/*.md'
paths:
- '**'
- '!.gitignore'
- '!*.md'
- '!.github/**'
- '.github/workflows/pull-request.yml'
jobs:
build:
runs-on: [self-hosted, windows]
runs-on: windows-latest
steps:
- name: Checkout
uses: https://github.com/actions/checkout@v6
uses: actions/checkout@v6
with:
submodules: recursive
- name: Setup MSVC
uses: https://github.com/ilammy/msvc-dev-cmd@v1
uses: ilammy/msvc-dev-cmd@v1
- name: Setup CMake
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
uses: lukka/get-cmake@latest
- name: Run CMake
uses: https://github.com/lukka/run-cmake@v10
uses: lukka/run-cmake@v10
env:
VCPKG_ROOT: "" # Disable vcpkg for CI builds
with:
+1 -9
View File
@@ -26,7 +26,6 @@ mono_crash.*
[Rr]elease/
[Rr]eleases/
x64/
x64_*/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
@@ -416,19 +415,12 @@ 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://github.com/itsRevela/4JLibs.git
url = https://gitea.str1k3r.xyz/str1k3r/4JLibs.git
-116
View File
@@ -1,116 +0,0 @@
{
"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
}
}
+5 -16
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.24)
project(LCE-Revelations LANGUAGES C CXX RC ASM_MASM)
project(MinecraftConsoles LANGUAGES C CXX RC ASM_MASM)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
@@ -12,6 +12,7 @@ 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"
@@ -20,7 +21,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>
@@ -38,10 +39,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 /Zi>
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/GL>
)
target_link_options(${target} PRIVATE
$<$<CONFIG:Release>:/LTCG:incremental /DEBUG /OPT:REF /OPT:ICF>
$<$<CONFIG:Release>:/LTCG:incremental>
)
endif()
@@ -67,14 +68,9 @@ 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})
# ---
@@ -84,10 +80,6 @@ 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
@@ -105,9 +97,6 @@ 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
+61 -121
View File
@@ -1,59 +1,14 @@
# Compile Instructions
## Prerequisites
## Visual Studio
- **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`
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`
## CMake (Windows x64)
@@ -65,48 +20,12 @@ 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
@@ -114,20 +33,6 @@ 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.
@@ -150,40 +55,75 @@ Install xwin for downloading the Windows SDK:
cargo install xwin
```
### Compile
### Download Windows SDK
Download and extract the Windows SDK and CRT:
Run this (Release):
```bash
./build-linux.sh
xwin --accept-license splat --output ~/.cache/xwin/splat
```
Or, for debug:
Create symlinks to account for Linux filesystems being case sensitive:
```bash
./build-linux.sh . Debug
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
```
### Configure
### NixOS / Nix
For NixOS or systems with Nix installed, use the provided flake:
Set environment variables and configure CMake:
```bash
nix build .#client
nix build .#server
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"
```
Or enter the development shell with all dependencies:
### Build
Build Release:
```bash
nix develop
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
```
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`.
+4 -11
View File
@@ -1,5 +1,8 @@
# 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, quality of life, and platform support over these things.
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)
## 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...
@@ -30,21 +33,11 @@ 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)
+19 -18
View File
@@ -6,8 +6,6 @@
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);
@@ -20,18 +18,21 @@ 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);
@@ -72,20 +73,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();
}
else
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
{
t->begin();
t->color(255, 255, 255, 32);
@@ -110,22 +111,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,7 +9,5 @@ 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);
};
+3 -11
View File
@@ -21,13 +21,9 @@ 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" "Windows64/NetworkHelpers.h" "Windows64/NetworkHelpers.cpp" "Windows64/Windows64_Launcher.cpp" "Windows64/Windows64_Launcher.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")
# Only define executable on windows
if(PLATFORM_NAME STREQUAL "Windows64")
@@ -39,7 +35,6 @@ 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}
@@ -57,7 +52,6 @@ set_target_properties(Minecraft.Client PROPERTIES
target_link_libraries(Minecraft.Client PRIVATE
Minecraft.World
d3d11
dxgi
d3dcompiler
XInput9_1_0
wsock32
@@ -67,9 +61,6 @@ 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
@@ -82,7 +73,7 @@ endforeach()
# ---
include("${CMAKE_SOURCE_DIR}/cmake/CopyAssets.cmake")
set(ASSET_FOLDER_PAIRS
"${CMAKE_CURRENT_SOURCE_DIR}/music" "music"
"${CMAKE_CURRENT_SOURCE_DIR}/Music" "${PLATFORM_NAME}Media/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"
@@ -95,4 +86,5 @@ 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()
+8 -25
View File
@@ -6,7 +6,6 @@
#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;
@@ -16,12 +15,7 @@ int ChatScreen::s_chatIndex = 0;
bool ChatScreen::isAllowedChatChar(wchar_t c)
{
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;
return c >= 0x20 && (c == L'\u00A7' || allowedChars.empty() || allowedChars.find(c) != wstring::npos);
}
ChatScreen::ChatScreen()
@@ -116,9 +110,6 @@ 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))
@@ -161,7 +152,6 @@ 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); }
}
}
@@ -172,21 +162,14 @@ void ChatScreen::render(int xm, int ym, float a)
int x = 4;
drawString(font, prefix, x, height - 12, 0xe0e0e0);
x += font->width(prefix);
// 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);
wstring beforeCursor = message.substr(0, cursorIndex);
wstring afterCursor = message.substr(cursorIndex);
drawStringLiteral(font, beforeCursor, x, height - 12, 0xe0e0e0);
x += font->widthLiteral(beforeCursor);
if (frame / 6 % 2 == 0)
drawString(font, L"_", cursorX, height - 12, 0xe0e0e0);
drawString(font, L"_", x, height - 12, 0xe0e0e0);
x += font->width(L"_");
drawStringLiteral(font, afterCursor, x, height - 12, 0xe0e0e0);
Screen::render(xm, ym, a);
}
+16 -231
View File
@@ -58,7 +58,6 @@
#ifdef _WINDOWS64
#include "Xbox/Network/NetworkPlayerXbox.h"
#include "Common/Network/PlatformNetworkManagerStub.h"
#include "Windows64/Network/WinsockNetLayer.h"
#endif
@@ -67,30 +66,6 @@
#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.
@@ -135,7 +110,6 @@ ClientConnection::ClientConnection(Minecraft *minecraft, Socket *socket, int iUs
started = false;
savedDataStorage = new SavedDataStorage(nullptr);
maxPlayers = 20;
m_isForkServer = false;
this->minecraft = minecraft;
@@ -368,7 +342,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, packet->m_isHardcore, 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, false, 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;
@@ -403,7 +377,6 @@ 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
@@ -438,7 +411,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, packet->m_isHardcore, 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, false, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
dimensionLevel->savedDataStorage = activeLevel->savedDataStorage;
@@ -474,7 +447,6 @@ 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
@@ -945,36 +917,6 @@ 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
@@ -1004,7 +946,6 @@ 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))
@@ -1142,35 +1083,33 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr<MoveEntityPacketSmall> p
void ClientConnection::handleRemoveEntity(shared_ptr<RemoveEntitiesPacket> packet)
{
#ifdef _WINDOWS64
// 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())
if (!g_NetworkManager.IsHost())
{
for (int i = 0; i < packet->ids.length; i++)
{
shared_ptr<Entity> entity = getEntity(packet->ids[i]);
if (entity != nullptr)
if (entity != nullptr && entity->GetType() == eTYPE_PLAYER)
{
shared_ptr<Player> player = dynamic_pointer_cast<Player>(entity);
if (player != nullptr)
{
for (int s = 1; s < MINECRAFT_NET_MAX_PLAYERS; ++s)
PlayerUID xuid = player->getXuid();
INetworkPlayer* np = g_NetworkManager.GetPlayerByXuid(xuid);
if (np != nullptr)
{
IQNetPlayer* qp = &IQNet::m_player[s];
if (qp->GetCustomDataValue() != 0 &&
_wcsicmp(qp->m_gamertag, player->getName().c_str()) == 0)
NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np;
IQNetPlayer* qp = npx->GetQNetPlayer();
if (qp != nullptr)
{
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;
}
}
}
@@ -2944,7 +2883,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, packet->m_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, minecraft->level->getLevelData()->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 )
@@ -3389,9 +3328,7 @@ void ClientConnection::handleTileEditorOpen(shared_ptr<TileEditorOpenPacket> pac
void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
{
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());
app.DebugPrintf("ClientConnection::handleSignUpdate - ");
if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z))
{
shared_ptr<TileEntity> te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z);
@@ -3405,7 +3342,7 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
ste->SetMessage(i,packet->lines[i]);
}
app.DebugPrintf("[SIGN] verified=%d censored=%d\n", packet->m_bVerified, packet->m_bCensored);
app.DebugPrintf("verified = %d\tCensored = %d\n",packet->m_bVerified,packet->m_bCensored);
ste->SetVerified(packet->m_bVerified);
ste->SetCensored(packet->m_bCensored);
@@ -3413,12 +3350,12 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
}
else
{
app.DebugPrintf("[SIGN] ERROR: tile entity is not a SignTileEntity\n");
app.DebugPrintf("dynamic_pointer_cast<SignTileEntity>(te) == nullptr\n");
}
}
else
{
app.DebugPrintf("[SIGN] ERROR: chunk not loaded at position\n");
app.DebugPrintf("hasChunkAt failed\n");
}
}
@@ -3805,158 +3742,6 @@ 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,7 +48,6 @@ 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); }
+2 -10
View File
@@ -1,13 +1,5 @@
#include "stdafx.h"
#include "ClientConstants.h"
#include <string>
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"";
}
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;
+1 -3
View File
@@ -13,9 +13,7 @@ class ClientConstants
// INTERNAL DEVELOPMENT SETTINGS
public:
static const wstring VERSION_STRING;
static const wstring LCEN_STRING;
static const wchar_t* LCEN_HOST;
static std::wstring GetLCENString();
static const wstring BRANCH_STRING;
static const bool DEADMAU5_CAMERA_CHEATS = false;
};
-3
View File
@@ -45,7 +45,6 @@
#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
@@ -105,8 +104,6 @@ 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,9 +178,6 @@ enum eGameSetting
// PSVita
eGameSetting_PSVita_NetworkModeAdhoc,
// PC
eGameSetting_VSync,
eGameSetting_ExclusiveFullscreen,
};
@@ -651,7 +648,6 @@ 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
+82 -161
View File
@@ -8,8 +8,6 @@
#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__
@@ -27,7 +25,7 @@
#include <vector>
#include <memory>
#include <mutex>
#include <lce_filesystem/lce_filesystem.h>
#include <lce_filesystem\lce_filesystem.h>
#ifdef __ORBIS__
#include <audioout.h>
@@ -67,7 +65,7 @@ void SoundEngine::playMusicTick() {};
#ifdef _WINDOWS64
char SoundEngine::m_szSoundPath[]={"Windows64Media\\Sound\\"};
char SoundEngine::m_szMusicPath[]={"music\\"};
char SoundEngine::m_szMusicPath[]={"Windows64Media\\Music\\"};
char SoundEngine::m_szRedistName[]={"redist64"};
#elif defined _DURANGO
char SoundEngine::m_szSoundPath[]={"Sound\\"};
@@ -116,9 +114,6 @@ const char *SoundEngine::m_szStreamFileA[eStream_Max]=
"hal4",
"nuance1",
"nuance2",
"piano1",
"piano2",
"piano3",
#ifndef _XBOX
"creative1",
@@ -133,6 +128,10 @@ const char *SoundEngine::m_szStreamFileA[eStream_Max]=
"menu4",
#endif
"piano1",
"piano2",
"piano3",
// Nether
"nether1",
"nether2",
@@ -410,13 +409,6 @@ 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;
@@ -476,69 +468,65 @@ 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);
// Check path cache first to avoid expensive filesystem probing
auto cacheIt = m_soundPathCache.find(iSound);
if (cacheIt != m_soundPathCache.end())
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++)
{
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());
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;
}
}
else
{
// 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)
if (!found)
{
int count = 0;
for (size_t extIdx = 0; extIdx < extCount; extIdx++)
{
char basePlusExt[256];
sprintf_s(basePlusExt, "%s%s", basePath, extensions[extIdx]);
DWORD attr = GetFileAttributesA(basePlusExt);
if (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY))
for (size_t i = 1; i < 32; i++)
{
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++)
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))
{
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);
}
count = i;
}
}
}
m_soundPathCache[iSound] = validPaths;
if (validPaths.empty())
if (count > 0)
{
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());
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);
}
}
}
@@ -558,7 +546,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_DECODE | MA_SOUND_FLAG_ASYNC,
MA_SOUND_FLAG_ASYNC,
nullptr,
nullptr,
&s->sound) != MA_SUCCESS)
@@ -617,40 +605,24 @@ 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);
// Check UI sound path cache first
auto cacheIt = m_uiSoundPathCache.find(iSound);
if (cacheIt != m_uiSoundPathCache.end())
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++)
{
if (cacheIt->second.empty())
sprintf_s(finalPath, "%s%s", basePath, extensions[i]);
if (FileExists(finalPath))
{
app.DebugPrintf("No sound file found for UI sound (cached): %s\n", basePath);
return;
found = true;
break;
}
sprintf_s(finalPath, "%s", cacheIt->second.c_str());
}
else
if (!found)
{
// 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;
app.DebugPrintf("No sound file found for UI sound: %s\n", basePath);
return;
}
MiniAudioSound* s = new MiniAudioSound();
@@ -664,7 +636,7 @@ void SoundEngine::playUI(int iSound, float volume, float pitch)
if (ma_sound_init_from_file(
&m_engine,
finalPath,
MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC,
MA_SOUND_FLAG_ASYNC,
nullptr,
nullptr,
&s->sound) != MA_SUCCESS)
@@ -817,46 +789,6 @@ 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
@@ -864,33 +796,29 @@ int SoundEngine::getOverworldMusicID(Minecraft *pMinecraft)
/////////////////////////////////////////////
int SoundEngine::getMusicID(int iDomain)
{
int result=-1;
int iRandomVal=0;
Minecraft *pMinecraft=Minecraft::GetInstance();
// Before the game has started?
if(pMinecraft==nullptr)
{
#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
// any track from the overworld
return GetRandomishTrack(m_iStream_Overworld_Min,m_iStream_Overworld_Max);
}
else if(pMinecraft->skins->isUsingDefaultSkin())
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
result = m_iStream_End_Min;
break;
return m_iStream_End_Min;
case LevelData::DIMENSION_NETHER:
result = GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
break;
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);
default: //overworld
result = getOverworldMusicID(pMinecraft);
break;
//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);
}
}
else
@@ -899,22 +827,15 @@ int SoundEngine::getMusicID(int iDomain)
switch(iDomain)
{
case LevelData::DIMENSION_END:
result = GetRandomishTrack(m_iStream_End_Min,m_iStream_End_Max);
break;
return GetRandomishTrack(m_iStream_End_Min,m_iStream_End_Max);
case LevelData::DIMENSION_NETHER:
result = GetRandomishTrack(m_iStream_Nether_Min,m_iStream_Nether_Max);
break;
//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);
default: //overworld
result = getOverworldMusicID(pMinecraft);
break;
//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);
}
}
#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;
}
/////////////////////////////////////////////
@@ -1579,4 +1500,4 @@ char *SoundEngine::ConvertSoundPathToName(const wstring& name, bool bConvertSpac
return buf;
}
#endif
#endif
+5 -15
View File
@@ -1,13 +1,10 @@
#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;
@@ -26,10 +23,8 @@ 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,
@@ -41,6 +36,9 @@ 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,
@@ -136,7 +134,6 @@ 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();
@@ -188,15 +185,8 @@ 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
+38 -40
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,8 +223,6 @@ 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,7 +45,6 @@ enum eAward
eAward_bookcase,
#endif
eAward_adventuringTime,
eAward_repopulation,
//eAward_porkChop,
+15 -122
View File
@@ -188,7 +188,6 @@ CMinecraftApp::CMinecraftApp()
#endif
ZeroMemory(m_playerColours,MINECRAFT_NET_MAX_PLAYERS);
ZeroMemory(m_playerMapIcons,MINECRAFT_NET_MAX_PLAYERS);
m_iDLCOfferC=0;
m_bAllDLCContentRetrieved=true;
@@ -208,8 +207,6 @@ CMinecraftApp::CMinecraftApp()
m_dwRequiredTexturePackID=0;
m_bResetNether=false;
m_seedOverride = 0;
m_hasSeedOverride = false;
#ifdef _XBOX
// m_bTransferSavesToXboxOne=false;
@@ -791,7 +788,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, "settings.dat", _TRUNCATE);
strncat_s(outPath, size, "Windows64/Settings/settings.dat", _TRUNCATE);
}
static void Win64_SaveSettings(GAME_SETTINGS *gs)
{
@@ -842,8 +839,11 @@ void CMinecraftApp::InitGameSettings()
memset(pProfileSettings,0,sizeof(C_4JProfile::PROFILESETTINGS));
SetDefaultOptions(pProfileSettings,i);
Win64_LoadSettings(GameSettingsA[i]);
app.SetMinecraftLocale(i, GameSettingsA[i]->ucLocale);
app.loadStringTable();
app.DebugPrintf("Loaded language: %d\n", GameSettingsA[i]->ucLanguage);
app.SetMinecraftLanguage(i, GameSettingsA[i]->ucLanguage);
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,12 +851,6 @@ void CMinecraftApp::InitGameSettings()
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]);
}
}
}
@@ -866,6 +860,7 @@ 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);
@@ -950,6 +945,7 @@ 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
}
@@ -1391,7 +1387,6 @@ void CMinecraftApp::ApplyGameSettingsChanged(int iPad)
ActionGameSettings(iPad,eGameSetting_AnimatedCharacter);
ActionGameSettings(iPad,eGameSetting_PS3_EULA_Read);
ActionGameSettings(iPad,eGameSetting_VSync);
}
@@ -1627,22 +1622,6 @@ 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;
}
}
@@ -2354,38 +2333,6 @@ 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;
}
}
@@ -2521,12 +2468,6 @@ 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;
}
@@ -4713,7 +4654,6 @@ int CMinecraftApp::SignoutExitWorldThreadProc( void* lpParameter )
break;
case DisconnectPacket::eDisconnect_OutdatedClient:
exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
break;
default:
exitReasonStringId = IDS_DISCONNECTED;
}
@@ -6663,11 +6603,12 @@ 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;"},
};
static std::unordered_map<wchar_t, wchar_t*> replacementMap = {
{L'&', L"&amp;"},
{L'<', L"&lt;"},
{L'>', L"&gt;"},
{L'\"', L"&quot;"},
};
wstring finalString = L"";
for (int i = 0; i < desc.size(); i++) {
@@ -6738,8 +6679,6 @@ 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)) {
@@ -8240,16 +8179,6 @@ 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;
@@ -8351,9 +8280,6 @@ 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;
@@ -8632,39 +8558,6 @@ 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)
{
@@ -9806,7 +9699,7 @@ bool CMinecraftApp::IsLocalMultiplayerAvailable()
// 4J-PB - language and locale function
// getLocale from LCEN Client pasted ig
void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
{
#ifdef _WINDOWS64
+1 -16
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 = 2*972; // per user
static const int GAME_DEFINED_PROFILE_DATA_BYTES = 3*972; // per user
#endif
unsigned int uiGameDefinedDataChangedBitmask;
@@ -708,8 +708,6 @@ private:
bool m_bGameNewWorldSizeUseMoat;
unsigned int m_GameNewHellScale;
#endif
int64_t m_seedOverride;
bool m_hasSeedOverride;
unsigned int FromBigEndian(unsigned int uiValue);
public:
@@ -727,10 +725,6 @@ 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();
@@ -755,14 +749,10 @@ 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);
@@ -817,10 +807,6 @@ 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:
@@ -842,7 +828,6 @@ 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.

Before

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 B

Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -38220,56 +38220,6 @@
<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>
@@ -38324,16 +38274,6 @@
<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>
@@ -38459,66 +38399,6 @@
<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,7 +214,6 @@ 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,8 +76,11 @@ 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
@@ -1,212 +0,0 @@
#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
@@ -1,23 +0,0 @@
#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,7 +29,6 @@ IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu()
m_pointerPos.y = 0.0f;
m_bPointerDrivenByMouse = false;
m_iLastMouseTickTimeNs = -1;
}
IUIScene_AbstractContainerMenu::~IUIScene_AbstractContainerMenu()
@@ -267,21 +266,6 @@ 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)
{
@@ -438,10 +422,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 * fFrameScale;
fInputY *= fInputScale * fFrameScale;
fInputX *= fInputScale;
fInputY *= fInputScale;
#ifdef USE_POINTER_ACCEL
#ifdef USE_POINTER_ACCEL
m_fPointerAccelX += fInputX / 50.0f;
m_fPointerAccelY += fInputY / 50.0f;
@@ -1285,8 +1269,36 @@ void IUIScene_AbstractContainerMenu::onMouseTick()
vPointerPos.x -= m_fPointerImageOffsetX;
vPointerPos.y -= m_fPointerImageOffsetY;
// Keep sub-pixel float state so deltas <1px accumulate across frames; the renderer
// truncates to integer pixels when emitting the Iggy mouse event.
// 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));
m_pointerPos = vPointerPos;
adjustPointerForSafeZone();
@@ -145,8 +145,6 @@ 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,40 +210,6 @@ 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())
@@ -492,16 +458,6 @@ 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)
+2 -12
View File
@@ -5,8 +5,6 @@
#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"
@@ -22,7 +20,6 @@ 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;
@@ -97,10 +94,9 @@ void IUIScene_HUD::updateFrameTick()
ShowHealth(false);
ShowFood(false);
ShowAir(false);
ShowArmour(false);
ShowArmour(false);
ShowExpBar(false);
SetHealthAbsorb(0);
SetHardcoreMode(false);
SetHealthAbsorb(0);
}
if(pMinecraft->localplayers[iPad]->isRidingJumpable())
@@ -210,12 +206,6 @@ 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,7 +11,6 @@ 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;
@@ -47,7 +46,6 @@ 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,72 +410,11 @@ 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;
@@ -686,17 +625,6 @@ 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();
+13 -3
View File
@@ -141,9 +141,6 @@ 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);
}
@@ -256,6 +253,19 @@ 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,7 +3,6 @@
#include "UIScene.h"
#include "UIControl_Label.h"
class UIComponent_PressStartToPlay : public UIScene
{
private:
@@ -51,7 +50,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,27 +88,23 @@ 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:
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT:
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
safeBottom = getSafeZoneHalfHeight();
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
safeTop = getSafeZoneHalfHeight();
safeRight = getSafeZoneHalfWidth();
safeBottom = getSafeZoneHalfHeight();
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT:
safeTop = getSafeZoneHalfHeight();
@@ -116,22 +112,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:
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
safeRight = getSafeZoneHalfWidth();
break;
case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
default:
safeTop = getSafeZoneHalfHeight();
safeBottom = getSafeZoneHalfHeight();
safeLeft = getSafeZoneHalfWidth();
safeRight = getSafeZoneHalfWidth();
break;
}
setSafeZone(safeTop, safeBottom, safeLeft, safeRight);
@@ -142,54 +138,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();
}
}
@@ -198,16 +194,29 @@ void UIComponent_Tooltips::tick()
void UIComponent_Tooltips::render(S32 width, S32 height, C4JRender::eViewportType viewport)
{
if((ProfileManager.GetLockedProfile()!=-1) && !ui.GetMenuDisplayed(m_iPad) && (app.GetGameSettings(m_iPad,eGameSetting_Tooltips)==0 || app.GetGameSettings(m_iPad,eGameSetting_DisplayHUD)==0))
//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)
{
return;
if (pMinecraft->level == nullptr || pMinecraft->player == nullptr)
{
menuOKoverride = true;
}
}
if(m_bSplitscreen)
{
if (m_bSplitscreen) {
//Individiualize the flags for each viewport :)
S32 xPos = 0;
S32 yPos = 0;
switch( viewport )
switch (viewport)
{
case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM:
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT:
@@ -222,6 +231,7 @@ 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;
@@ -230,7 +240,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:
@@ -248,88 +258,127 @@ 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));
IggyPlayerDrawTilesStart ( getMovie() );
m_renderWidth = tileWidth;
m_renderHeight = tileHeight;
IggyPlayerDrawTile ( getMovie() ,
tileXStart ,
tileYStart ,
tileXStart + tileWidth ,
tileYStart + tileHeight ,
0 );
IggyPlayerDrawTilesEnd ( getMovie() );
if (!renderTooltipsOK && !menuOKoverride) return;
IggyPlayerDrawTilesStart(getMovie());
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;
@@ -337,7 +386,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;
}
@@ -358,7 +407,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");
}
@@ -366,7 +415,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
@@ -381,64 +430,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;
}
}
}
@@ -449,29 +498,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:
@@ -493,7 +542,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:
@@ -518,7 +567,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;
@@ -545,5 +594,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;
}
+4 -11
View File
@@ -3,7 +3,6 @@
#include "UIControl.h"
#include "../../../Minecraft.World/StringHelpers.h"
#include "../../../Minecraft.World/JavaMath.h"
#include "../../../Minecraft.World/ArabicShaping.h"
UIControl_Base::UIControl_Base()
{
@@ -33,16 +32,13 @@ 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*) shaped.c_str();
stringVal.length = (int)shaped.length();
stringVal.string = (IggyUTF16*) m_label.c_str();
stringVal.length = m_label.length();
value[0].string16 = stringVal;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
@@ -60,16 +56,13 @@ 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*) shaped.c_str();
stringVal.length = (int)shaped.length();
stringVal.string = (IggyUTF16*)m_label.c_str();
stringVal.length = m_label.length();
value[0].string16 = stringVal;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
@@ -9,7 +9,6 @@ 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,7 +2,6 @@
#include "UI.h"
#include "UIControl_Label.h"
#include "../../../Minecraft.World/StringHelpers.h"
#include "../../../Minecraft.World/ArabicShaping.h"
UIControl_Label::UIControl_Label()
{
@@ -23,15 +22,13 @@ 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*)shaped.c_str();
stringVal.length = (int)shaped.length();
stringVal.string = (IggyUTF16*)label.c_str();
stringVal.length = label.length();
value[0].string16 = stringVal;
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value );
}
@@ -13,56 +13,6 @@
//#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);
@@ -337,11 +287,7 @@ 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;
@@ -394,16 +340,8 @@ 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,7 +1,6 @@
#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)
{
@@ -70,14 +69,12 @@ 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*)shaped.c_str();
stringVal.length = static_cast<S32>(shaped.length());
stringVal.string = (IggyUTF16*)label.c_str();
stringVal.length = static_cast<S32>(label.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)
+12 -15
View File
@@ -16,7 +16,6 @@
#include "../../EnderDragonRenderer.h"
#include "../../MultiPlayerLocalPlayer.h"
#include "UIFontData.h"
#include "UIUnicodeBitmapFont.h"
#include "UISplitScreenHelpers.h"
#ifdef _WINDOWS64
#include "../../Windows64/KeyboardMouseInput.h"
@@ -197,7 +196,6 @@ 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;
@@ -312,14 +310,6 @@ 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();
@@ -592,6 +582,9 @@ 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");
@@ -938,7 +931,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::eAchievementList)
type != UIControl::eButtonList && type != UIControl::eTexturePackList && type != UIControl::eAchievementList)
continue;
// If the scene has an active panel (e.g. tab menus),
@@ -972,7 +965,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(
@@ -1855,9 +1848,11 @@ 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 )
@@ -1871,13 +1866,15 @@ GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void *
#if defined _WINDOWS64
// Only set the size to 96x96 for 1080p on Windows
UIScene *scene = uiController->GetTopScene(0);
if (scene) {
if (scene->getSceneResolution() == UIScene::eSceneResolution_1080 && (scene->getSceneType() != eUIScene_PauseMenu && scene->getSceneType() != eUIScene_MainMenu && scene->getSceneType() != eUIScene_AchievementsMenu) && isSub == false)
//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)
{
*width = 96;
*height = 96;
}
}
#endif
*destroy_callback_data = (void *)id;
+2 -3
View File
@@ -7,7 +7,6 @@ using namespace std;
class UIAbstractBitmapFont;
class UIBitmapFont;
class UIUnicodeBitmapFont;
class UITTFFont;
class UIComponent_DebugUIConsole;
class UIComponent_DebugUIMarketingGuide;
@@ -20,6 +19,7 @@ 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,7 +65,6 @@ 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;
@@ -103,7 +102,6 @@ private:
eLibrary_HUD,
eLibrary_Tooltips,
eLibrary_Default,
eLibrary_LCDefault,
eLibrary_LCInGame,
@@ -206,6 +204,7 @@ 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,11 +335,6 @@ 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,9 +125,6 @@ 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.
+5 -12
View File
@@ -2,6 +2,7 @@
#include "UI.h"
#include "UIScene.h"
#include "UISplitScreenHelpers.h"
#include "../../Lighting.h"
#include "../../LocalPlayer.h"
#include "../../ItemRenderer.h"
@@ -309,27 +310,19 @@ void UIScene::loadMovie()
if(!app.hasArchiveFile(moviePath))
{
app.DebugPrintf("WARNING: Could not find iggy movie %ls, trying other resolutions\n", moviePath.c_str());
app.DebugPrintf("WARNING: Could not find iggy movie %ls, falling back on 720\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))
{
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());
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,15 +8,12 @@
#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;
@@ -24,8 +21,7 @@ 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(L"Achievements");
m_labelAchievements.init(app.GetString(IDS_ACHIEVEMENTS));
//m_labelDesc.init(L"");
m_labelName.init(L"");
m_achievementsList.init(0);
@@ -35,19 +31,16 @@ 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();
}
@@ -61,27 +54,21 @@ 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;
@@ -89,10 +76,8 @@ 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)
@@ -104,7 +89,6 @@ wstring UIScene_AchievementsMenu::getMoviePath()
return L"AchievementsMenu";
}
}
void UIScene_AchievementsMenu::updateComponents()
{
bool bNotInGame = (Minecraft::GetInstance()->level == nullptr);
@@ -113,9 +97,7 @@ 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);
@@ -127,7 +109,6 @@ 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));
}
@@ -175,10 +156,8 @@ 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;
@@ -187,19 +166,16 @@ 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();
@@ -207,7 +183,6 @@ 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));
@@ -218,24 +193,20 @@ 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);
@@ -246,15 +217,12 @@ 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,16 +1,13 @@
#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 "UIControl_Label.h"
#include "Common/UI/UIControl_Label.h"
class UIScene_AchievementsMenu : public UIScene
{
private:
enum EControls
{
eControl_AchievementsLabel,
@@ -36,10 +33,8 @@ private:
UI_MAP_ELEMENT(m_achievementsList, "AchievementsList")
UI_END_MAP_CHILD_ELEMENTS()
UI_END_MAP_ELEMENTS_AND_NAMES()
bool showDescription = false;
public:
struct SceneMousePos
{
@@ -62,8 +57,7 @@ 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,6 +4,7 @@
#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)
{
@@ -52,10 +53,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_Connecting ||
initState == WinsockNetLayer::eJoinState_Success);
m_asyncJoinActive = (initState != WinsockNetLayer::eJoinState_Idle && initState != WinsockNetLayer::eJoinState_Cancelled);
m_asyncJoinFailed = false;
#endif
}
@@ -71,12 +72,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
@@ -93,54 +94,78 @@ void UIScene_ConnectingProgress::tick()
if (m_asyncJoinActive)
{
WinsockNetLayer::eJoinState state = WinsockNetLayer::GetJoinState();
switch (state)
{
case WinsockNetLayer::eJoinState_Connecting:
if (state == WinsockNetLayer::eJoinState_Connecting)
{
// connecting.............
int attempt = WinsockNetLayer::GetJoinAttempt();
int maxAttempts = WinsockNetLayer::GetJoinMaxAttempts();
wchar_t buf[128];
if (attempt > 1)
swprintf_s(buf, L"Connecting... (attempt %d/%d)", attempt, maxAttempts);
char buf[128];
if (attempt <= 1)
sprintf_s(buf, "Connecting...");
else
swprintf_s(buf, L"Connecting...");
m_labelTitle.setLabel(buf);
break;
sprintf_s(buf, "Connecting failed, trying again (%d/%d)", attempt, maxAttempts);
wchar_t wbuf[128];
mbstowcs(wbuf, buf, 128);
m_labelTitle.setLabel(wstring(wbuf));
}
case WinsockNetLayer::eJoinState_Success:
m_asyncJoinActive = false;
m_labelTitle.setLabel(L"Joining world...");
break;
case WinsockNetLayer::eJoinState_Cancelled:
m_asyncJoinActive = false;
navigateBack();
break;
case WinsockNetLayer::eJoinState_Rejected:
else if (state == WinsockNetLayer::eJoinState_Success)
{
m_asyncJoinActive = false;
// go go go
}
else if (state == WinsockNetLayer::eJoinState_Cancelled)
{
// cancel
m_asyncJoinActive = false;
navigateBack();
}
else if (state == 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 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;
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;
}
UINT uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_CONNECTION_FAILED, reasonStringId, uiIDA, 1, m_iPad, ConnectingProgress_OnRejectedDialogOK, nullptr);
break;
ui.RequestErrorMessage(IDS_CONNECTION_FAILED, exitReasonStringId, uiIDA, 1, ProfileManager.GetPrimaryPad(), ConnectingProgress_OnRejectedDialogOK, nullptr, nullptr);
}
case WinsockNetLayer::eJoinState_Failed:
else if (state == WinsockNetLayer::eJoinState_Failed)
{
// FAIL
m_asyncJoinActive = false;
m_asyncJoinFailed = true;
m_labelTitle.setLabel(app.GetString(IDS_CONNECTION_FAILED));
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_buttonConfirm.setVisible(true);
m_showingButton = true;
updateTooltips();
break;
default:
break;
m_controlTimer.setVisible(false);
}
return;
}
#endif
@@ -177,6 +202,7 @@ 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");
@@ -290,6 +316,7 @@ 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)
@@ -298,11 +325,9 @@ 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)
@@ -349,8 +374,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,6 +12,7 @@ private:
bool m_showingButton;
void (*m_cancelFunc)(LPVOID param);
LPVOID m_cancelFuncParam;
#ifdef _WINDOWS64
bool m_asyncJoinActive;
bool m_asyncJoinFailed;
@@ -26,9 +26,6 @@
#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,
@@ -473,7 +470,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;
@@ -657,14 +654,9 @@ void UIScene_CreateWorldMenu::handleSliderMove(F64 sliderId, F64 currentValue)
case eControl_Difficulty:
m_sliderDifficulty.handleSliderMove(value);
// 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);
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;
}
}
@@ -831,7 +823,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.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
}
else
{
@@ -1121,10 +1113,6 @@ 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() )
@@ -1191,8 +1179,7 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
Minecraft *pMinecraft = Minecraft::GetInstance();
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
// 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_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);
+9 -10
View File
@@ -490,21 +490,20 @@ 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"LCE-Revelations", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eExtraLargeText},
{L"MinecraftConsoles", 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,42 +3,24 @@
#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;
if(pMC != nullptr && pMC->localgameModes[iPad] != nullptr )
Minecraft *pMinecraft = Minecraft::GetInstance();
if(pMinecraft != nullptr && pMinecraft->localgameModes[iPad] != nullptr )
{
TutorialMode *gameMode = static_cast<TutorialMode *>(pMC->localgameModes[iPad]);
TutorialMode *gameMode = static_cast<TutorialMode *>(pMinecraft->localgameModes[iPad]);
// This just allows it to be shown
gameMode->getTutorial()->showTutorialPopup(false);
@@ -102,16 +84,8 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
switch(static_cast<int>(controlId))
{
case eControl_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);
}
m_bIgnoreInput = true;
app.SetAction(m_iPad,eAppAction_Respawn);
#ifdef _DURANGO
//InputManager.SetEnabledGtcButtons(_360_GTC_MENU|_360_GTC_PAUSE|_360_GTC_VIEW);
#endif
@@ -135,16 +109,7 @@ 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())
{
@@ -223,4 +188,4 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
}
break;
}
}
}
@@ -240,17 +240,13 @@ void UIScene_DebugOverlay::handlePress(F64 controlId, F64 childId)
case eControl_SetDay:
{
ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad());
conn->send(
TimeCommand::preparePacket(L"set", L"day")
);
conn->send( TimeCommand::preparePacket(false) );
}
break;
case eControl_SetNight:
{
ClientConnection *conn = Minecraft::GetInstance()->getConnection(ProfileManager.GetPrimaryPad());
conn->send(
TimeCommand::preparePacket(L"set", L"night")
);
conn->send( TimeCommand::preparePacket(true) );
}
break;
};
+1 -13
View File
@@ -50,19 +50,7 @@ UIScene_EndPoem::UIScene_EndPoem(int iPad, void *initData, UILayer *parentLayer)
Minecraft *pMinecraft = Minecraft::GetInstance();
wstring playerName = L"";
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";
}
playerName = escapeXML( pMinecraft->localplayers[ProfileManager.GetPrimaryPad()]->getDisplayName() );
noNoiseString = replaceAll(noNoiseString,L"{*PLAYER*}",playerName);
Random random(8124371);
@@ -287,11 +287,7 @@ 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,7 +25,6 @@ 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")
@@ -90,7 +89,6 @@ 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:
@@ -161,8 +159,6 @@ private:
void SetHealthAbsorb(int healthAbsorb);
void SetHardcoreMode(bool bHardcore);
public:
void SetSelectedLabel(const wstring &label);
void ShowDisplayName(bool show);
@@ -27,15 +27,8 @@ 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);
}
}
@@ -181,15 +174,8 @@ 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);
}
}
@@ -216,22 +202,23 @@ void UIScene_InGameInfoMenu::tick()
{
UIScene::tick();
// 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)
// Update players by index
for(DWORD i = 0; i < m_players.size(); ++i)
{
INetworkPlayer *player = g_NetworkManager.GetPlayerBySmallId( m_players[i]->m_smallId );
INetworkPlayer *player = g_NetworkManager.GetPlayerByIndex( i );
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;
@@ -437,19 +424,11 @@ 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);
@@ -512,7 +491,7 @@ UIScene_InGameInfoMenu::PlayerInfo *UIScene_InGameInfoMenu::BuildPlayerInfo(INet
}
info->m_voiceStatus = voiceStatus;
info->m_colorState = app.GetPlayerMapIconByName(player->GetOnlineName());
info->m_colorState = app.GetPlayerColour(info->m_smallId);
info->m_name = playerName;
return info;
+11 -360
View File
@@ -1,15 +1,12 @@
#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"
#ifdef _WINDOWS64
#include "../../Windows64/Network/WinsockNetLayer.h"
#endif
#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"
#define UPDATE_PLAYERS_TIMER_ID 0
#define UPDATE_PLAYERS_TIMER_TIME 30000
@@ -24,12 +21,6 @@ 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()
@@ -125,16 +116,6 @@ 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));
@@ -306,38 +287,12 @@ 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__
@@ -372,16 +327,6 @@ 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;
};
}
@@ -586,23 +531,6 @@ 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;
@@ -657,18 +585,16 @@ void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass)
if( exitReasonStringId == -1 )
{
// 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;
ui.NavigateBack(pClass->m_iPad);
}
else
{
UINT uiIDA[1];
uiIDA[0]=IDS_CONFIRM_OK;
ui.RequestErrorMessage( IDS_CONNECTION_FAILED, exitReasonStringId, uiIDA,1,ProfileManager.GetPrimaryPad());
exitReasonStringId = -1;
pClass->m_bIgnoreInput = false;
ui.NavigateToHomeMenu();
}
}
}
@@ -718,279 +644,4 @@ 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
}
+1 -10
View File
@@ -105,13 +105,4 @@ 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;
}
}
+26 -81
View File
@@ -24,7 +24,7 @@
#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50
#endif
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[5]=
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[4]=
{
IDS_DIFFICULTY_TITLE_PEACEFUL,
IDS_DIFFICULTY_TITLE_EASY,
@@ -53,7 +53,6 @@ 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;
@@ -100,7 +99,6 @@ 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;
@@ -110,7 +108,8 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
m_bThumbnailGetFailed = false;
m_seed = 0;
m_bIsCorrupt = false;
m_bHardcore = false;
m_pbThumbnailData = nullptr;
m_uiThumbnailSize = 0;
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.
@@ -250,17 +249,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)
{
// Set thumbnail name from save filename (needed for texture display in tick)
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);
}
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
ZeroMemory(wFilename, sizeof(wFilename));
mbstowcs(wFilename, params->saveDetails->UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
@@ -268,24 +267,14 @@ 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
}
@@ -425,7 +414,15 @@ void UIScene_LoadMenu::updateTooltips()
void UIScene_LoadMenu::updateComponents()
{
m_parentLayer->showComponent(m_iPad,eUIComponent_Panorama,true);
m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false);
if(RenderManager.IsWidescreen())
{
m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,true);
}
else
{
m_parentLayer->showComponent(m_iPad,eUIComponent_Logo,false);
}
}
wstring UIScene_LoadMenu::getMoviePath()
@@ -510,17 +507,6 @@ 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)
{
@@ -579,21 +565,6 @@ 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();
@@ -747,8 +718,6 @@ 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
@@ -1000,15 +969,10 @@ 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;
}
@@ -1222,7 +1186,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];
@@ -1635,24 +1599,6 @@ 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;
@@ -1685,7 +1631,6 @@ 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[5];
static int m_iDifficultyTitleSettingA[4];
UIControl m_controlMainPanel;
UIControl_Label m_labelGameName, m_labelSeed, m_labelCreatedMode;
@@ -50,7 +50,6 @@ private:
int m_iGameModeId;
bool m_bHasBeenInCreative;
bool m_bIsSaveOwner;
bool m_bRetrievingSaveThumbnail;
bool m_bSaveThumbnailReady;
bool m_bMultiplayerAllowed;
bool m_bShowTimer;
@@ -71,7 +70,6 @@ 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,13 +26,12 @@
#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, bool *outHardcore = nullptr)
static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
{
// 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)
{
@@ -50,8 +49,8 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
if (len > 0)
{
wchar_t wbuf[128] = {};
MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, 127);
sidecarName = wbuf;
mbstowcs(wbuf, buf, 127);
return wstring(wbuf);
}
}
else fclose(fr);
@@ -59,10 +58,10 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
}
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 sidecarName;
if (hFile == INVALID_HANDLE_VALUE) return L"";
DWORD fileSize = GetFileSize(hFile, nullptr);
if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); return sidecarName; }
if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); return L""; }
unsigned char *rawData = new unsigned char[fileSize];
DWORD bytesRead = 0;
@@ -70,7 +69,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
{
CloseHandle(hFile);
delete[] rawData;
return sidecarName;
return L"";
}
CloseHandle(hFile);
@@ -85,7 +84,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
if (decompSize == 0 || decompSize > 128 * 1024 * 1024)
{
delete[] rawData;
return sidecarName;
return L"";
}
saveData = new unsigned char[decompSize];
Compression::getCompression()->Decompress(saveData, &decompSize, rawData + 8, fileSize - 8);
@@ -125,11 +124,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
{
CompoundTag *dataTag = root->getCompound(L"Data");
if (dataTag != nullptr)
{
result = dataTag->getString(L"LevelName");
if (outHardcore)
*outHardcore = dataTag->getBoolean(L"hardcore");
}
delete root;
}
}
@@ -141,10 +136,6 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
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"";
@@ -536,9 +527,6 @@ void UIScene_LoadOrJoinMenu::Initialise()
{
m_iSaveListIndex = 0;
m_iGameListIndex = 0;
#ifdef _WINDOWS64
m_addServerPhase = eAddServer_Idle;
#endif
m_iDefaultButtonsC = 0;
m_iMashUpButtonsC=0;
@@ -642,11 +630,6 @@ 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" );
@@ -779,16 +762,7 @@ 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);
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");
}
wstring 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;
@@ -811,17 +785,13 @@ void UIScene_LoadOrJoinMenu::tick()
#else
#ifdef _WINDOWS64
{
bool saveHardcore = false;
wstring levelName = ReadLevelNameFromSaveFile(filePath, &saveHardcore);
m_saveDetails[i].isHardcore = saveHardcore;
wstring levelName = ReadLevelNameFromSaveFile(filePath);
if (!levelName.empty())
{
m_buttonListSaves.addItem(levelName, wstring(L""));
{
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';
}
wcstombs(m_saveDetails[i].UTF8SaveName, levelName.c_str(), 127);
m_saveDetails[i].UTF8SaveName[127] = '\0';
}
else
{
@@ -1466,9 +1436,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 (UTF-8 to preserve Unicode)
char narrowName[256] = {};
WideCharToMultiByte(CP_UTF8, 0, wNewName, -1, narrowName, 255, nullptr, nullptr);
// Convert to narrow for storage and in-memory update
char narrowName[128] = {};
wcstombs(narrowName, wNewName, 127);
// Build the sidecar path: Windows64\GameHDD\{folder}\worldname.txt
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH] = {};
@@ -1484,7 +1454,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'; // UTF8SaveName is still 128 bytes; narrowName fits as Arabic is <=2 bytes/char in UTF-8
pClass->m_saveDetails[listPos].UTF8SaveName[127] = '\0';
// Reuse the existing callback to trigger the list repopulate
UIScene_LoadOrJoinMenu::RenameSaveDataReturned(pClass, true);
@@ -1519,10 +1489,6 @@ 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:
@@ -1650,14 +1616,6 @@ 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;
@@ -1667,10 +1625,7 @@ 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);
}
@@ -1978,13 +1933,7 @@ 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;
@@ -2066,11 +2015,6 @@ 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
@@ -2136,12 +2080,7 @@ 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;
@@ -2552,7 +2491,7 @@ int UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad,C4JS
{
wchar_t wSaveName[128];
ZeroMemory(wSaveName, 128 * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, -1, wSaveName, 127);
mbstowcs_s(nullptr, wSaveName, 128, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, _TRUNCATE);
UIKeyboardInitData kbData;
kbData.title = app.GetString(IDS_RENAME_WORLD_TITLE);
kbData.defaultText = wSaveName;
@@ -4177,169 +4116,4 @@ int UIScene_LoadOrJoinMenu::CopySaveErrorDialogFinishedCallback(void *pParam,int
return 0;
}
#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
#endif // _XBOX_ONE
@@ -176,17 +176,6 @@ 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,23 +619,8 @@ void UIScene_PauseMenu::handlePress(F64 controlId, F64 childId)
Windows::Xbox::ApplicationModel::Help::Show(user);
}
break;
#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:
case BUTTON_PAUSE_ACHIEVEMENTS:
// guests can't look at achievements
/*if(ProfileManager.IsGuest(pNotifyPressData->UserIndex))
@@ -647,9 +632,11 @@ 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,11 +5,6 @@
#include "../../Options.h"
#include "../../GameRenderer.h"
#ifdef _WINDOWS64
extern bool g_bVSync;
extern void SetExclusiveFullscreen(bool enabled);
#endif
namespace
{
constexpr int FOV_MIN = 70;
@@ -67,14 +62,12 @@ 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,3,DistanceToLevel(app.GetGameSettings(m_iPad,eGameSetting_RenderDistance)));
m_sliderRenderDistance.init(TempString,eControl_RenderDistance,0,5,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));
@@ -89,50 +82,28 @@ 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)
{
#ifndef _WINDOWS64
// Console splitscreen: non-host and non-primary players can't change world-level settings
// If the game has started, then you need to be the host to change the in-game gamertags
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)
@@ -194,12 +165,6 @@ 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,22 +12,18 @@ 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, m_checkboxVSync, m_checkboxExclusiveFullscreen; // Checkboxes
UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // 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 = static_cast<short>(app.GetPlayerMapIconByName(player->GetOnlineName()));
short icon = app.GetPlayerColour( m_players[i] );
if(icon != m_playersColourState[i])
{
m_playersColourState[i] = icon;
m_playerList.setPlayerIcon( i, (int)icon );
m_playerList.setPlayerIcon( i, (int)app.GetPlayerColour( m_players[i] ) );
}
wstring playerName = L"";
-3
View File
@@ -247,14 +247,11 @@ 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