Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dc7353939 | ||
|
|
3e8284ace8 | ||
|
|
e7a44db374 | ||
|
|
028dcdce41 | ||
|
|
658849b427 | ||
|
|
8a6d21779d | ||
|
|
a9e98d3c03 | ||
|
|
7f72bf5549 | ||
|
|
584d2a517f | ||
|
|
525c5170b9 | ||
|
|
fc93ed09bf | ||
|
|
eec0e6bdc4 | ||
|
|
39cb8cbc54 | ||
|
|
e44a98b518 | ||
|
|
0002344ea3 | ||
|
|
9795b96e8f | ||
|
|
77b5b16de4 | ||
|
|
ed0823fe95 | ||
|
|
62fdc45d3f | ||
|
|
02f1e14855 | ||
|
|
d6232544ca | ||
|
|
fb83868d25 | ||
|
|
e3056038b9 | ||
|
|
80bc1e74d8 | ||
|
|
0fc8b1ef44 | ||
|
|
5f79f00dd2 | ||
|
|
568e5a5a7f | ||
|
|
590556ae49 | ||
|
|
e0c09e7afb | ||
|
|
84a59834a7 | ||
|
|
70086d3b28 | ||
|
|
cbe40abcdb |
@@ -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
|
||||
|
||||
|
Before Width: | Height: | Size: 496 KiB |
|
Before Width: | Height: | Size: 952 KiB |
|
Before Width: | Height: | Size: 646 KiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 778 KiB |
@@ -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-*
|
||||
@@ -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-*
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"&"},
|
||||
{L'<', L"<"},
|
||||
{L'>', L">"},
|
||||
};
|
||||
static std::unordered_map<wchar_t, wchar_t*> replacementMap = {
|
||||
{L'&', L"&"},
|
||||
{L'<', L"<"},
|
||||
{L'>', L">"},
|
||||
{L'\"', L"""},
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 149 B |
|
Before Width: | Height: | Size: 135 B |
|
Before Width: | Height: | Size: 153 B |
|
Before Width: | Height: | Size: 163 B |
|
Before Width: | Height: | Size: 122 B |
|
Before Width: | Height: | Size: 117 B |
|
Before Width: | Height: | Size: 125 B |
|
Before Width: | Height: | Size: 135 B |
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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, ¢er);
|
||||
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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"";
|
||||
|
||||
@@ -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);
|
||||
|
||||