Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e773e64840 | |||
| bf2b488f2d | |||
| 7c88569e8b | |||
| a02538daa0 | |||
| 6df8089003 | |||
| 76f4832a6b | |||
| 02a5961f39 | |||
| 1a3fcb5b20 | |||
| a3ca23fdf6 | |||
| c98153bf07 | |||
| a5f5595c63 | |||
| dc8af13b45 | |||
| ab16f3bf45 | |||
| 994a23f96b | |||
| e4335cfc09 | |||
| 863998e19a | |||
| 9c6186f06e | |||
| d56a4bbe2a | |||
| 24f27462a6 | |||
| d359957727 | |||
| ce739f6045 | |||
| 5a59f5d146 | |||
| 68537572e5 | |||
| 43145a9366 | |||
| 72012da42f | |||
| e5a035795b | |||
| 1a95b757ea | |||
| faf32515f5 | |||
| 97bb759ecc | |||
| 1c4e5d5f95 | |||
| 635ffc6c54 | |||
| ba6a6393e8 | |||
| d2e9808a26 | |||
| 110cec3dab | |||
| 700fdf0c41 | |||
| d7efcad139 | |||
| c60eabe32d | |||
| 7cb91529fb | |||
| a4b0572362 | |||
| c59010cb81 | |||
| a41c82539a | |||
| 1e8c7a08b6 | |||
| f0c554a893 | |||
| e10ddcacd0 | |||
| 8a20e34b31 | |||
| eaffb40316 | |||
| 50c4c42660 | |||
| 31a6facf02 | |||
| 022427cb93 | |||
| 8bd66905aa | |||
| 9397d404a6 | |||
| 54f70cd904 | |||
| e2644b2c35 | |||
| 85c589f453 | |||
| 4a284a289b | |||
| 18081f8fb9 | |||
| 514c4cf102 | |||
| b28c0026af | |||
| 176a3db770 | |||
| c00375b72c | |||
| 0b3281d17f | |||
| 857155f3d6 | |||
| e0e3a00a83 | |||
| 812b3ea6af | |||
| b51fb18120 | |||
| b1c44c33bd | |||
| 330d764972 | |||
| 3caa5713e5 | |||
| 0631aefec2 | |||
| 255a18fe8e | |||
| cffe636e35 | |||
| d1eb09a4b9 | |||
| 4b13b3345e | |||
| 0666959d31 | |||
| 9370cbc7d8 |
@@ -0,0 +1,3 @@
|
|||||||
|
.github/workflows/docker-nightly.yml merge=ours
|
||||||
|
.github/workflows/nightly.yml merge=ours
|
||||||
|
docker-compose.dedicated-server.ghcr.yml merge=ours
|
||||||
|
|||||||
|
After Width: | Height: | Size: 778 KiB |
@@ -1,31 +0,0 @@
|
|||||||
name: Build Minecraft Legacy Console Edition
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: windows-2022
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
configuration: [Release, Debug]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup MSBuild
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
|
|
||||||
- name: Build Minecraft Legacy Console Edition
|
|
||||||
run: |
|
|
||||||
msbuild MinecraftConsoles.sln `
|
|
||||||
/p:Configuration=${{ matrix.configuration }} `
|
|
||||||
/p:Platform=Windows64 `
|
|
||||||
/m
|
|
||||||
|
|
||||||
- name: Upload Release + Debug Artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: MinecraftClient-${{ matrix.configuration }}
|
|
||||||
path: x64/${{ matrix.configuration }}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
name: MSBuild Debug Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, reopened, synchronize]
|
|
||||||
paths-ignore:
|
|
||||||
- '.gitignore'
|
|
||||||
- '*.md'
|
|
||||||
- '.github/*.md'
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'main'
|
|
||||||
paths-ignore:
|
|
||||||
- '.gitignore'
|
|
||||||
- '*.md'
|
|
||||||
- '.github/*.md'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build Windows64 (DEBUG)
|
|
||||||
runs-on: windows-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Setup msbuild
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: MSBuild.exe MinecraftConsoles.sln /p:Configuration=Debug /p:Platform="Windows64"
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
name: Docker Nightly Dedicated Server
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "main"
|
|
||||||
- 'feature/dedicated-server'
|
|
||||||
paths-ignore:
|
|
||||||
- ".gitignore"
|
|
||||||
- "*.md"
|
|
||||||
- ".github/*.md"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: docker-nightly-dedicated-server
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-runtime:
|
|
||||||
name: Build Dedicated Server Runtime
|
|
||||||
runs-on: windows-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Setup msbuild
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
|
|
||||||
- name: Build Dedicated Server Runtime Only
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
MSBuild.exe Minecraft.World\Minecraft.World.vcxproj /p:Configuration=Release /p:Platform=x64 /m
|
|
||||||
MSBuild.exe Minecraft.Server\Minecraft.Server.vcxproj /p:Configuration=Release /p:Platform=x64 /m
|
|
||||||
|
|
||||||
- name: Stage dedicated server runtime
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$serverOut = "Minecraft.Server/x64/Minecraft.Server/Release"
|
|
||||||
$stage = ".artifacts/dedicated-server-runtime"
|
|
||||||
|
|
||||||
if (Test-Path $stage) {
|
|
||||||
Remove-Item -Path $stage -Recurse -Force
|
|
||||||
}
|
|
||||||
|
|
||||||
New-Item -ItemType Directory -Path (Join-Path $stage "Windows64") -Force | Out-Null
|
|
||||||
|
|
||||||
# Minimum required runtime files
|
|
||||||
$required = @(
|
|
||||||
"Minecraft.Server.exe",
|
|
||||||
"iggy_w64.dll",
|
|
||||||
"Common"
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($entry in $required) {
|
|
||||||
$src = Join-Path $serverOut $entry
|
|
||||||
if (-not (Test-Path $src)) {
|
|
||||||
throw "Missing required runtime path: $src"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Copy required files
|
|
||||||
Copy-Item -Path (Join-Path $serverOut "Minecraft.Server.exe") -Destination (Join-Path $stage "Minecraft.Server.exe") -Force
|
|
||||||
Copy-Item -Path (Join-Path $serverOut "iggy_w64.dll") -Destination (Join-Path $stage "iggy_w64.dll") -Force
|
|
||||||
Copy-Item -Path (Join-Path $serverOut "Common") -Destination (Join-Path $stage "Common") -Recurse -Force
|
|
||||||
if (Test-Path (Join-Path $serverOut "Windows64")) {
|
|
||||||
Copy-Item -Path (Join-Path $serverOut "Windows64/*") -Destination (Join-Path $stage "Windows64") -Recurse -Force
|
|
||||||
} else {
|
|
||||||
Write-Host "Windows64 directory is not present in build output; staging without it."
|
|
||||||
}
|
|
||||||
|
|
||||||
Get-ChildItem -Path $stage -Recurse -File | Select-Object -First 20 | ForEach-Object {
|
|
||||||
Write-Host "Staged: $($_.FullName)"
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Upload dedicated server runtime to artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: dedicated-server-runtime
|
|
||||||
if-no-files-found: error
|
|
||||||
path: |
|
|
||||||
.artifacts/dedicated-server-runtime/**
|
|
||||||
|
|
||||||
docker-publish:
|
|
||||||
name: Build and Push Docker Image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build-runtime
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Download dedicated server runtime from artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: dedicated-server-runtime
|
|
||||||
path: .artifacts/runtime
|
|
||||||
|
|
||||||
- name: Prepare Docker runtime directory
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
rm -rf runtime
|
|
||||||
mkdir -p runtime
|
|
||||||
cp .artifacts/runtime/Minecraft.Server.exe runtime/Minecraft.Server.exe
|
|
||||||
cp .artifacts/runtime/iggy_w64.dll runtime/iggy_w64.dll
|
|
||||||
cp -R .artifacts/runtime/Common runtime/Common
|
|
||||||
mkdir -p runtime/Windows64
|
|
||||||
if [[ -d ".artifacts/runtime/Windows64" ]]; then
|
|
||||||
cp -R .artifacts/runtime/Windows64/. runtime/Windows64/
|
|
||||||
fi
|
|
||||||
|
|
||||||
test -f runtime/Minecraft.Server.exe
|
|
||||||
test -f runtime/iggy_w64.dll
|
|
||||||
test -d runtime/Common
|
|
||||||
test -d runtime/Windows64
|
|
||||||
|
|
||||||
- name: Compute image name
|
|
||||||
id: image
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
owner="$(echo "${{ vars.CONTAINER_REGISTRY_OWNER || github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
|
||||||
image_tag="nightly"
|
|
||||||
# if [[ "${{ github.ref }}" != "refs/heads/main" ]]; then
|
|
||||||
# image_tag="nightly-test"
|
|
||||||
# fi
|
|
||||||
echo "owner=$owner" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "image=ghcr.io/$owner/minecraft-lce-dedicated-server" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "image_tag=$image_tag" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Extract Docker metadata
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ${{ steps.image.outputs.image }}
|
|
||||||
tags: |
|
|
||||||
type=raw,value=${{ steps.image.outputs.image_tag }}
|
|
||||||
|
|
||||||
- name: Login to GHCR
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ secrets.GHCR_USERNAME || github.actor }}
|
|
||||||
password: ${{ secrets.GHCR_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push image
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: docker/dedicated-server/Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
build-args: |
|
|
||||||
MC_RUNTIME_DIR=runtime
|
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
name: Nightly Server Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitignore'
|
||||||
|
- '*.md'
|
||||||
|
- '.github/**'
|
||||||
|
- '!.github/workflows/nightly-server.yml'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: nightly-server
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
platform: [Windows64]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- 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.Server']"
|
||||||
|
|
||||||
|
- name: Zip Build
|
||||||
|
run: 7z a -r LCEServer${{ matrix.platform }}.zip ./build/${{ env.MATRIX_PLATFORM }}/Minecraft.Server/Release/* -x!*.ipdb -x!*.iobj
|
||||||
|
|
||||||
|
- name: Stage artifacts
|
||||||
|
run: |
|
||||||
|
New-Item -ItemType Directory -Force -Path staging
|
||||||
|
Copy-Item LCEServer${{ matrix.platform }}.zip staging/
|
||||||
|
|
||||||
|
- name: Stage exe and pdb
|
||||||
|
if: matrix.platform == 'Windows64'
|
||||||
|
run: |
|
||||||
|
Copy-Item ./build/${{ env.MATRIX_PLATFORM }}/Minecraft.Server/Release/Minecraft.Server.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: nightly-dedicated-server
|
||||||
|
name: Nightly Dedicated Server Release
|
||||||
|
body: |
|
||||||
|
Dedicated Server runtime for Windows64.
|
||||||
|
|
||||||
|
Download `LCEServerWindows64.zip` and extract it to a folder where you'd like to keep the server runtime.
|
||||||
|
files: |
|
||||||
|
artifacts/*
|
||||||
|
|
||||||
|
docker-publish:
|
||||||
|
name: Build and Push Docker Image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Download dedicated server runtime from artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-Windows64
|
||||||
|
path: .artifacts/
|
||||||
|
|
||||||
|
- name: Prepare Docker runtime directory
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
rm -rf runtime
|
||||||
|
mkdir -p runtime
|
||||||
|
unzip .artifacts/LCEServerWindows64.zip -d runtime
|
||||||
|
|
||||||
|
- name: Compute image name
|
||||||
|
id: image
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
owner="$(echo "${{ vars.CONTAINER_REGISTRY_OWNER || github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
image_tag="nightly"
|
||||||
|
# if [[ "${{ github.ref }}" != "refs/heads/main" ]]; then
|
||||||
|
# image_tag="nightly-test"
|
||||||
|
# fi
|
||||||
|
echo "owner=$owner" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "image=ghcr.io/$owner/minecraft-lce-dedicated-server" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "image_tag=$image_tag" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ steps.image.outputs.image }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=${{ steps.image.outputs.image_tag }}
|
||||||
|
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.GHCR_USERNAME || github.actor }}
|
||||||
|
password: ${{ secrets.GHCR_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/dedicated-server/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
build-args: |
|
||||||
|
MC_RUNTIME_DIR=runtime
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
needs: [build, release]
|
||||||
|
if: always()
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Cleanup artifacts
|
||||||
|
uses: geekyeggo/delete-artifact@v5
|
||||||
|
with:
|
||||||
|
name: build-*
|
||||||
@@ -2,14 +2,6 @@ name: Nightly Releases
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'main'
|
|
||||||
- 'feature/dedicated-server'
|
|
||||||
paths-ignore:
|
|
||||||
- '.gitignore'
|
|
||||||
- '*.md'
|
|
||||||
- '.github/*.md'
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
name: Pull Request Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, reopened, synchronize]
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitignore'
|
||||||
|
- '*.md'
|
||||||
|
- '.github/*.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- 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: windows64
|
||||||
|
buildPreset: windows64-debug
|
||||||
@@ -26,6 +26,7 @@ mono_crash.*
|
|||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
x64/
|
||||||
|
x64_*/
|
||||||
x86/
|
x86/
|
||||||
[Ww][Ii][Nn]32/
|
[Ww][Ii][Nn]32/
|
||||||
[Aa][Rr][Mm]/
|
[Aa][Rr][Mm]/
|
||||||
@@ -407,39 +408,10 @@ enc_temp_folder/
|
|||||||
Minecraft.Client/Schematics/
|
Minecraft.Client/Schematics/
|
||||||
Minecraft.Client/Windows64/GameHDD/
|
Minecraft.Client/Windows64/GameHDD/
|
||||||
|
|
||||||
# Intermediate build files (per-project)
|
# CMake build output
|
||||||
Minecraft.Client/x64/
|
build/
|
||||||
Minecraft.Client/Debug/
|
|
||||||
Minecraft.Client/x64_Debug/
|
|
||||||
Minecraft.Client/Release/
|
|
||||||
Minecraft.Client/x64_Release/
|
|
||||||
|
|
||||||
Minecraft.World/x64/
|
|
||||||
Minecraft.World/Debug/
|
|
||||||
Minecraft.World/x64_Debug/
|
|
||||||
Minecraft.World/Release/
|
|
||||||
Minecraft.World/x64_Release/
|
|
||||||
|
|
||||||
Minecraft.Server/x64/
|
|
||||||
Minecraft.Server/Debug/
|
|
||||||
Minecraft.Server/x64_Debug/
|
|
||||||
Minecraft.Server/Release/
|
|
||||||
Minecraft.Server/x64_Release/
|
|
||||||
|
|
||||||
build/*
|
|
||||||
|
|
||||||
# Existing build output files
|
|
||||||
!x64/**/Effects.msscmp
|
|
||||||
!x64/**/iggy_w64.dll
|
|
||||||
!x64/**/mss64.dll
|
|
||||||
!x64/**/redist64/
|
|
||||||
|
|
||||||
# Local saves
|
|
||||||
Minecraft.Client/Saves/
|
|
||||||
|
|
||||||
|
# Server data
|
||||||
tmp*/
|
tmp*/
|
||||||
_server_asset_probe/
|
_server_asset_probe/
|
||||||
server-data/
|
server-data/
|
||||||
# Visual Studio Per-User Config
|
|
||||||
*.user
|
|
||||||
/out
|
|
||||||
|
|||||||
@@ -13,232 +13,101 @@ if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|||||||
message(FATAL_ERROR "Use a 64-bit generator/toolchain (x64).")
|
message(FATAL_ERROR "Use a 64-bit generator/toolchain (x64).")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CONFIGURATION_TYPES
|
||||||
|
"Debug"
|
||||||
|
"Release"
|
||||||
|
CACHE STRING "" FORCE
|
||||||
|
)
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
|
|
||||||
function(configure_msvc_target target)
|
function(configure_compiler_target target)
|
||||||
target_compile_options(${target} PRIVATE
|
# MSVC and compatible compilers (like Clang-cl)
|
||||||
$<$<AND:$<NOT:$<CONFIG:Release>>,$<COMPILE_LANGUAGE:C,CXX>>:/W3>
|
if (MSVC)
|
||||||
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/W0>
|
target_compile_options(${target} PRIVATE
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
|
$<$<AND:$<CONFIG:Debug>,$<COMPILE_LANGUAGE:C,CXX>>:/W3>
|
||||||
$<$<COMPILE_LANGUAGE:C,CXX>:/FS>
|
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/W0>
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
|
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
|
||||||
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/GL /O2 /Oi /GT /GF>
|
$<$<COMPILE_LANGUAGE:C,CXX>:/FS>
|
||||||
)
|
$<$<COMPILE_LANGUAGE:C,CXX>:/GS>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
|
||||||
|
$<$<COMPILE_LANGUAGE:CXX>:/GR>
|
||||||
|
$<$<AND:$<CONFIG:Debug>,$<COMPILE_LANGUAGE:C,CXX>>:/Od>
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/O2 /Oi /GT /GF>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# MSVC
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
target_compile_options(${target} PRIVATE
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/GL>
|
||||||
|
)
|
||||||
|
target_link_options(${target} PRIVATE
|
||||||
|
$<$<CONFIG:Release>:/LTCG:incremental>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Clang
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
target_compile_options(${target} PRIVATE
|
||||||
|
$<$<AND:$<CONFIG:Debug>,$<COMPILE_LANGUAGE:C,CXX>>:-O0 -Wall>
|
||||||
|
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:-O2 -w -flto>
|
||||||
|
)
|
||||||
|
target_link_options(${target} PRIVATE
|
||||||
|
$<$<CONFIG:Release>:-flto>
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/WorldSources.cmake")
|
|
||||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake")
|
|
||||||
|
|
||||||
list(TRANSFORM MINECRAFT_WORLD_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/")
|
# ---
|
||||||
list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/")
|
# Configuration
|
||||||
list(APPEND MINECRAFT_CLIENT_SOURCES
|
# ---
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/MinecraftWindows.rc"
|
set(MINECRAFT_SHARED_DEFINES
|
||||||
|
_LARGE_WORLDS
|
||||||
|
_DEBUG_MENUS_ENABLED
|
||||||
|
$<$<CONFIG:Debug>:_DEBUG>
|
||||||
|
_CRT_NON_CONFORMING_SWPRINTFS
|
||||||
|
_CRT_SECURE_NO_WARNINGS
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(MinecraftWorld STATIC ${MINECRAFT_WORLD_SOURCES})
|
# Add platform-specific defines
|
||||||
target_include_directories(MinecraftWorld PRIVATE
|
list(APPEND MINECRAFT_SHARED_DEFINES ${PLATFORM_DEFINES})
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers"
|
# ---
|
||||||
)
|
# Sources
|
||||||
target_compile_definitions(MinecraftWorld PRIVATE
|
# ---
|
||||||
$<$<CONFIG:Debug>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
add_subdirectory(Minecraft.World)
|
||||||
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
add_subdirectory(Minecraft.Client)
|
||||||
)
|
if(PLATFORM_NAME STREQUAL "Windows64") # Server is only supported on Windows for now
|
||||||
if(MSVC)
|
add_subdirectory(Minecraft.Server)
|
||||||
configure_msvc_target(MinecraftWorld)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES})
|
# ---
|
||||||
target_include_directories(MinecraftClient PRIVATE
|
# Build versioning
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client"
|
# ---
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/include"
|
set(BUILDVER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateBuildVer.cmake")
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/Sentient/Include"
|
set(BUILDVER_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated/Common/BuildVer.h")
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/"
|
|
||||||
)
|
|
||||||
target_compile_definitions(MinecraftClient PRIVATE
|
|
||||||
$<$<CONFIG:Debug>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
|
||||||
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
|
||||||
)
|
|
||||||
if(MSVC)
|
|
||||||
configure_msvc_target(MinecraftClient)
|
|
||||||
target_link_options(MinecraftClient PRIVATE
|
|
||||||
$<$<CONFIG:Release>:/LTCG /INCREMENTAL:NO>
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(MinecraftClient PROPERTIES
|
add_custom_target(GenerateBuildVer
|
||||||
VS_DEBUGGER_WORKING_DIRECTORY "$<TARGET_FILE_DIR:MinecraftClient>"
|
COMMAND ${CMAKE_COMMAND}
|
||||||
)
|
"-DOUTPUT_FILE=${BUILDVER_OUTPUT}"
|
||||||
|
-P "${BUILDVER_SCRIPT}"
|
||||||
target_link_libraries(MinecraftClient PRIVATE
|
COMMENT "Generating BuildVer.h..."
|
||||||
MinecraftWorld
|
|
||||||
d3d11
|
|
||||||
XInput9_1_0
|
|
||||||
wsock32
|
|
||||||
legacy_stdio_definitions
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/lib/iggy_w64.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/lib/iggyperfmon_w64.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/lib/iggyexpruntime_w64.lib"
|
|
||||||
$<$<CONFIG:Debug>:
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib"
|
|
||||||
>
|
|
||||||
$<$<NOT:$<CONFIG:Debug>>:
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC.lib"
|
|
||||||
>
|
|
||||||
)
|
|
||||||
|
|
||||||
set(MINECRAFT_SERVER_SOURCES ${MINECRAFT_CLIENT_SOURCES})
|
|
||||||
list(APPEND MINECRAFT_SERVER_SOURCES
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Windows64/ServerMain.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Access/Access.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Access/BanManager.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Access/WhitelistManager.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/ServerCli.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/ServerCliInput.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/ServerCliParser.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/ServerCliEngine.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/ServerCliRegistry.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/ban/CliCommandBan.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/ban-ip/CliCommandBanIp.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/ban-list/CliCommandBanList.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/help/CliCommandHelp.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/pardon/CliCommandPardon.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/pardon-ip/CliCommandPardonIp.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/stop/CliCommandStop.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/list/CliCommandList.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/tp/CliCommandTp.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/whitelist/CliCommandWhitelist.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/gamemode/CliCommandGamemode.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/time/CliCommandTime.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/weather/CliCommandWeather.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/give/CliCommandGive.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/enchant/CliCommandEnchant.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/kill/CliCommandKill.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/defaultgamemode/CliCommandDefaultGamemode.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Console/commands/experience/CliCommandExperience.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/FileUtils.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Common/StringUtils.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/ServerLogger.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/ServerLogManager.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/ServerProperties.cpp"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/vendor/linenoise/linenoise.c"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/WorldManager.cpp"
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(MinecraftServer ${MINECRAFT_SERVER_SOURCES})
|
|
||||||
target_include_directories(MinecraftServer PRIVATE
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/include"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/Sentient/Include"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Server/Windows64"
|
|
||||||
)
|
|
||||||
target_compile_definitions(MinecraftServer PRIVATE
|
|
||||||
$<$<CONFIG:Debug>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;MINECRAFT_SERVER_BUILD>
|
|
||||||
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64;MINECRAFT_SERVER_BUILD>
|
|
||||||
)
|
|
||||||
if(MSVC)
|
|
||||||
configure_msvc_target(MinecraftServer)
|
|
||||||
target_link_options(MinecraftServer PRIVATE
|
|
||||||
$<$<CONFIG:Release>:/LTCG /INCREMENTAL:NO>
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(MinecraftServer PROPERTIES
|
|
||||||
OUTPUT_NAME "Minecraft.Server"
|
|
||||||
VS_DEBUGGER_WORKING_DIRECTORY "$<TARGET_FILE_DIR:MinecraftServer>"
|
|
||||||
VS_DEBUGGER_COMMAND_ARGUMENTS "-port 25565 -bind 0.0.0.0 -name DedicatedServer"
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(MinecraftServer PRIVATE
|
|
||||||
MinecraftWorld
|
|
||||||
d3d11
|
|
||||||
XInput9_1_0
|
|
||||||
wsock32
|
|
||||||
legacy_stdio_definitions
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/lib/iggy_w64.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/lib/iggyperfmon_w64.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/lib/iggyexpruntime_w64.lib"
|
|
||||||
$<$<CONFIG:Debug>:
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib"
|
|
||||||
>
|
|
||||||
$<$<NOT:$<CONFIG:Debug>>:
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC.lib"
|
|
||||||
>
|
|
||||||
)
|
|
||||||
|
|
||||||
if(CMAKE_HOST_WIN32)
|
|
||||||
message(STATUS "Starting redist copy...")
|
|
||||||
execute_process(
|
|
||||||
COMMAND robocopy.exe
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/x64/Release"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
/S /MT /R:0 /W:0 /NP
|
|
||||||
)
|
|
||||||
message(STATUS "Starting asset copy...")
|
|
||||||
execute_process(
|
|
||||||
COMMAND robocopy.exe
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
/S /MT /R:0 /W:0 /NP
|
|
||||||
/XF "*.cpp" "*.c" "*.h" "*.hpp" "*.asm"
|
|
||||||
"*.xml" "*.lang" "*.vcxproj" "*.vcxproj.*" "*.sln"
|
|
||||||
"*.docx" "*.xls"
|
|
||||||
"*.bat" "*.cmd" "*.ps1" "*.py"
|
|
||||||
"*Test*"
|
|
||||||
/XD "Durango*" "Orbis*" "PS*" "Xbox"
|
|
||||||
)
|
|
||||||
message(STATUS "Patching Windows64Media...")
|
|
||||||
execute_process(
|
|
||||||
COMMAND robocopy.exe
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/DurangoMedia"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/Windows64Media"
|
|
||||||
/S /MT /R:0 /W:0 /NP
|
|
||||||
/XF "*.h" "*.xml" "*.lang" "*.bat"
|
|
||||||
)
|
|
||||||
elseif(CMAKE_HOST_UNIX)
|
|
||||||
message(STATUS "Starting redist copy...")
|
|
||||||
execute_process(
|
|
||||||
COMMAND rsync -av "${CMAKE_CURRENT_SOURCE_DIR}/x64/Release/" "${CMAKE_CURRENT_BINARY_DIR}/"
|
|
||||||
)
|
|
||||||
message(STATUS "Starting asset copy...")
|
|
||||||
execute_process(
|
|
||||||
COMMAND rsync -av
|
|
||||||
"--exclude=*.cpp" "--exclude=*.c" "--exclude=*.h" "--exclude=*.hpp" "--exclude=*.asm"
|
|
||||||
"--exclude=*.xml" "--exclude=*.lang" "--exclude=*.vcxproj" "--exclude=*.vcxproj.*" "--exclude=*.sln"
|
|
||||||
"--exclude=*.docx" "--exclude=*.xls"
|
|
||||||
"--exclude=*.bat" "--exclude=*.cmd" "--exclude=*.ps1" "--exclude=*.py"
|
|
||||||
"--exclude=*Test*"
|
|
||||||
"--exclude=Durango*" "--exclude=Orbis*" "--exclude=PS*" "--exclude=Xbox"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/" "${CMAKE_CURRENT_BINARY_DIR}/"
|
|
||||||
)
|
|
||||||
message(STATUS "Patching Windows64Media...")
|
|
||||||
execute_process(
|
|
||||||
COMMAND rsync -av
|
|
||||||
"--exclude=*.h" "--exclude=*.xml" "--exclude=*.lang" "--exclude=*.bat"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/DurangoMedia/" "${CMAKE_CURRENT_BINARY_DIR}/Windows64Media/"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Redist and asset copying is only supported on Windows (Robocopy) and Unix systems (rsync).")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_custom_command(TARGET MinecraftServer POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}"
|
|
||||||
-DPROJECT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
|
|
||||||
-DOUTPUT_DIR="$<TARGET_FILE_DIR:MinecraftServer>"
|
|
||||||
-DCONFIGURATION=$<CONFIG>
|
|
||||||
-P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/CopyServerAssets.cmake"
|
|
||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MinecraftServer)
|
add_dependencies(Minecraft.World GenerateBuildVer)
|
||||||
|
add_dependencies(Minecraft.Client GenerateBuildVer)
|
||||||
|
if(PLATFORM_NAME STREQUAL "Windows64")
|
||||||
|
add_dependencies(Minecraft.Server GenerateBuildVer)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# Project organisation
|
||||||
|
# ---
|
||||||
|
# Set the startup project for Visual Studio
|
||||||
|
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT Minecraft.Client)
|
||||||
|
|
||||||
|
# Setup folders for Visual Studio, just hides the build targets under a sub folder
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
set_property(TARGET GenerateBuildVer PROPERTY FOLDER "Build")
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
{
|
||||||
|
"version": 5,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "base",
|
||||||
|
"generator": "Ninja Multi-Config",
|
||||||
|
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||||
|
"hidden": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows64",
|
||||||
|
"displayName": "Windows64",
|
||||||
|
"inherits": "base",
|
||||||
|
"cacheVariables": {
|
||||||
|
"PLATFORM_DEFINES": "_WINDOWS64",
|
||||||
|
"PLATFORM_NAME": "Windows64",
|
||||||
|
"IGGY_LIBS": "iggy_w64.lib;iggyperfmon_w64.lib;iggyexpruntime_w64.lib"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "durango",
|
||||||
|
"displayName": "Durango",
|
||||||
|
"inherits": "base",
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/durango.cmake",
|
||||||
|
"cacheVariables": {
|
||||||
|
"PLATFORM_DEFINES": "_DURANGO;_XBOX_ONE",
|
||||||
|
"PLATFORM_NAME": "Durango",
|
||||||
|
"IGGY_LIBS": "iggy_durango.lib;iggyperfmon_durango.lib"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "orbis",
|
||||||
|
"displayName": "ORBIS",
|
||||||
|
"inherits": "base",
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/orbis.cmake",
|
||||||
|
"cacheVariables": {
|
||||||
|
"PLATFORM_DEFINES": "__ORBIS__",
|
||||||
|
"PLATFORM_NAME": "Orbis",
|
||||||
|
"IGGY_LIBS": "libiggy_orbis.a;libiggyperfmon_orbis.a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ps3",
|
||||||
|
"displayName": "PS3",
|
||||||
|
"inherits": "base",
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/ps3.cmake",
|
||||||
|
"cacheVariables": {
|
||||||
|
"PLATFORM_DEFINES": "__PS3__",
|
||||||
|
"PLATFORM_NAME": "PS3",
|
||||||
|
"IGGY_LIBS": "libiggy_ps3.a;libiggyperfmon_ps3.a;libiggyexpruntime_ps3.a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "psvita",
|
||||||
|
"displayName": "PSVita",
|
||||||
|
"inherits": "base",
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/psvita.cmake",
|
||||||
|
"cacheVariables": {
|
||||||
|
"PLATFORM_DEFINES": "__PSVITA__",
|
||||||
|
"PLATFORM_NAME": "PSVita",
|
||||||
|
"IGGY_LIBS": "libiggy_psp2.a;libiggyperfmon_psp2.a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "xbox360",
|
||||||
|
"displayName": "Xbox 360",
|
||||||
|
"inherits": "base",
|
||||||
|
"toolchainFile": "${sourceDir}/cmake/toolchains/xbox360.cmake",
|
||||||
|
"cacheVariables": {
|
||||||
|
"PLATFORM_DEFINES": "_XBOX",
|
||||||
|
"PLATFORM_NAME": "Xbox"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buildPresets": [
|
||||||
|
{ "name": "windows64-debug", "displayName": "Windows64 - Debug", "configurePreset": "windows64", "configuration": "Debug" },
|
||||||
|
{ "name": "windows64-release", "displayName": "Windows64 - Release", "configurePreset": "windows64", "configuration": "Release" },
|
||||||
|
|
||||||
|
{ "name": "durango-debug", "displayName": "Durango - Debug", "configurePreset": "durango", "configuration": "Debug" },
|
||||||
|
{ "name": "durango-release", "displayName": "Durango - Release", "configurePreset": "durango", "configuration": "Release" },
|
||||||
|
|
||||||
|
{ "name": "orbis-debug", "displayName": "ORBIS - Debug", "configurePreset": "orbis", "configuration": "Debug" },
|
||||||
|
{ "name": "orbis-release", "displayName": "ORBIS - Release", "configurePreset": "orbis", "configuration": "Release" },
|
||||||
|
|
||||||
|
{ "name": "ps3-debug", "displayName": "PS3 - Debug", "configurePreset": "ps3", "configuration": "Debug" },
|
||||||
|
{ "name": "ps3-release", "displayName": "PS3 - Release", "configurePreset": "ps3", "configuration": "Release" },
|
||||||
|
|
||||||
|
{ "name": "psvita-debug", "displayName": "PSVita - Debug", "configurePreset": "psvita", "configuration": "Debug" },
|
||||||
|
{ "name": "psvita-release", "displayName": "PSVita - Release", "configurePreset": "psvita", "configuration": "Release" },
|
||||||
|
|
||||||
|
{ "name": "xbox360-debug", "displayName": "Xbox 360 - Debug", "configurePreset": "xbox360", "configuration": "Debug" },
|
||||||
|
{ "name": "xbox360-release", "displayName": "Xbox 360 - Release", "configurePreset": "xbox360", "configuration": "Release" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,16 +1,14 @@
|
|||||||
# Compile Instructions
|
# Compile Instructions
|
||||||
|
|
||||||
## Visual Studio (`.sln`)
|
## Visual Studio
|
||||||
|
|
||||||
1. Open `MinecraftConsoles.sln` in Visual Studio 2022.
|
1. Clone or download the repository
|
||||||
2. Set Startup Project:
|
1. Open the repo folder in Visual Studio 2022+.
|
||||||
- Client: `Minecraft.Client`
|
2. Wait for cmake to configure the project and load all assets (this may take a few minutes on the first run).
|
||||||
- Dedicated server: `Minecraft.Server`
|
3. Right click a folder in the solution explorer and switch to the 'CMake Targets View'
|
||||||
3. Select configuration:
|
4. Select platform and configuration from the dropdown. EG: `Windows64 - Debug` or `Windows64 - Release`
|
||||||
- `Debug` (recommended), or
|
5. Pick the startup project `Minecraft.Client.exe` or `Minecraft.Server.exe` using the debug targets dropdown
|
||||||
- `Release`
|
6. Build and run the project:
|
||||||
4. Select platform: `Windows64`.
|
|
||||||
5. Build and run:
|
|
||||||
- `Build > Build Solution` (or `Ctrl+Shift+B`)
|
- `Build > Build Solution` (or `Ctrl+Shift+B`)
|
||||||
- Start debugging with `F5`.
|
- Start debugging with `F5`.
|
||||||
|
|
||||||
@@ -29,50 +27,52 @@
|
|||||||
|
|
||||||
Configure (use your VS Community instance explicitly):
|
Configure (use your VS Community instance explicitly):
|
||||||
|
|
||||||
|
Open `Developer PowerShell for VS` and run:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_GENERATOR_INSTANCE="C:/Program Files/Microsoft Visual Studio/2022/Community"
|
cmake --preset windows64
|
||||||
```
|
```
|
||||||
|
|
||||||
Build Debug:
|
Build Debug:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cmake --build build --config Debug --target MinecraftClient
|
cmake --build --preset windows64-debug --target Minecraft.Client
|
||||||
```
|
```
|
||||||
|
|
||||||
Build Release:
|
Build Release:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cmake --build build --config Release --target MinecraftClient
|
cmake --build --preset windows64-release --target Minecraft.Client
|
||||||
```
|
```
|
||||||
|
|
||||||
Build Dedicated Server (Debug):
|
Build Dedicated Server (Debug):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cmake --build build --config Debug --target MinecraftServer
|
cmake --build --preset windows64-debug --target Minecraft.Server
|
||||||
```
|
```
|
||||||
|
|
||||||
Build Dedicated Server (Release):
|
Build Dedicated Server (Release):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cmake --build build --config Release --target MinecraftServer
|
cmake --build --preset windows64-release --target Minecraft.Server
|
||||||
```
|
```
|
||||||
|
|
||||||
Run executable:
|
Run executable:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd .\build\Debug
|
cd .\build\windows64\Minecraft.Client\Debug
|
||||||
.\MinecraftClient.exe
|
.\Minecraft.Client.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
Run dedicated server:
|
Run dedicated server:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
cd .\build\Debug
|
cd .\build\windows64\Minecraft.Server\Debug
|
||||||
.\Minecraft.Server.exe -port 25565 -bind 0.0.0.0 -name DedicatedServer
|
.\Minecraft.Server.exe -port 25565 -bind 0.0.0.0 -name DedicatedServer
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
- The CMake build is Windows-only and x64-only.
|
- The CMake build is Windows-only and x64-only.
|
||||||
- Contributors on macOS or Linux need a Windows machine or VM to build the project. Running the game via Wine is separate from having a supported build environment.
|
- Contributors on macOS or Linux need a Windows machine or VM to build the project. Running the game via Wine is separate from having a supported build environment.
|
||||||
- Post-build asset copy is automatic for `MinecraftClient` in CMake (Debug and Release variants).
|
- 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.
|
- The game relies on relative paths (for example `Common\Media\...`), so launching from the output directory is required.
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cmake/sources/Common.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cmake/sources/Durango.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cmake/sources/ORBIS.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cmake/sources/PS3.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cmake/sources/PSVita.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cmake/sources/Windows.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cmake/sources/Xbox360.cmake")
|
||||||
|
|
||||||
|
include("${CMAKE_SOURCE_DIR}/cmake/CommonSources.cmake")
|
||||||
|
|
||||||
|
include("${CMAKE_SOURCE_DIR}/cmake/Utils.cmake")
|
||||||
|
|
||||||
|
# Combine all source files into a single variable for the target
|
||||||
|
# We cant use CMAKE_CONFIGURE_PRESET here as VS doesn't set it, so just rely on the folder
|
||||||
|
set(MINECRAFT_CLIENT_SOURCES
|
||||||
|
${MINECRAFT_CLIENT_COMMON}
|
||||||
|
$<$<STREQUAL:${PLATFORM_NAME},Durango>:${MINECRAFT_CLIENT_DURANGO}>
|
||||||
|
$<$<STREQUAL:${PLATFORM_NAME},Orbis>:${MINECRAFT_CLIENT_ORBIS}>
|
||||||
|
$<$<STREQUAL:${PLATFORM_NAME},PS3>:${MINECRAFT_CLIENT_PS3}>
|
||||||
|
$<$<STREQUAL:${PLATFORM_NAME},PSVita>:${MINECRAFT_CLIENT_PSVITA}>
|
||||||
|
$<$<STREQUAL:${PLATFORM_NAME},Windows64>:${MINECRAFT_CLIENT_WINDOWS}>
|
||||||
|
$<$<STREQUAL:${PLATFORM_NAME},Xbox>:${MINECRAFT_CLIENT_XBOX360}>
|
||||||
|
${SOURCES_COMMON}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(Minecraft.Client ${MINECRAFT_CLIENT_SOURCES})
|
||||||
|
|
||||||
|
# Only define executable on windows
|
||||||
|
if(PLATFORM_NAME STREQUAL "Windows64")
|
||||||
|
set_target_properties(Minecraft.Client PROPERTIES WIN32_EXECUTABLE TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(Minecraft.Client PRIVATE
|
||||||
|
"${CMAKE_BINARY_DIR}/generated/" # This is for the generated BuildVer.h
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/Iggy/include"
|
||||||
|
"${CMAKE_SOURCE_DIR}/include/"
|
||||||
|
)
|
||||||
|
target_compile_definitions(Minecraft.Client PRIVATE
|
||||||
|
${MINECRAFT_SHARED_DEFINES}
|
||||||
|
)
|
||||||
|
target_precompile_headers(Minecraft.Client PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:stdafx.h>")
|
||||||
|
set_source_files_properties(compat_shims.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS ON) # This redefines internal MSVC CRT symbols which will cause an issue with PCH
|
||||||
|
|
||||||
|
configure_compiler_target(Minecraft.Client)
|
||||||
|
|
||||||
|
set_target_properties(Minecraft.Client PROPERTIES
|
||||||
|
OUTPUT_NAME "Minecraft.Client"
|
||||||
|
VS_DEBUGGER_WORKING_DIRECTORY "$<TARGET_FILE_DIR:Minecraft.Client>"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Minecraft.Client PRIVATE
|
||||||
|
Minecraft.World
|
||||||
|
d3d11
|
||||||
|
d3dcompiler
|
||||||
|
XInput9_1_0
|
||||||
|
wsock32
|
||||||
|
legacy_stdio_definitions
|
||||||
|
$<$<CONFIG:Debug>: # Debug 4J libraries
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Input_d.lib"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Storage_d.lib"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Render_PC_d.lib"
|
||||||
|
>
|
||||||
|
$<$<NOT:$<CONFIG:Debug>>: # Release 4J libraries
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Input.lib"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Storage.lib"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/4JLibs/libs/4J_Render_PC.lib"
|
||||||
|
>
|
||||||
|
)
|
||||||
|
|
||||||
|
# Iggy libs
|
||||||
|
foreach(lib IN LISTS IGGY_LIBS)
|
||||||
|
target_link_libraries(Minecraft.Client PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}/Iggy/lib/${lib}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# Asset / redist copy
|
||||||
|
# ---
|
||||||
|
include("${CMAKE_SOURCE_DIR}/cmake/CopyAssets.cmake")
|
||||||
|
set(ASSET_FOLDER_PAIRS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/music" "music"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Common/Media" "Common/Media"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Common/res" "Common/res"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Common/Trial" "Common/Trial"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/Common/Tutorial" "Common/Tutorial"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/${PLATFORM_NAME}Media" "${PLATFORM_NAME}Media"
|
||||||
|
)
|
||||||
|
setup_asset_folder_copy(Minecraft.Client "${ASSET_FOLDER_PAIRS}")
|
||||||
|
|
||||||
|
# Copy redist files
|
||||||
|
add_copyredist_target(Minecraft.Client)
|
||||||
|
|
||||||
|
# Make sure GameHDD exists on Windows
|
||||||
|
if(PLATFORM_NAME STREQUAL "Windows64")
|
||||||
|
add_gamehdd_target(Minecraft.Client)
|
||||||
|
endif()
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "..\Minecraft.World\SharedConstants.h"
|
#include "..\Minecraft.World\SharedConstants.h"
|
||||||
#include "..\Minecraft.World\StringHelpers.h"
|
#include "..\Minecraft.World\StringHelpers.h"
|
||||||
#include "..\Minecraft.World\ChatPacket.h"
|
#include "..\Minecraft.World\ChatPacket.h"
|
||||||
|
#include "..\Minecraft.World\ArabicShaping.h"
|
||||||
|
|
||||||
const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters;
|
const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters;
|
||||||
vector<wstring> ChatScreen::s_chatHistory;
|
vector<wstring> ChatScreen::s_chatHistory;
|
||||||
@@ -14,7 +15,12 @@ wstring ChatScreen::s_historyDraft;
|
|||||||
|
|
||||||
bool ChatScreen::isAllowedChatChar(wchar_t c)
|
bool ChatScreen::isAllowedChatChar(wchar_t c)
|
||||||
{
|
{
|
||||||
return c >= 0x20 && (c == L'\u00A7' || allowedChars.empty() || allowedChars.find(c) != wstring::npos);
|
if (c < 0x20) return false;
|
||||||
|
// Block Unicode bidirectional override characters that can be used to
|
||||||
|
// spoof chat messages or impersonate players.
|
||||||
|
if (c >= 0x202A && c <= 0x202E) return false; // LRE, RLE, PDF, LRO, RLO
|
||||||
|
if (c >= 0x2066 && c <= 0x2069) return false; // LRI, RLI, FSI, PDI
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatScreen::ChatScreen()
|
ChatScreen::ChatScreen()
|
||||||
@@ -93,6 +99,9 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
|||||||
if (eventKey == Keyboard::KEY_RETURN)
|
if (eventKey == Keyboard::KEY_RETURN)
|
||||||
{
|
{
|
||||||
wstring trim = trimString(message);
|
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 (trim.length() > 0)
|
||||||
{
|
{
|
||||||
if (!minecraft->handleClientSideCommand(trim))
|
if (!minecraft->handleClientSideCommand(trim))
|
||||||
@@ -135,6 +144,7 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
|||||||
{
|
{
|
||||||
message.insert(cursorIndex, 1, ch);
|
message.insert(cursorIndex, 1, ch);
|
||||||
cursorIndex++;
|
cursorIndex++;
|
||||||
|
{ char buf[64]; sprintf_s(buf, "[CHAT] Char U+%04X accepted (%d chars)\n", (unsigned)ch, (int)message.length()); OutputDebugStringA(buf); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,14 +155,21 @@ void ChatScreen::render(int xm, int ym, float a)
|
|||||||
int x = 4;
|
int x = 4;
|
||||||
drawString(font, prefix, x, height - 12, 0xe0e0e0);
|
drawString(font, prefix, x, height - 12, 0xe0e0e0);
|
||||||
x += font->width(prefix);
|
x += font->width(prefix);
|
||||||
wstring beforeCursor = message.substr(0, cursorIndex);
|
|
||||||
wstring afterCursor = message.substr(cursorIndex);
|
// Shape the full message as one unit so letter connections and word order
|
||||||
drawStringLiteral(font, beforeCursor, x, height - 12, 0xe0e0e0);
|
// are correct. Track where the logical cursor maps in the visual string.
|
||||||
x += font->widthLiteral(beforeCursor);
|
int visualCursorPos = 0;
|
||||||
|
wstring shaped = shapeArabicText(message, cursorIndex, &visualCursorPos);
|
||||||
|
|
||||||
|
// Render the full shaped message without re-shaping it
|
||||||
|
drawStringPreshaped(font, shaped, x, height - 12, 0xe0e0e0);
|
||||||
|
|
||||||
|
// Place the cursor at the correct visual position
|
||||||
|
wstring beforeCursorVisual = shaped.substr(0, visualCursorPos);
|
||||||
|
int cursorX = x + font->widthPreshaped(beforeCursorVisual);
|
||||||
if (frame / 6 % 2 == 0)
|
if (frame / 6 % 2 == 0)
|
||||||
drawString(font, L"_", x, height - 12, 0xe0e0e0);
|
drawString(font, L"_", cursorX, height - 12, 0xe0e0e0);
|
||||||
x += font->width(L"_");
|
|
||||||
drawStringLiteral(font, afterCursor, x, height - 12, 0xe0e0e0);
|
|
||||||
Screen::render(xm, ym, a);
|
Screen::render(xm, ym, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
|||||||
Level *dimensionLevel = minecraft->getLevel( packet->dimension );
|
Level *dimensionLevel = minecraft->getLevel( packet->dimension );
|
||||||
if( dimensionLevel == nullptr )
|
if( dimensionLevel == nullptr )
|
||||||
{
|
{
|
||||||
level = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, false, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
level = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||||
|
|
||||||
// 4J Stu - We want to share the SavedDataStorage between levels
|
// 4J Stu - We want to share the SavedDataStorage between levels
|
||||||
int otherDimensionId = packet->dimension == 0 ? -1 : 0;
|
int otherDimensionId = packet->dimension == 0 ? -1 : 0;
|
||||||
@@ -411,7 +411,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
|||||||
activeLevel = minecraft->getLevel(otherDimensionId);
|
activeLevel = minecraft->getLevel(otherDimensionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiPlayerLevel *dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, false, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
MultiPlayerLevel *dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||||
|
|
||||||
dimensionLevel->savedDataStorage = activeLevel->savedDataStorage;
|
dimensionLevel->savedDataStorage = activeLevel->savedDataStorage;
|
||||||
|
|
||||||
@@ -2870,7 +2870,7 @@ void ClientConnection::handleRespawn(shared_ptr<RespawnPacket> packet)
|
|||||||
MultiPlayerLevel *dimensionLevel = (MultiPlayerLevel *)minecraft->getLevel( packet->dimension );
|
MultiPlayerLevel *dimensionLevel = (MultiPlayerLevel *)minecraft->getLevel( packet->dimension );
|
||||||
if( dimensionLevel == nullptr )
|
if( dimensionLevel == nullptr )
|
||||||
{
|
{
|
||||||
dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->mapSeed, packet->playerGameType, false, minecraft->level->getLevelData()->isHardcore(), packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->mapSeed, packet->playerGameType, false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||||
|
|
||||||
// 4J Stu - We want to shared the savedDataStorage between both levels
|
// 4J Stu - We want to shared the savedDataStorage between both levels
|
||||||
//if( dimensionLevel->savedDataStorage != nullptr )
|
//if( dimensionLevel->savedDataStorage != nullptr )
|
||||||
@@ -3315,7 +3315,9 @@ void ClientConnection::handleTileEditorOpen(shared_ptr<TileEditorOpenPacket> pac
|
|||||||
|
|
||||||
void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("ClientConnection::handleSignUpdate - ");
|
app.DebugPrintf("[SIGN] handleSignUpdate at (%d, %d, %d):\n", packet->x, packet->y, packet->z);
|
||||||
|
for (int i = 0; i < MAX_SIGN_LINES; i++)
|
||||||
|
app.DebugPrintf("[SIGN] Line%d: \"%ls\"\n", i+1, packet->lines[i].c_str());
|
||||||
if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z))
|
if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z))
|
||||||
{
|
{
|
||||||
shared_ptr<TileEntity> te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z);
|
shared_ptr<TileEntity> te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z);
|
||||||
@@ -3329,7 +3331,7 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
|||||||
ste->SetMessage(i,packet->lines[i]);
|
ste->SetMessage(i,packet->lines[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.DebugPrintf("verified = %d\tCensored = %d\n",packet->m_bVerified,packet->m_bCensored);
|
app.DebugPrintf("[SIGN] verified=%d censored=%d\n", packet->m_bVerified, packet->m_bCensored);
|
||||||
ste->SetVerified(packet->m_bVerified);
|
ste->SetVerified(packet->m_bVerified);
|
||||||
ste->SetCensored(packet->m_bCensored);
|
ste->SetCensored(packet->m_bCensored);
|
||||||
|
|
||||||
@@ -3337,12 +3339,12 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
app.DebugPrintf("dynamic_pointer_cast<SignTileEntity>(te) == nullptr\n");
|
app.DebugPrintf("[SIGN] ERROR: tile entity is not a SignTileEntity\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
app.DebugPrintf("hasChunkAt failed\n");
|
app.DebugPrintf("[SIGN] ERROR: chunk not loaded at position\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "ClientConstants.h"
|
#include "ClientConstants.h"
|
||||||
|
#include "Common/BuildVer.h"
|
||||||
|
|
||||||
const wstring ClientConstants::VERSION_STRING = wstring(L"Minecraft LCE ") + VER_FILEVERSION_STR_W;//+ SharedConstants::VERSION_STRING;
|
const wstring ClientConstants::VERSION_STRING = wstring(L"Minecraft LCE ") + VER_FILEVERSION_STR_W;//+ SharedConstants::VERSION_STRING;
|
||||||
const wstring ClientConstants::BRANCH_STRING = VER_BRANCHVERSION_STR_W;
|
const wstring ClientConstants::BRANCH_STRING = VER_BRANCHVERSION_STR_W;
|
||||||
|
|
||||||
|
// Default value for the toggle. If BuildVer defines VER_SHOW_VERSION_WATERMARK, use that.
|
||||||
|
#ifdef VER_SHOW_VERSION_WATERMARK
|
||||||
|
const bool ClientConstants::SHOW_VERSION_WATERMARK = (VER_SHOW_VERSION_WATERMARK != 0);
|
||||||
|
#else
|
||||||
|
const bool ClientConstants::SHOW_VERSION_WATERMARK = false;
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -15,5 +15,8 @@ public:
|
|||||||
static const wstring VERSION_STRING;
|
static const wstring VERSION_STRING;
|
||||||
static const wstring BRANCH_STRING;
|
static const wstring BRANCH_STRING;
|
||||||
|
|
||||||
|
// Toggle to show/hide the version/branch watermark in the debug overlay
|
||||||
|
static const bool SHOW_VERSION_WATERMARK;
|
||||||
|
|
||||||
static const bool DEADMAU5_CAMERA_CHEATS = false;
|
static const bool DEADMAU5_CAMERA_CHEATS = false;
|
||||||
};
|
};
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
#define GAME_HOST_OPTION_BITMASK_DOTILEDROPS 0x08000000
|
#define GAME_HOST_OPTION_BITMASK_DOTILEDROPS 0x08000000
|
||||||
#define GAME_HOST_OPTION_BITMASK_NATURALREGEN 0x10000000
|
#define GAME_HOST_OPTION_BITMASK_NATURALREGEN 0x10000000
|
||||||
#define GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE 0x20000000
|
#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_ALL 0xFFFFFFFF
|
||||||
|
|
||||||
#define GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT 20
|
#define GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT 20
|
||||||
|
|||||||
@@ -648,6 +648,7 @@ enum eGameHostOption
|
|||||||
eGameHostOption_DoTileDrops,
|
eGameHostOption_DoTileDrops,
|
||||||
eGameHostOption_NaturalRegeneration,
|
eGameHostOption_NaturalRegeneration,
|
||||||
eGameHostOption_DoDaylightCycle,
|
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
|
// 4J-PB - If any new DLC items are added to the TMSFiles, this array needs updated
|
||||||
@@ -878,7 +879,8 @@ enum EControllerActions
|
|||||||
MINECRAFT_ACTION_SPAWN_CREEPER,
|
MINECRAFT_ACTION_SPAWN_CREEPER,
|
||||||
MINECRAFT_ACTION_CHANGE_SKIN,
|
MINECRAFT_ACTION_CHANGE_SKIN,
|
||||||
MINECRAFT_ACTION_FLY_TOGGLE,
|
MINECRAFT_ACTION_FLY_TOGGLE,
|
||||||
MINECRAFT_ACTION_RENDER_DEBUG
|
MINECRAFT_ACTION_RENDER_DEBUG,
|
||||||
|
MINECRAFT_ACTION_SCREENSHOT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eMCLang
|
enum eMCLang
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define VER_PRODUCTBUILD 560
|
|
||||||
#define VER_PRODUCTVERSION_STR_W L"DEV (unknown version)"
|
|
||||||
#define VER_FILEVERSION_STR_W VER_PRODUCTVERSION_STR_W
|
|
||||||
#define VER_BRANCHVERSION_STR_W L"UNKNOWN BRANCH"
|
|
||||||
#define VER_NETWORK VER_PRODUCTBUILD
|
|
||||||
|
|||||||
@@ -8084,6 +8084,16 @@ void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOpt
|
|||||||
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
|
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
|
||||||
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
|
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
|
||||||
break;
|
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:
|
case eGameHostOption_All:
|
||||||
uiHostSettings=uiVal;
|
uiHostSettings=uiVal;
|
||||||
break;
|
break;
|
||||||
@@ -8185,6 +8195,9 @@ unsigned int CMinecraftApp::GetGameHostOption(unsigned int uiHostSettings, eGame
|
|||||||
case eGameHostOption_DoDaylightCycle:
|
case eGameHostOption_DoDaylightCycle:
|
||||||
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE);
|
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE);
|
||||||
break;
|
break;
|
||||||
|
case eGameHostOption_Hardcore: // 4J Added - for hardcore mode
|
||||||
|
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HARDCORE) ? 1 : 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -805,6 +805,10 @@ public:
|
|||||||
void SetCorruptSaveDeleted(bool bVal) {m_bCorruptSaveDeleted=bVal;}
|
void SetCorruptSaveDeleted(bool bVal) {m_bCorruptSaveDeleted=bVal;}
|
||||||
bool GetCorruptSaveDeleted(void) {return m_bCorruptSaveDeleted;}
|
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 EnterSaveNotificationSection();
|
||||||
void LeaveSaveNotificationSection();
|
void LeaveSaveNotificationSection();
|
||||||
private:
|
private:
|
||||||
@@ -826,6 +830,7 @@ private:
|
|||||||
CRITICAL_SECTION csAdditionalSkinBoxes;
|
CRITICAL_SECTION csAdditionalSkinBoxes;
|
||||||
CRITICAL_SECTION csAnimOverrideBitmask;
|
CRITICAL_SECTION csAnimOverrideBitmask;
|
||||||
bool m_bCorruptSaveDeleted;
|
bool m_bCorruptSaveDeleted;
|
||||||
|
wstring m_currentSaveFolderName; // 4J Added: for hardcore world deletion on Win64
|
||||||
|
|
||||||
DWORD m_dwAdditionalModelParts[XUSER_MAX_COUNT];
|
DWORD m_dwAdditionalModelParts[XUSER_MAX_COUNT];
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 128 B |
|
After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 149 B |
|
After Width: | Height: | Size: 135 B |
|
After Width: | Height: | Size: 153 B |
|
After Width: | Height: | Size: 163 B |
|
After Width: | Height: | Size: 122 B |
|
After Width: | Height: | Size: 117 B |
|
After Width: | Height: | Size: 125 B |
|
After Width: | Height: | Size: 135 B |
@@ -38220,6 +38220,56 @@
|
|||||||
<Time>19</Time>
|
<Time>19</Time>
|
||||||
<Command>stop</Command>
|
<Command>stop</Command>
|
||||||
</NamedFrame>
|
</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>
|
</NamedFrames>
|
||||||
<Timeline>
|
<Timeline>
|
||||||
<Id>Border</Id>
|
<Id>Border</Id>
|
||||||
@@ -38274,6 +38324,16 @@
|
|||||||
<Interpolation>0</Interpolation>
|
<Interpolation>0</Interpolation>
|
||||||
<Prop>Graphics\HUD\Health_Background_Flash.png</Prop>
|
<Prop>Graphics\HUD\Health_Background_Flash.png</Prop>
|
||||||
</KeyFrame>
|
</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>
|
||||||
<Timeline>
|
<Timeline>
|
||||||
<Id>Heart</Id>
|
<Id>Heart</Id>
|
||||||
@@ -38399,6 +38459,66 @@
|
|||||||
<Prop>true</Prop>
|
<Prop>true</Prop>
|
||||||
<Prop>Graphics\HUD\HorseHealth_Half_Flash.png</Prop>
|
<Prop>Graphics\HUD\HorseHealth_Half_Flash.png</Prop>
|
||||||
</KeyFrame>
|
</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>
|
</Timeline>
|
||||||
</Timelines>
|
</Timelines>
|
||||||
</XuiVisual>
|
</XuiVisual>
|
||||||
|
|||||||
@@ -410,11 +410,72 @@ int IUIScene_PauseMenu::ExitWorldThreadProc( void* lpParameter )
|
|||||||
return S_OK;
|
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.
|
// 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)
|
void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
|
||||||
{
|
{
|
||||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
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 exitReasonStringId = pMinecraft->progressRenderer->getCurrentTitle();
|
||||||
int exitReasonTitleId = IDS_CONNECTION_LOST;
|
int exitReasonTitleId = IDS_CONNECTION_LOST;
|
||||||
|
|
||||||
@@ -625,6 +686,17 @@ void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
|
|||||||
{
|
{
|
||||||
Sleep(1);
|
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);
|
pMinecraft->setLevel(nullptr,exitReasonStringId,nullptr,saveStats);
|
||||||
|
|
||||||
TelemetryManager->Flush();
|
TelemetryManager->Flush();
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ S32 UIBitmapFont::GetCodepointGlyph(U32 codepoint)
|
|||||||
// 4J-JEV: Change "right single quotation marks" to apostrophies.
|
// 4J-JEV: Change "right single quotation marks" to apostrophies.
|
||||||
if (codepoint == 0x2019) codepoint = 0x27;
|
if (codepoint == 0x2019) codepoint = 0x27;
|
||||||
|
|
||||||
|
if (!m_cFontData->hasGlyph(codepoint))
|
||||||
|
return IGGY_GLYPH_INVALID;
|
||||||
|
|
||||||
return m_cFontData->getGlyphId(codepoint);
|
return m_cFontData->getGlyphId(codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,19 +256,6 @@ rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacte
|
|||||||
while ( (0.5f + glyphScale) * truePixelScale < pixel_scale)
|
while ( (0.5f + glyphScale) * truePixelScale < pixel_scale)
|
||||||
glyphScale++;
|
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.
|
// 4J-JEV: Debug code to check which font sizes are being used.
|
||||||
#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0)
|
#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "UIControl.h"
|
#include "UIControl.h"
|
||||||
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
||||||
#include "..\..\..\Minecraft.World\JavaMath.h"
|
#include "..\..\..\Minecraft.World\JavaMath.h"
|
||||||
|
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||||
|
|
||||||
UIControl_Base::UIControl_Base()
|
UIControl_Base::UIControl_Base()
|
||||||
{
|
{
|
||||||
@@ -32,13 +33,16 @@ void UIControl_Base::tick()
|
|||||||
//app.DebugPrintf("Calling SetLabel - '%ls'\n", m_label.c_str());
|
//app.DebugPrintf("Calling SetLabel - '%ls'\n", m_label.c_str());
|
||||||
m_bLabelChanged = false;
|
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 result;
|
||||||
IggyDataValue value[1];
|
IggyDataValue value[1];
|
||||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||||
IggyStringUTF16 stringVal;
|
IggyStringUTF16 stringVal;
|
||||||
|
|
||||||
stringVal.string = (IggyUTF16*) m_label.c_str();
|
stringVal.string = (IggyUTF16*) shaped.c_str();
|
||||||
stringVal.length = m_label.length();
|
stringVal.length = (int)shaped.length();
|
||||||
value[0].string16 = stringVal;
|
value[0].string16 = stringVal;
|
||||||
|
|
||||||
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
|
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
|
||||||
@@ -56,13 +60,16 @@ void UIControl_Base::setLabel(UIString label, bool instant, bool force)
|
|||||||
{
|
{
|
||||||
m_bLabelChanged = false;
|
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 result;
|
||||||
IggyDataValue value[1];
|
IggyDataValue value[1];
|
||||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||||
IggyStringUTF16 stringVal;
|
IggyStringUTF16 stringVal;
|
||||||
|
|
||||||
stringVal.string = (IggyUTF16*)m_label.c_str();
|
stringVal.string = (IggyUTF16*) shaped.c_str();
|
||||||
stringVal.length = m_label.length();
|
stringVal.length = (int)shaped.length();
|
||||||
value[0].string16 = stringVal;
|
value[0].string16 = stringVal;
|
||||||
|
|
||||||
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
|
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "UI.h"
|
#include "UI.h"
|
||||||
#include "UIControl_Label.h"
|
#include "UIControl_Label.h"
|
||||||
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
||||||
|
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||||
|
|
||||||
UIControl_Label::UIControl_Label()
|
UIControl_Label::UIControl_Label()
|
||||||
{
|
{
|
||||||
@@ -22,13 +23,15 @@ void UIControl_Label::init(UIString label)
|
|||||||
{
|
{
|
||||||
m_label = label;
|
m_label = label;
|
||||||
|
|
||||||
|
wstring shaped = shapeArabicText(m_label.getString());
|
||||||
|
|
||||||
IggyDataValue result;
|
IggyDataValue result;
|
||||||
IggyDataValue value[1];
|
IggyDataValue value[1];
|
||||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||||
IggyStringUTF16 stringVal;
|
IggyStringUTF16 stringVal;
|
||||||
|
|
||||||
stringVal.string = (IggyUTF16*)label.c_str();
|
stringVal.string = (IggyUTF16*)shaped.c_str();
|
||||||
stringVal.length = label.length();
|
stringVal.length = (int)shaped.length();
|
||||||
value[0].string16 = stringVal;
|
value[0].string16 = stringVal;
|
||||||
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value );
|
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "UI.h"
|
#include "UI.h"
|
||||||
#include "UIControl_SaveList.h"
|
#include "UIControl_SaveList.h"
|
||||||
|
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||||
|
|
||||||
bool UIControl_SaveList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName)
|
bool UIControl_SaveList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName)
|
||||||
{
|
{
|
||||||
@@ -69,12 +70,14 @@ void UIControl_SaveList::addItem(const string &label, const wstring &iconName, i
|
|||||||
|
|
||||||
void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName, int data)
|
void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName, int data)
|
||||||
{
|
{
|
||||||
|
wstring shaped = shapeArabicText(label);
|
||||||
|
|
||||||
IggyDataValue result;
|
IggyDataValue result;
|
||||||
IggyDataValue value[3];
|
IggyDataValue value[3];
|
||||||
|
|
||||||
IggyStringUTF16 stringVal;
|
IggyStringUTF16 stringVal;
|
||||||
stringVal.string = (IggyUTF16*)label.c_str();
|
stringVal.string = (IggyUTF16*)shaped.c_str();
|
||||||
stringVal.length = static_cast<S32>(label.length());
|
stringVal.length = static_cast<S32>(shaped.length());
|
||||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||||
value[0].string16 = stringVal;
|
value[0].string16 = stringVal;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "UI.h"
|
#include "UI.h"
|
||||||
#include "UIControl_TextInput.h"
|
#include "UIControl_TextInput.h"
|
||||||
|
#include "..\..\Screen.h"
|
||||||
|
|
||||||
UIControl_TextInput::UIControl_TextInput()
|
UIControl_TextInput::UIControl_TextInput()
|
||||||
{
|
{
|
||||||
@@ -211,6 +212,21 @@ UIControl_TextInput::EDirectEditResult UIControl_TextInput::tickDirectEdit()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paste from clipboard
|
||||||
|
if (g_KBMInput.IsKeyPressed('V') && g_KBMInput.IsKeyDown(VK_CONTROL))
|
||||||
|
{
|
||||||
|
wstring pasted = Screen::getClipboard();
|
||||||
|
for (size_t i = 0; i < pasted.length(); i++)
|
||||||
|
{
|
||||||
|
wchar_t pc = pasted[i];
|
||||||
|
if (pc < 0x20) continue; // skip control characters
|
||||||
|
if (m_iCharLimit > 0 && (int)m_editBuffer.length() >= m_iCharLimit) break;
|
||||||
|
m_editBuffer.insert(m_iCursorPos, 1, pc);
|
||||||
|
m_iCursorPos++;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Arrow keys, Home, End, Delete for cursor movement
|
// Arrow keys, Home, End, Delete for cursor movement
|
||||||
if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0)
|
if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "..\..\EnderDragonRenderer.h"
|
#include "..\..\EnderDragonRenderer.h"
|
||||||
#include "..\..\MultiPlayerLocalPlayer.h"
|
#include "..\..\MultiPlayerLocalPlayer.h"
|
||||||
#include "UIFontData.h"
|
#include "UIFontData.h"
|
||||||
|
#include "UIUnicodeBitmapFont.h"
|
||||||
#include "UISplitScreenHelpers.h"
|
#include "UISplitScreenHelpers.h"
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
#include "..\..\Windows64\KeyboardMouseInput.h"
|
#include "..\..\Windows64\KeyboardMouseInput.h"
|
||||||
@@ -193,6 +194,7 @@ UIController::UIController()
|
|||||||
m_mcTTFFont = nullptr;
|
m_mcTTFFont = nullptr;
|
||||||
m_moj7 = nullptr;
|
m_moj7 = nullptr;
|
||||||
m_moj11 = nullptr;
|
m_moj11 = nullptr;
|
||||||
|
m_unicodeBitmapFont = nullptr;
|
||||||
|
|
||||||
// 4J-JEV: It's important that these remain the same, unless updateCurrentLanguage is going to be called.
|
// 4J-JEV: It's important that these remain the same, unless updateCurrentLanguage is going to be called.
|
||||||
m_eCurrentFont = m_eTargetFont = eFont_NotLoaded;
|
m_eCurrentFont = m_eTargetFont = eFont_NotLoaded;
|
||||||
@@ -307,6 +309,14 @@ void UIController::postInit()
|
|||||||
IggySetAS3ExternalFunctionCallbackUTF16 ( &UIController::ExternalFunctionCallback, this );
|
IggySetAS3ExternalFunctionCallbackUTF16 ( &UIController::ExternalFunctionCallback, this );
|
||||||
IggySetTextureSubstitutionCallbacks ( &UIController::TextureSubstitutionCreateCallback , &UIController::TextureSubstitutionDestroyCallback, 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();
|
SetupFont();
|
||||||
//
|
//
|
||||||
loadSkins();
|
loadSkins();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using namespace std;
|
|||||||
|
|
||||||
class UIAbstractBitmapFont;
|
class UIAbstractBitmapFont;
|
||||||
class UIBitmapFont;
|
class UIBitmapFont;
|
||||||
|
class UIUnicodeBitmapFont;
|
||||||
class UITTFFont;
|
class UITTFFont;
|
||||||
class UIComponent_DebugUIConsole;
|
class UIComponent_DebugUIConsole;
|
||||||
class UIComponent_DebugUIMarketingGuide;
|
class UIComponent_DebugUIMarketingGuide;
|
||||||
@@ -63,6 +64,7 @@ private:
|
|||||||
UIAbstractBitmapFont *m_mcBitmapFont;
|
UIAbstractBitmapFont *m_mcBitmapFont;
|
||||||
UITTFFont *m_mcTTFFont;
|
UITTFFont *m_mcTTFFont;
|
||||||
UIBitmapFont *m_moj7, *m_moj11;
|
UIBitmapFont *m_moj7, *m_moj11;
|
||||||
|
UIUnicodeBitmapFont *m_unicodeBitmapFont;
|
||||||
|
|
||||||
std::mt19937 m_randomGenerator;
|
std::mt19937 m_randomGenerator;
|
||||||
std::uniform_real_distribution<float> m_randomDistribution;
|
std::uniform_real_distribution<float> m_randomDistribution;
|
||||||
|
|||||||
@@ -335,6 +335,11 @@ bool CFontData::unicodeIsWhitespace(unsigned int unicode)
|
|||||||
return false;
|
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)
|
void CFontData::moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy)
|
||||||
{
|
{
|
||||||
cursor += (dy * m_sFontData->m_uiGlyphMapX) + dx;
|
cursor += (dy * m_sFontData->m_uiGlyphMapX) + dx;
|
||||||
|
|||||||
@@ -125,6 +125,9 @@ public:
|
|||||||
// Returns true if this unicodepoint is whitespace
|
// Returns true if this unicodepoint is whitespace
|
||||||
bool unicodeIsWhitespace(unsigned int unicodepoint);
|
bool unicodeIsWhitespace(unsigned int unicodepoint);
|
||||||
|
|
||||||
|
// Returns true if this unicodepoint exists in the font's glyph map.
|
||||||
|
bool hasGlyph(unsigned int unicodepoint);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Move a pointer in an image dx pixels right and dy pixels down, wrap around in either dimension leads to unknown behaviour.
|
// Move a pointer in an image dx pixels right and dy pixels down, wrap around in either dimension leads to unknown behaviour.
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#define GAME_CREATE_ONLINE_TIMER_ID 0
|
#define GAME_CREATE_ONLINE_TIMER_ID 0
|
||||||
#define GAME_CREATE_ONLINE_TIMER_TIME 100
|
#define GAME_CREATE_ONLINE_TIMER_TIME 100
|
||||||
|
|
||||||
|
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]=
|
int UIScene_CreateWorldMenu::m_iDifficultyTitleSettingA[4]=
|
||||||
{
|
{
|
||||||
IDS_DIFFICULTY_TITLE_PEACEFUL,
|
IDS_DIFFICULTY_TITLE_PEACEFUL,
|
||||||
@@ -59,8 +61,9 @@ UIScene_CreateWorldMenu::UIScene_CreateWorldMenu(int iPad, void *initData, UILay
|
|||||||
|
|
||||||
WCHAR TempString[256];
|
WCHAR TempString[256];
|
||||||
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[app.GetGameSettings(m_iPad,eGameSetting_Difficulty)]));
|
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[app.GetGameSettings(m_iPad,eGameSetting_Difficulty)]));
|
||||||
m_sliderDifficulty.init(TempString,eControl_Difficulty,0,3,app.GetGameSettings(m_iPad,eGameSetting_Difficulty));
|
m_sliderDifficulty.init(TempString,eControl_Difficulty,0,4,app.GetGameSettings(m_iPad,eGameSetting_Difficulty));
|
||||||
|
|
||||||
|
s_bHardcore = false;
|
||||||
m_MoreOptionsParams.bGenerateOptions=TRUE;
|
m_MoreOptionsParams.bGenerateOptions=TRUE;
|
||||||
m_MoreOptionsParams.bStructures=TRUE;
|
m_MoreOptionsParams.bStructures=TRUE;
|
||||||
m_MoreOptionsParams.bFlatWorld=FALSE;
|
m_MoreOptionsParams.bFlatWorld=FALSE;
|
||||||
@@ -654,8 +657,13 @@ void UIScene_CreateWorldMenu::handleSliderMove(F64 sliderId, F64 currentValue)
|
|||||||
case eControl_Difficulty:
|
case eControl_Difficulty:
|
||||||
m_sliderDifficulty.handleSliderMove(value);
|
m_sliderDifficulty.handleSliderMove(value);
|
||||||
|
|
||||||
app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value);
|
// 4J Added: Difficulty value 4 = Hardcore (store actual difficulty as Hard, track hardcore separately)
|
||||||
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
|
s_bHardcore = (value >= 4);
|
||||||
|
app.SetGameSettings(m_iPad, eGameSetting_Difficulty, s_bHardcore ? 3 : value);
|
||||||
|
if (value >= 4)
|
||||||
|
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ), L"Hardcore");
|
||||||
|
else
|
||||||
|
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
|
||||||
m_sliderDifficulty.setLabel(TempString);
|
m_sliderDifficulty.setLabel(TempString);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -823,7 +831,7 @@ void UIScene_CreateWorldMenu::checkStateAndStartGame()
|
|||||||
// 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK
|
// 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];
|
UINT uiIDA[1];
|
||||||
uiIDA[0]=IDS_OK;
|
uiIDA[0]=IDS_OK;
|
||||||
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
|
ui.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1113,6 +1121,10 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
|
|||||||
StorageManager.ResetSaveData();
|
StorageManager.ResetSaveData();
|
||||||
// Make our next save default to the name of the level
|
// Make our next save default to the name of the level
|
||||||
StorageManager.SetSaveTitle((wchar_t *)wWorldName.c_str());
|
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;
|
wstring wSeed;
|
||||||
if(!pClass->m_MoreOptionsParams.seed.empty() )
|
if(!pClass->m_MoreOptionsParams.seed.empty() )
|
||||||
@@ -1179,7 +1191,9 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
|
|||||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||||
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
|
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
|
||||||
|
|
||||||
app.SetGameHostOption(eGameHostOption_Difficulty,Minecraft::GetInstance()->options->difficulty);
|
// 4J Added: If hardcore was selected on difficulty slider, set difficulty to Hard and enable hardcore flag
|
||||||
|
app.SetGameHostOption(eGameHostOption_Difficulty, Minecraft::GetInstance()->options->difficulty);
|
||||||
|
app.SetGameHostOption(eGameHostOption_Hardcore, s_bHardcore ? 1 : 0);
|
||||||
app.SetGameHostOption(eGameHostOption_FriendsOfFriends,pClass->m_MoreOptionsParams.bAllowFriendsOfFriends);
|
app.SetGameHostOption(eGameHostOption_FriendsOfFriends,pClass->m_MoreOptionsParams.bAllowFriendsOfFriends);
|
||||||
app.SetGameHostOption(eGameHostOption_Gamertags,app.GetGameSettings(pClass->m_iPad,eGameSetting_GamertagsVisible)?1:0);
|
app.SetGameHostOption(eGameHostOption_Gamertags,app.GetGameSettings(pClass->m_iPad,eGameSetting_GamertagsVisible)?1:0);
|
||||||
|
|
||||||
|
|||||||
@@ -480,14 +480,6 @@ SCreditTextItemDef UIScene_Credits::gs_aCreditDefs[MAX_CREDIT_STRINGS] =
|
|||||||
{ L"Copyright (C) 2009-2013 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
{ L"Copyright (C) 2009-2013 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
||||||
#else
|
#else
|
||||||
{ L"Copyright (C) 2009-2014 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
{ L"Copyright (C) 2009-2014 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
||||||
#endif
|
|
||||||
{ L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
|
||||||
{ L"", CREDIT_ICON, eCreditIcon_Miles,eSmallText }, // extra blank line
|
|
||||||
{ L"Uses Miles Sound System.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
|
||||||
#ifdef __PS3__
|
|
||||||
{ L"Copyright (C) 1991-2013 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
|
||||||
#else
|
|
||||||
{ L"Copyright (C) 1991-2014 by RAD Game Tools, Inc.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef __PS3__
|
#ifdef __PS3__
|
||||||
{ L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
{ L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
||||||
@@ -496,6 +488,24 @@ SCreditTextItemDef UIScene_Credits::gs_aCreditDefs[MAX_CREDIT_STRINGS] =
|
|||||||
{ L"are trademarks of Dolby Laboratories.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
{ L"are trademarks of Dolby Laboratories.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
|
||||||
|
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
|
||||||
|
{L"MinecraftConsoles", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eExtraLargeText},
|
||||||
|
{L"Project Maintainers", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
|
||||||
|
{L"smartcmd", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
|
||||||
|
{L"codeHusky", 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"mattsumi", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
|
||||||
|
{L"dxf", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
|
||||||
|
{L"la", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
|
||||||
|
{L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText},
|
||||||
|
{L"Thank you to our 100+ contributors on GitHub!", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eLargeText},
|
||||||
|
{L"github.com/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},
|
||||||
|
{L"notpies - Security Fixes", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING, eSmallText}
|
||||||
};
|
};
|
||||||
|
|
||||||
UIScene_Credits::UIScene_Credits(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
UIScene_Credits::UIScene_Credits(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
||||||
|
|||||||
@@ -3,24 +3,43 @@
|
|||||||
#include "UIScene_DeathMenu.h"
|
#include "UIScene_DeathMenu.h"
|
||||||
#include "IUIScene_PauseMenu.h"
|
#include "IUIScene_PauseMenu.h"
|
||||||
#include "..\..\Minecraft.h"
|
#include "..\..\Minecraft.h"
|
||||||
|
#include "..\..\MultiPlayerLevel.h"
|
||||||
#include "..\..\MultiplayerLocalPlayer.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)
|
UIScene_DeathMenu::UIScene_DeathMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
||||||
{
|
{
|
||||||
// Setup all the Iggy references we need for this scene
|
// Setup all the Iggy references we need for this scene
|
||||||
initialiseMovie();
|
initialiseMovie();
|
||||||
|
|
||||||
m_buttonRespawn.init(app.GetString(IDS_RESPAWN),eControl_Respawn);
|
|
||||||
m_buttonExitGame.init(app.GetString(IDS_EXIT_GAME),eControl_ExitGame);
|
m_buttonExitGame.init(app.GetString(IDS_EXIT_GAME),eControl_ExitGame);
|
||||||
|
|
||||||
m_labelTitle.setLabel(app.GetString(IDS_YOU_DIED));
|
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.init(app.GetString(IDS_HARDCORE_DEATH_MESSAGE), eControl_Respawn);
|
||||||
|
m_buttonRespawn.setVisible(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_buttonRespawn.init(app.GetString(IDS_RESPAWN), eControl_Respawn);
|
||||||
|
}
|
||||||
|
|
||||||
m_bIgnoreInput = false;
|
m_bIgnoreInput = false;
|
||||||
|
|
||||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
if(pMC != nullptr && pMC->localgameModes[iPad] != nullptr )
|
||||||
if(pMinecraft != nullptr && pMinecraft->localgameModes[iPad] != nullptr )
|
|
||||||
{
|
{
|
||||||
TutorialMode *gameMode = static_cast<TutorialMode *>(pMinecraft->localgameModes[iPad]);
|
TutorialMode *gameMode = static_cast<TutorialMode *>(pMC->localgameModes[iPad]);
|
||||||
|
|
||||||
// This just allows it to be shown
|
// This just allows it to be shown
|
||||||
gameMode->getTutorial()->showTutorialPopup(false);
|
gameMode->getTutorial()->showTutorialPopup(false);
|
||||||
@@ -84,8 +103,16 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
|
|||||||
switch(static_cast<int>(controlId))
|
switch(static_cast<int>(controlId))
|
||||||
{
|
{
|
||||||
case eControl_Respawn:
|
case eControl_Respawn:
|
||||||
m_bIgnoreInput = true;
|
{
|
||||||
app.SetAction(m_iPad,eAppAction_Respawn);
|
// 4J Added: Safeguard - don't respawn in hardcore mode
|
||||||
|
Minecraft *pMC = Minecraft::GetInstance();
|
||||||
|
if (pMC != nullptr && pMC->level != nullptr && pMC->level->getLevelData()->isHardcore())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_bIgnoreInput = true;
|
||||||
|
app.SetAction(m_iPad,eAppAction_Respawn);
|
||||||
|
}
|
||||||
#ifdef _DURANGO
|
#ifdef _DURANGO
|
||||||
//InputManager.SetEnabledGtcButtons(_360_GTC_MENU|_360_GTC_PAUSE|_360_GTC_VIEW);
|
//InputManager.SetEnabledGtcButtons(_360_GTC_MENU|_360_GTC_PAUSE|_360_GTC_VIEW);
|
||||||
#endif
|
#endif
|
||||||
@@ -110,6 +137,15 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
|
|||||||
}
|
}
|
||||||
TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Failed);
|
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 defined (_XBOX_ONE) || defined(__ORBIS__)
|
||||||
if(g_NetworkManager.IsHost() && StorageManager.GetSaveDisabled())
|
if(g_NetworkManager.IsHost() && StorageManager.GetSaveDisabled())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "UI.h"
|
#include "UI.h"
|
||||||
#include "UIScene_Keyboard.h"
|
#include "UIScene_Keyboard.h"
|
||||||
|
#include "..\..\Screen.h"
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
// Global buffer that stores the text entered in the native keyboard scene.
|
// Global buffer that stores the text entered in the native keyboard scene.
|
||||||
@@ -224,6 +225,28 @@ void UIScene_Keyboard::tick()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paste from clipboard
|
||||||
|
if (g_KBMInput.IsKeyPressed('V') && g_KBMInput.IsKeyDown(VK_CONTROL))
|
||||||
|
{
|
||||||
|
wstring pasted = Screen::getClipboard();
|
||||||
|
for (size_t i = 0; i < pasted.length(); i++)
|
||||||
|
{
|
||||||
|
wchar_t pc = pasted[i];
|
||||||
|
if (pc < 0x20) continue; // skip control characters
|
||||||
|
if (static_cast<int>(m_win64TextBuffer.length()) >= m_win64MaxChars) break;
|
||||||
|
if (m_bPCMode)
|
||||||
|
{
|
||||||
|
m_win64TextBuffer.insert(m_iCursorPos, 1, pc);
|
||||||
|
m_iCursorPos++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_win64TextBuffer += pc;
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_bPCMode)
|
if (m_bPCMode)
|
||||||
{
|
{
|
||||||
// Arrow keys, Home, End, Delete for cursor movement
|
// Arrow keys, Home, End, Delete for cursor movement
|
||||||
|
|||||||
@@ -24,12 +24,13 @@
|
|||||||
#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50
|
#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[4]=
|
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[5]=
|
||||||
{
|
{
|
||||||
IDS_DIFFICULTY_TITLE_PEACEFUL,
|
IDS_DIFFICULTY_TITLE_PEACEFUL,
|
||||||
IDS_DIFFICULTY_TITLE_EASY,
|
IDS_DIFFICULTY_TITLE_EASY,
|
||||||
IDS_DIFFICULTY_TITLE_NORMAL,
|
IDS_DIFFICULTY_TITLE_NORMAL,
|
||||||
IDS_DIFFICULTY_TITLE_HARD
|
IDS_DIFFICULTY_TITLE_HARD,
|
||||||
|
IDS_GAMEMODE_HARDCORE
|
||||||
};
|
};
|
||||||
|
|
||||||
int UIScene_LoadMenu::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes)
|
int UIScene_LoadMenu::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes)
|
||||||
@@ -110,6 +111,7 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
|
|||||||
m_bThumbnailGetFailed = false;
|
m_bThumbnailGetFailed = false;
|
||||||
m_seed = 0;
|
m_seed = 0;
|
||||||
m_bIsCorrupt = false;
|
m_bIsCorrupt = false;
|
||||||
|
m_bHardcore = false;
|
||||||
|
|
||||||
m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
|
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.
|
// 4J-PB - read the settings for the online flag. We'll only save this setting if the user changed it.
|
||||||
@@ -253,10 +255,34 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
|
|||||||
{
|
{
|
||||||
wchar_t wSaveName[128];
|
wchar_t wSaveName[128];
|
||||||
ZeroMemory(wSaveName, sizeof(wSaveName));
|
ZeroMemory(wSaveName, sizeof(wSaveName));
|
||||||
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, 127);
|
MultiByteToWideChar(CP_UTF8, 0, params->saveDetails->UTF8SaveName, -1, wSaveName, 127);
|
||||||
m_levelName = wstring(wSaveName);
|
m_levelName = wstring(wSaveName);
|
||||||
m_labelGameName.init(m_levelName);
|
m_labelGameName.init(m_levelName);
|
||||||
}
|
}
|
||||||
|
if (params->saveDetails != nullptr)
|
||||||
|
{
|
||||||
|
// Set thumbnail name from save filename (needed for texture display in tick)
|
||||||
|
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
|
||||||
|
ZeroMemory(wFilename, sizeof(wFilename));
|
||||||
|
mbstowcs(wFilename, params->saveDetails->UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
|
||||||
|
m_thumbnailName = wFilename;
|
||||||
|
|
||||||
|
if (params->saveDetails->pbThumbnailData && params->saveDetails->dwThumbnailSize > 0)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,6 +572,14 @@ void UIScene_LoadMenu::tick()
|
|||||||
{
|
{
|
||||||
m_MoreOptionsParams.bAllowFriendsOfFriends = TRUE;
|
m_MoreOptionsParams.bAllowFriendsOfFriends = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_bHardcore = app.GetGameHostOption(uiHostOptions, eGameHostOption_Hardcore) > 0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||||
@@ -950,6 +984,11 @@ void UIScene_LoadMenu::handleSliderMove(F64 sliderId, F64 currentValue)
|
|||||||
switch(static_cast<int>(sliderId))
|
switch(static_cast<int>(sliderId))
|
||||||
{
|
{
|
||||||
case eControl_Difficulty:
|
case eControl_Difficulty:
|
||||||
|
if (m_bHardcore)
|
||||||
|
{
|
||||||
|
m_sliderDifficulty.handleSliderMove(4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
m_sliderDifficulty.handleSliderMove(value);
|
m_sliderDifficulty.handleSliderMove(value);
|
||||||
|
|
||||||
app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value);
|
app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value);
|
||||||
@@ -1580,6 +1619,24 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
|
|||||||
|
|
||||||
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
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();
|
NetworkGameInitData *param = new NetworkGameInitData();
|
||||||
param->seed = pClass->m_seed;
|
param->seed = pClass->m_seed;
|
||||||
param->saveData = nullptr;
|
param->saveData = nullptr;
|
||||||
@@ -1612,6 +1669,7 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
|
|||||||
app.SetGameHostOption(eGameHostOption_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
|
app.SetGameHostOption(eGameHostOption_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
|
||||||
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
|
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
|
||||||
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
|
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
|
||||||
|
app.SetGameHostOption(eGameHostOption_Hardcore, pClass->m_bHardcore ? 1 : 0);
|
||||||
|
|
||||||
#ifdef _LARGE_WORLDS
|
#ifdef _LARGE_WORLDS
|
||||||
app.SetGameHostOption(eGameHostOption_WorldSize, pClass->m_MoreOptionsParams.worldSize+1 ); // 0 is GAME_HOST_OPTION_WORLDSIZE_UNKNOWN
|
app.SetGameHostOption(eGameHostOption_WorldSize, pClass->m_MoreOptionsParams.worldSize+1 ); // 0 is GAME_HOST_OPTION_WORLDSIZE_UNKNOWN
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ private:
|
|||||||
eControl_OnlineGame,
|
eControl_OnlineGame,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int m_iDifficultyTitleSettingA[4];
|
static int m_iDifficultyTitleSettingA[5];
|
||||||
|
|
||||||
UIControl m_controlMainPanel;
|
UIControl m_controlMainPanel;
|
||||||
UIControl_Label m_labelGameName, m_labelSeed, m_labelCreatedMode;
|
UIControl_Label m_labelGameName, m_labelSeed, m_labelCreatedMode;
|
||||||
@@ -71,6 +71,7 @@ private:
|
|||||||
wstring m_thumbnailName;
|
wstring m_thumbnailName;
|
||||||
|
|
||||||
bool m_bRebuildTouchBoxes;
|
bool m_bRebuildTouchBoxes;
|
||||||
|
bool m_bHardcore;
|
||||||
public:
|
public:
|
||||||
UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLayer);
|
UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLayer);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include "..\..\..\Minecraft.World\NbtIo.h"
|
#include "..\..\..\Minecraft.World\NbtIo.h"
|
||||||
#include "..\..\..\Minecraft.World\compression.h"
|
#include "..\..\..\Minecraft.World\compression.h"
|
||||||
|
|
||||||
static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
|
static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardcore = nullptr)
|
||||||
{
|
{
|
||||||
// Check for a worldname.txt sidecar written by the rename feature first
|
// Check for a worldname.txt sidecar written by the rename feature first
|
||||||
size_t slashPos = filePath.rfind(L'\\');
|
size_t slashPos = filePath.rfind(L'\\');
|
||||||
@@ -49,7 +49,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
|
|||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
wchar_t wbuf[128] = {};
|
wchar_t wbuf[128] = {};
|
||||||
mbstowcs(wbuf, buf, 127);
|
MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, 127);
|
||||||
return wstring(wbuf);
|
return wstring(wbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,11 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
|
|||||||
{
|
{
|
||||||
CompoundTag *dataTag = root->getCompound(L"Data");
|
CompoundTag *dataTag = root->getCompound(L"Data");
|
||||||
if (dataTag != nullptr)
|
if (dataTag != nullptr)
|
||||||
|
{
|
||||||
result = dataTag->getString(L"LevelName");
|
result = dataTag->getString(L"LevelName");
|
||||||
|
if (outHardcore)
|
||||||
|
*outHardcore = dataTag->getBoolean(L"hardcore");
|
||||||
|
}
|
||||||
delete root;
|
delete root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,6 +210,8 @@ int UIScene_LoadOrJoinMenu::LoadSaveCallback(LPVOID lpParam,bool bRes)
|
|||||||
|
|
||||||
UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
||||||
{
|
{
|
||||||
|
constexpr uint64_t MAXIMUM_SAVE_STORAGE = 4LL * 1024LL * 1024LL * 1024LL;
|
||||||
|
|
||||||
// Setup all the Iggy references we need for this scene
|
// Setup all the Iggy references we need for this scene
|
||||||
initialiseMovie();
|
initialiseMovie();
|
||||||
app.SetLiveLinkRequired( true );
|
app.SetLiveLinkRequired( true );
|
||||||
@@ -230,8 +236,8 @@ UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer
|
|||||||
m_controlJoinTimer.setVisible( true );
|
m_controlJoinTimer.setVisible( true );
|
||||||
|
|
||||||
|
|
||||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||||
m_spaceIndicatorSaves.init(L"",eControl_SpaceIndicator,0, (4LL *1024LL * 1024LL * 1024LL) );
|
m_spaceIndicatorSaves.init(L"",eControl_SpaceIndicator,0, MAXIMUM_SAVE_STORAGE);
|
||||||
#endif
|
#endif
|
||||||
m_bUpdateSaveSize = false;
|
m_bUpdateSaveSize = false;
|
||||||
|
|
||||||
@@ -695,7 +701,7 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
if(m_eSaveTransferState == eSaveTransfer_Idle)
|
if(m_eSaveTransferState == eSaveTransfer_Idle)
|
||||||
m_bSaveTransferRunning = false;
|
m_bSaveTransferRunning = false;
|
||||||
#endif
|
#endif
|
||||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||||
if(m_bUpdateSaveSize)
|
if(m_bUpdateSaveSize)
|
||||||
{
|
{
|
||||||
if((m_iDefaultButtonsC > 0) && (m_iSaveListIndex >= m_iDefaultButtonsC))
|
if((m_iDefaultButtonsC > 0) && (m_iSaveListIndex >= m_iDefaultButtonsC))
|
||||||
@@ -716,7 +722,7 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
if(m_pSaveDetails!=nullptr)
|
if(m_pSaveDetails!=nullptr)
|
||||||
{
|
{
|
||||||
//CD - Fix - Adding define for ORBIS/XBOXONE
|
//CD - Fix - Adding define for ORBIS/XBOXONE
|
||||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||||
m_spaceIndicatorSaves.reset();
|
m_spaceIndicatorSaves.reset();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -758,6 +764,22 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
{
|
{
|
||||||
#if defined(_XBOX_ONE)
|
#if defined(_XBOX_ONE)
|
||||||
m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[i].totalSize);
|
m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[i].totalSize);
|
||||||
|
#elif defined(_WINDOWS64)
|
||||||
|
int origIdx = sortedIdx[i];
|
||||||
|
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
|
||||||
|
ZeroMemory(wFilename, sizeof(wFilename));
|
||||||
|
mbstowcs(wFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
|
||||||
|
wstring filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\saveData.ms");
|
||||||
|
|
||||||
|
HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
|
||||||
|
DWORD fileSize = 0;
|
||||||
|
|
||||||
|
if (hFile != INVALID_HANDLE_VALUE) {
|
||||||
|
fileSize = GetFileSize(hFile, nullptr);
|
||||||
|
if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) fileSize = 0;
|
||||||
|
CloseHandle(hFile);
|
||||||
|
}
|
||||||
|
m_spaceIndicatorSaves.addSave(fileSize);
|
||||||
#elif defined(__ORBIS__)
|
#elif defined(__ORBIS__)
|
||||||
m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[i].blocksUsed * (32 * 1024) );
|
m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[i].blocksUsed * (32 * 1024) );
|
||||||
#endif
|
#endif
|
||||||
@@ -770,17 +792,17 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
#else
|
#else
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
{
|
{
|
||||||
int origIdx = sortedIdx[i];
|
bool saveHardcore = false;
|
||||||
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
|
wstring levelName = ReadLevelNameFromSaveFile(filePath, &saveHardcore);
|
||||||
ZeroMemory(wFilename, sizeof(wFilename));
|
m_saveDetails[i].isHardcore = saveHardcore;
|
||||||
mbstowcs(wFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
|
|
||||||
wstring filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\saveData.ms");
|
|
||||||
wstring levelName = ReadLevelNameFromSaveFile(filePath);
|
|
||||||
if (!levelName.empty())
|
if (!levelName.empty())
|
||||||
{
|
{
|
||||||
m_buttonListSaves.addItem(levelName, wstring(L""));
|
m_buttonListSaves.addItem(levelName, wstring(L""));
|
||||||
wcstombs(m_saveDetails[i].UTF8SaveName, levelName.c_str(), 127);
|
{
|
||||||
m_saveDetails[i].UTF8SaveName[127] = '\0';
|
int n = WideCharToMultiByte(CP_UTF8, 0, levelName.c_str(), -1, m_saveDetails[i].UTF8SaveName, 127, nullptr, nullptr);
|
||||||
|
if (n <= 0) m_saveDetails[i].UTF8SaveName[0] = '\0';
|
||||||
|
m_saveDetails[i].UTF8SaveName[127] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1425,9 +1447,9 @@ int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,boo
|
|||||||
for (int k = 0; k < 127 && ui16Text[k]; k++)
|
for (int k = 0; k < 127 && ui16Text[k]; k++)
|
||||||
wNewName[k] = static_cast<wchar_t>(ui16Text[k]);
|
wNewName[k] = static_cast<wchar_t>(ui16Text[k]);
|
||||||
|
|
||||||
// Convert to narrow for storage and in-memory update
|
// Convert to narrow for storage and in-memory update (UTF-8 to preserve Unicode)
|
||||||
char narrowName[128] = {};
|
char narrowName[256] = {};
|
||||||
wcstombs(narrowName, wNewName, 127);
|
WideCharToMultiByte(CP_UTF8, 0, wNewName, -1, narrowName, 255, nullptr, nullptr);
|
||||||
|
|
||||||
// Build the sidecar path: Windows64\GameHDD\{folder}\worldname.txt
|
// Build the sidecar path: Windows64\GameHDD\{folder}\worldname.txt
|
||||||
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH] = {};
|
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH] = {};
|
||||||
@@ -1443,7 +1465,7 @@ int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,boo
|
|||||||
|
|
||||||
// Update the in-memory display name so the list reflects it immediately
|
// Update the in-memory display name so the list reflects it immediately
|
||||||
strncpy_s(pClass->m_saveDetails[listPos].UTF8SaveName, narrowName, 127);
|
strncpy_s(pClass->m_saveDetails[listPos].UTF8SaveName, narrowName, 127);
|
||||||
pClass->m_saveDetails[listPos].UTF8SaveName[127] = '\0';
|
pClass->m_saveDetails[listPos].UTF8SaveName[127] = '\0'; // UTF8SaveName is still 128 bytes; narrowName fits as Arabic is <=2 bytes/char in UTF-8
|
||||||
|
|
||||||
// Reuse the existing callback to trigger the list repopulate
|
// Reuse the existing callback to trigger the list repopulate
|
||||||
UIScene_LoadOrJoinMenu::RenameSaveDataReturned(pClass, true);
|
UIScene_LoadOrJoinMenu::RenameSaveDataReturned(pClass, true);
|
||||||
@@ -2511,7 +2533,7 @@ int UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad,C4JS
|
|||||||
{
|
{
|
||||||
wchar_t wSaveName[128];
|
wchar_t wSaveName[128];
|
||||||
ZeroMemory(wSaveName, 128 * sizeof(wchar_t));
|
ZeroMemory(wSaveName, 128 * sizeof(wchar_t));
|
||||||
mbstowcs_s(nullptr, wSaveName, 128, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, _TRUNCATE);
|
MultiByteToWideChar(CP_UTF8, 0, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, -1, wSaveName, 127);
|
||||||
UIKeyboardInitData kbData;
|
UIKeyboardInitData kbData;
|
||||||
kbData.title = app.GetString(IDS_RENAME_WORLD_TITLE);
|
kbData.title = app.GetString(IDS_RENAME_WORLD_TITLE);
|
||||||
kbData.defaultText = wSaveName;
|
kbData.defaultText = wSaveName;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ private:
|
|||||||
{
|
{
|
||||||
eControl_SavesList,
|
eControl_SavesList,
|
||||||
eControl_GamesList,
|
eControl_GamesList,
|
||||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||||
eControl_SpaceIndicator,
|
eControl_SpaceIndicator,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -52,7 +52,7 @@ protected:
|
|||||||
UIControl_SaveList m_buttonListGames;
|
UIControl_SaveList m_buttonListGames;
|
||||||
UIControl_Label m_labelSavesListTitle, m_labelJoinListTitle, m_labelNoGames;
|
UIControl_Label m_labelSavesListTitle, m_labelJoinListTitle, m_labelNoGames;
|
||||||
UIControl m_controlSavesTimer, m_controlJoinTimer;
|
UIControl m_controlSavesTimer, m_controlJoinTimer;
|
||||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||||
UIControl_SpaceIndicatorBar m_spaceIndicatorSaves;
|
UIControl_SpaceIndicatorBar m_spaceIndicatorSaves;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ private:
|
|||||||
UI_MAP_ELEMENT( m_controlSavesTimer, "SavesTimer")
|
UI_MAP_ELEMENT( m_controlSavesTimer, "SavesTimer")
|
||||||
UI_MAP_ELEMENT( m_controlJoinTimer, "JoinTimer")
|
UI_MAP_ELEMENT( m_controlJoinTimer, "JoinTimer")
|
||||||
|
|
||||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||||
UI_MAP_ELEMENT( m_spaceIndicatorSaves, "SaveSizeBar")
|
UI_MAP_ELEMENT( m_spaceIndicatorSaves, "SaveSizeBar")
|
||||||
#endif
|
#endif
|
||||||
UI_END_MAP_ELEMENTS_AND_NAMES()
|
UI_END_MAP_ELEMENTS_AND_NAMES()
|
||||||
|
|||||||
@@ -247,11 +247,14 @@ typedef struct _SaveListDetails
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool isHardcore;
|
||||||
|
|
||||||
_SaveListDetails()
|
_SaveListDetails()
|
||||||
{
|
{
|
||||||
saveId = 0;
|
saveId = 0;
|
||||||
pbThumbnailData = nullptr;
|
pbThumbnailData = nullptr;
|
||||||
dwThumbnailSize = 0;
|
dwThumbnailSize = 0;
|
||||||
|
isHardcore = false;
|
||||||
#ifdef _DURANGO
|
#ifdef _DURANGO
|
||||||
ZeroMemory(UTF16SaveName,sizeof(wchar_t)*128);
|
ZeroMemory(UTF16SaveName,sizeof(wchar_t)*128);
|
||||||
ZeroMemory(UTF16SaveFilename,sizeof(wchar_t)*MAX_SAVEFILENAME_LENGTH);
|
ZeroMemory(UTF16SaveFilename,sizeof(wchar_t)*MAX_SAVEFILENAME_LENGTH);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "..\..\..\Minecraft.World\File.h"
|
#include "..\..\..\Minecraft.World\File.h"
|
||||||
#include "UITTFFont.h"
|
#include "UITTFFont.h"
|
||||||
|
|
||||||
UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharacter)
|
UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharacter, bool registerAsDefaultFonts)
|
||||||
: m_strFontName(name)
|
: m_strFontName(name)
|
||||||
{
|
{
|
||||||
app.DebugPrintf("UITTFFont opening %s\n",path.c_str());
|
app.DebugPrintf("UITTFFont opening %s\n",path.c_str());
|
||||||
@@ -41,9 +41,12 @@ UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharact
|
|||||||
|
|
||||||
IggyFontInstallTruetypeFallbackCodepointUTF8( m_strFontName.c_str(), -1, IGGY_FONTFLAG_none, fallbackCharacter );
|
IggyFontInstallTruetypeFallbackCodepointUTF8( m_strFontName.c_str(), -1, IGGY_FONTFLAG_none, fallbackCharacter );
|
||||||
|
|
||||||
// 4J Stu - These are so we can use the default flash controls
|
if (registerAsDefaultFonts)
|
||||||
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Times New Roman", -1, IGGY_FONTFLAG_none );
|
{
|
||||||
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Arial", -1, IGGY_FONTFLAG_none );
|
// 4J Stu - These are so we can use the default flash controls
|
||||||
|
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Times New Roman", -1, IGGY_FONTFLAG_none );
|
||||||
|
IggyFontInstallTruetypeUTF8 ( (void *)pbData, IGGY_TTC_INDEX_none, "Arial", -1, IGGY_FONTFLAG_none );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ private:
|
|||||||
//DWORD dwDataSize;
|
//DWORD dwDataSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UITTFFont(const string &name, const string &path, S32 fallbackCharacter);
|
UITTFFont(const string &name, const string &path, S32 fallbackCharacter, bool registerAsDefaultFonts = true);
|
||||||
~UITTFFont();
|
~UITTFFont();
|
||||||
|
|
||||||
string getFontName();
|
string getFontName();
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
#include "stdafx.h"
|
||||||
|
#include "BufferedImage.h"
|
||||||
|
#include "UIFontData.h"
|
||||||
|
#include "UIUnicodeBitmapFont.h"
|
||||||
|
|
||||||
|
UIUnicodeBitmapFont::UIUnicodeBitmapFont(const string &fontname, SFontData &referenceFontData)
|
||||||
|
: UIAbstractBitmapFont(fontname)
|
||||||
|
{
|
||||||
|
m_numGlyphs = 65536;
|
||||||
|
m_referenceFontData = &referenceFontData;
|
||||||
|
memset(m_glyphPages, 0, sizeof(m_glyphPages));
|
||||||
|
memset(m_unicodeWidth, 0, sizeof(m_unicodeWidth));
|
||||||
|
|
||||||
|
FILE *f = nullptr;
|
||||||
|
fopen_s(&f, "Common/res/1_2_2/font/glyph_sizes.bin", "rb");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fread(m_unicodeWidth, 1, 65536, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UIUnicodeBitmapFont::~UIUnicodeBitmapFont()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
delete[] m_glyphPages[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIUnicodeBitmapFont::loadGlyphPage(int page)
|
||||||
|
{
|
||||||
|
wchar_t fileName[64];
|
||||||
|
swprintf(fileName, 64, L"/1_2_2/font/glyph_%02X.png", page);
|
||||||
|
BufferedImage bimg(fileName);
|
||||||
|
int *rawData = bimg.getData();
|
||||||
|
if (!rawData) return;
|
||||||
|
|
||||||
|
int size = 256 * 256;
|
||||||
|
m_glyphPages[page] = new unsigned char[size];
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
m_glyphPages[page][i] = (rawData[i] & 0xFF000000) >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
IggyFontMetrics *UIUnicodeBitmapFont::GetFontMetrics(IggyFontMetrics *metrics)
|
||||||
|
{
|
||||||
|
metrics->ascent = m_referenceFontData->m_fAscent;
|
||||||
|
metrics->descent = m_referenceFontData->m_fDescent;
|
||||||
|
metrics->average_glyph_width_for_tab_stops = 8.0f;
|
||||||
|
metrics->largest_glyph_bbox_y1 = metrics->descent;
|
||||||
|
return metrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
S32 UIUnicodeBitmapFont::GetCodepointGlyph(U32 codepoint)
|
||||||
|
{
|
||||||
|
if (codepoint < 65536 && m_unicodeWidth[codepoint] != 0)
|
||||||
|
return (S32)codepoint;
|
||||||
|
return IGGY_GLYPH_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
IggyGlyphMetrics *UIUnicodeBitmapFont::GetGlyphMetrics(S32 glyph, IggyGlyphMetrics *metrics)
|
||||||
|
{
|
||||||
|
if (glyph < 0 || glyph >= 65536) { metrics->x0 = metrics->x1 = metrics->advance = metrics->y0 = metrics->y1 = 0; return metrics; }
|
||||||
|
int left = m_unicodeWidth[glyph] >> 4;
|
||||||
|
int right = (m_unicodeWidth[glyph] & 0xF) + 1;
|
||||||
|
float pixelWidth = (right - left) / 2.0f + 1.0f;
|
||||||
|
float advance = pixelWidth * m_referenceFontData->m_fAdvPerPixel;
|
||||||
|
|
||||||
|
metrics->x0 = 0.0f;
|
||||||
|
metrics->x1 = advance;
|
||||||
|
metrics->advance = advance;
|
||||||
|
metrics->y0 = 0.0f;
|
||||||
|
metrics->y1 = 1.0f;
|
||||||
|
return metrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
rrbool UIUnicodeBitmapFont::IsGlyphEmpty(S32 glyph)
|
||||||
|
{
|
||||||
|
if (glyph < 0 || glyph >= 65536) return true;
|
||||||
|
return m_unicodeWidth[glyph] == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
F32 UIUnicodeBitmapFont::GetKerningForGlyphPair(S32 first_glyph, S32 second_glyph)
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
rrbool UIUnicodeBitmapFont::CanProvideBitmap(S32 glyph, F32 pixel_scale)
|
||||||
|
{
|
||||||
|
return glyph >= 0 && glyph < 65536;
|
||||||
|
}
|
||||||
|
|
||||||
|
rrbool UIUnicodeBitmapFont::GetGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap)
|
||||||
|
{
|
||||||
|
if (glyph < 0 || glyph >= 65536) return false;
|
||||||
|
int page = glyph / 256;
|
||||||
|
if (!m_glyphPages[page])
|
||||||
|
{
|
||||||
|
loadGlyphPage(page);
|
||||||
|
if (!m_glyphPages[page]) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cx = (glyph % 16) * 16;
|
||||||
|
int cy = ((glyph & 0xFF) / 16) * 16;
|
||||||
|
|
||||||
|
bitmap->pixels_one_per_byte = m_glyphPages[page] + (cy * 256) + cx;
|
||||||
|
bitmap->width_in_pixels = 16;
|
||||||
|
bitmap->height_in_pixels = 16;
|
||||||
|
bitmap->stride_in_bytes = 256;
|
||||||
|
|
||||||
|
bitmap->top_left_x = 0;
|
||||||
|
bitmap->top_left_y = -static_cast<S32>(16) * m_referenceFontData->m_fAscent;
|
||||||
|
|
||||||
|
bitmap->oversample = 0;
|
||||||
|
|
||||||
|
// Scale parameters: match UIBitmapFont's approach.
|
||||||
|
// truePixelScale = the pixel_scale at which 1 glyph pixel = 1 screen pixel.
|
||||||
|
// For 16px glyphs displayed at the same visual size as Mojangles_7 (8px glyphs with advPerPixel 1/10):
|
||||||
|
// The reference truePixelScale for Mojangles_7 is 1.0f/m_fAdvPerPixel = 10.0f
|
||||||
|
// Since our glyphs are 16px (2x the Mojangles 8px), our truePixelScale is 20.0f
|
||||||
|
float truePixelScale = 2.0f / m_referenceFontData->m_fAdvPerPixel;
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
bitmap->pixel_scale_correct = truePixelScale;
|
||||||
|
if (pixel_scale < truePixelScale)
|
||||||
|
{
|
||||||
|
bitmap->pixel_scale_min = 0.0f;
|
||||||
|
bitmap->pixel_scale_max = truePixelScale;
|
||||||
|
bitmap->point_sample = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmap->pixel_scale_min = truePixelScale;
|
||||||
|
bitmap->pixel_scale_max = 99.0f;
|
||||||
|
bitmap->point_sample = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
float glyphScale = 1.0f;
|
||||||
|
while ((0.5f + glyphScale) * truePixelScale < pixel_scale)
|
||||||
|
glyphScale++;
|
||||||
|
|
||||||
|
if (glyphScale <= 1 && pixel_scale < truePixelScale)
|
||||||
|
{
|
||||||
|
bitmap->pixel_scale_correct = truePixelScale;
|
||||||
|
bitmap->pixel_scale_min = 0.0f;
|
||||||
|
bitmap->pixel_scale_max = truePixelScale * 1.001f;
|
||||||
|
bitmap->point_sample = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float actualScale = pixel_scale / glyphScale;
|
||||||
|
bitmap->pixel_scale_correct = actualScale;
|
||||||
|
bitmap->pixel_scale_min = truePixelScale;
|
||||||
|
bitmap->pixel_scale_max = 99.0f;
|
||||||
|
bitmap->point_sample = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bitmap->user_context_for_free = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIUnicodeBitmapFont::FreeGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap)
|
||||||
|
{
|
||||||
|
// Pixel data lives in m_glyphPages -- nothing to free.
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "UIBitmapFont.h"
|
||||||
|
|
||||||
|
struct SFontData;
|
||||||
|
|
||||||
|
class UIUnicodeBitmapFont : public UIAbstractBitmapFont
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
unsigned char m_unicodeWidth[65536];
|
||||||
|
unsigned char* m_glyphPages[256];
|
||||||
|
SFontData* m_referenceFontData;
|
||||||
|
|
||||||
|
void loadGlyphPage(int page);
|
||||||
|
|
||||||
|
public:
|
||||||
|
UIUnicodeBitmapFont(const string &fontname, SFontData &referenceFontData);
|
||||||
|
~UIUnicodeBitmapFont();
|
||||||
|
|
||||||
|
virtual IggyFontMetrics *GetFontMetrics(IggyFontMetrics *metrics);
|
||||||
|
virtual S32 GetCodepointGlyph(U32 codepoint);
|
||||||
|
virtual IggyGlyphMetrics *GetGlyphMetrics(S32 glyph, IggyGlyphMetrics *metrics);
|
||||||
|
virtual rrbool IsGlyphEmpty(S32 glyph);
|
||||||
|
virtual F32 GetKerningForGlyphPair(S32 first_glyph, S32 second_glyph);
|
||||||
|
virtual rrbool CanProvideBitmap(S32 glyph, F32 pixel_scale);
|
||||||
|
virtual rrbool GetGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap);
|
||||||
|
virtual void FreeGlyphBitmap(S32 glyph, F32 pixel_scale, IggyBitmapCharacter *bitmap);
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "XUI_Chat.h"
|
#include "XUI_Chat.h"
|
||||||
#include "..\..\Minecraft.h"
|
#include "..\..\Minecraft.h"
|
||||||
#include "..\..\Gui.h"
|
#include "..\..\Gui.h"
|
||||||
|
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||||
|
|
||||||
HRESULT CScene_Chat::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
|
HRESULT CScene_Chat::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
|
||||||
{
|
{
|
||||||
@@ -29,7 +30,8 @@ HRESULT CScene_Chat::OnTimer( XUIMessageTimer *pXUIMessageTimer, BOOL &bHandled)
|
|||||||
{
|
{
|
||||||
m_Backgrounds[i].SetOpacity(opacity);
|
m_Backgrounds[i].SetOpacity(opacity);
|
||||||
m_Labels[i].SetOpacity(opacity);
|
m_Labels[i].SetOpacity(opacity);
|
||||||
m_Labels[i].SetText( pGui->getMessage(m_iPad,i).c_str() );
|
wstring shaped = shapeArabicText(pGui->getMessage(m_iPad, i));
|
||||||
|
m_Labels[i].SetText( shaped.c_str() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "XUI_Ctrl_4JList.h"
|
#include "XUI_Ctrl_4JList.h"
|
||||||
|
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||||
|
|
||||||
static bool TimeSortFn(const void *a, const void *b);
|
static bool TimeSortFn(const void *a, const void *b);
|
||||||
|
|
||||||
@@ -294,8 +295,16 @@ HRESULT CXuiCtrl4JList::OnGetSourceDataText(XUIMessageGetSourceText *pGetSourceT
|
|||||||
if( ( 0 == pGetSourceTextData->iData ) && ( ( pGetSourceTextData->bItemData ) ) )
|
if( ( 0 == pGetSourceTextData->iData ) && ( ( pGetSourceTextData->bItemData ) ) )
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&m_AccessListData);
|
EnterCriticalSection(&m_AccessListData);
|
||||||
pGetSourceTextData->szText =
|
LPCWSTR rawText = GetData(pGetSourceTextData->iItem).pwszText;
|
||||||
GetData(pGetSourceTextData->iItem).pwszText;
|
if (rawText)
|
||||||
|
{
|
||||||
|
m_shapedTextCache = shapeArabicText(rawText);
|
||||||
|
pGetSourceTextData->szText = m_shapedTextCache.c_str();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pGetSourceTextData->szText = rawText;
|
||||||
|
}
|
||||||
LeaveCriticalSection(&m_AccessListData);
|
LeaveCriticalSection(&m_AccessListData);
|
||||||
bHandled = TRUE;
|
bHandled = TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,4 +75,5 @@ private:
|
|||||||
static bool IndexSortFn(const void *a, const void *b);
|
static bool IndexSortFn(const void *a, const void *b);
|
||||||
|
|
||||||
HXUIOBJ m_hSelectionChangedHandlerObj;
|
HXUIOBJ m_hSelectionChangedHandlerObj;
|
||||||
|
std::wstring m_shapedTextCache; // temp buffer for Arabic-shaped text in OnGetSourceDataText
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "..\..\..\Minecraft.World\Entity.h"
|
#include "..\..\..\Minecraft.World\Entity.h"
|
||||||
#include "..\..\..\Minecraft.Client\MultiplayerLocalPlayer.h"
|
#include "..\..\..\Minecraft.Client\MultiplayerLocalPlayer.h"
|
||||||
#include "..\..\..\Minecraft.World\Level.h"
|
#include "..\..\..\Minecraft.World\Level.h"
|
||||||
|
#include "..\..\..\Minecraft.World\net.minecraft.world.level.storage.h"
|
||||||
#include "..\..\..\Minecraft.World\ChunkSource.h"
|
#include "..\..\..\Minecraft.World\ChunkSource.h"
|
||||||
#include "..\..\..\Minecraft.Client\ProgressRenderer.h"
|
#include "..\..\..\Minecraft.Client\ProgressRenderer.h"
|
||||||
#include "..\..\..\Minecraft.Client\GameRenderer.h"
|
#include "..\..\..\Minecraft.Client\GameRenderer.h"
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
#include "..\..\..\Minecraft.World\Pos.h"
|
#include "..\..\..\Minecraft.World\Pos.h"
|
||||||
#include "..\..\..\Minecraft.World\Dimension.h"
|
#include "..\..\..\Minecraft.World\Dimension.h"
|
||||||
#include "..\..\Minecraft.h"
|
#include "..\..\Minecraft.h"
|
||||||
|
#include "..\..\MinecraftServer.h"
|
||||||
#include "..\..\Options.h"
|
#include "..\..\Options.h"
|
||||||
#include "..\..\LocalPlayer.h"
|
#include "..\..\LocalPlayer.h"
|
||||||
#include "..\..\..\Minecraft.World\compression.h"
|
#include "..\..\..\Minecraft.World\compression.h"
|
||||||
@@ -37,9 +39,26 @@ HRESULT CScene_Death::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
|
|||||||
}
|
}
|
||||||
|
|
||||||
XuiControlSetText(m_Title,app.GetString(IDS_YOU_DIED));
|
XuiControlSetText(m_Title,app.GetString(IDS_YOU_DIED));
|
||||||
XuiControlSetText(m_Buttons[BUTTON_DEATH_RESPAWN],app.GetString(IDS_RESPAWN));
|
|
||||||
XuiControlSetText(m_Buttons[BUTTON_DEATH_EXITGAME],app.GetString(IDS_EXIT_GAME));
|
XuiControlSetText(m_Buttons[BUTTON_DEATH_EXITGAME],app.GetString(IDS_EXIT_GAME));
|
||||||
|
|
||||||
|
// 4J Added: In hardcore mode, disable respawn and show hardcore death message
|
||||||
|
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||||
|
bool isHardcore = false;
|
||||||
|
if (pMinecraft != nullptr && pMinecraft->level != nullptr)
|
||||||
|
{
|
||||||
|
isHardcore = pMinecraft->level->getLevelData()->isHardcore();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHardcore)
|
||||||
|
{
|
||||||
|
XuiControlSetText(m_Buttons[BUTTON_DEATH_RESPAWN], app.GetString(IDS_HARDCORE_DEATH_MESSAGE));
|
||||||
|
XuiElementSetShow(m_Buttons[BUTTON_DEATH_RESPAWN], FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XuiControlSetText(m_Buttons[BUTTON_DEATH_RESPAWN], app.GetString(IDS_RESPAWN));
|
||||||
|
}
|
||||||
|
|
||||||
// Display the tooltips
|
// Display the tooltips
|
||||||
ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT);
|
ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT);
|
||||||
|
|
||||||
@@ -111,6 +130,15 @@ HRESULT CScene_Death::OnNotifyPressEx(HXUIOBJ hObjPressed, XUINotifyPress* pNoti
|
|||||||
}
|
}
|
||||||
TelemetryManager->RecordLevelExit(pNotifyPressData->UserIndex, eSen_LevelExitStatus_Failed);
|
TelemetryManager->RecordLevelExit(pNotifyPressData->UserIndex, 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(pNotifyPressData->UserIndex, eAppAction_ExitWorld);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(StorageManager.GetSaveDisabled())
|
if(StorageManager.GetSaveDisabled())
|
||||||
{
|
{
|
||||||
uiIDA[0]=IDS_CONFIRM_CANCEL;
|
uiIDA[0]=IDS_CONFIRM_CANCEL;
|
||||||
@@ -172,6 +200,12 @@ HRESULT CScene_Death::OnNotifyPressEx(HXUIOBJ hObjPressed, XUINotifyPress* pNoti
|
|||||||
break;
|
break;
|
||||||
case BUTTON_DEATH_RESPAWN:
|
case BUTTON_DEATH_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;
|
m_bIgnoreInput = true;
|
||||||
app.SetAction(pNotifyPressData->UserIndex,eAppAction_Respawn);
|
app.SetAction(pNotifyPressData->UserIndex,eAppAction_Respawn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
|||||||
int iHealth = pMinecraft->localplayers[m_iPad]->getHealth();
|
int iHealth = pMinecraft->localplayers[m_iPad]->getHealth();
|
||||||
int iLastHealth = pMinecraft->localplayers[m_iPad]->lastHealth;
|
int iLastHealth = pMinecraft->localplayers[m_iPad]->lastHealth;
|
||||||
bool bHasPoison = pMinecraft->localplayers[m_iPad]->hasEffect(MobEffect::poison);
|
bool bHasPoison = pMinecraft->localplayers[m_iPad]->hasEffect(MobEffect::poison);
|
||||||
|
bool isHardcore = pMinecraft->level != nullptr && pMinecraft->level->getLevelData()->isHardcore();
|
||||||
for (int icon = 0; icon < Player::MAX_HEALTH / 2; icon++)
|
for (int icon = 0; icon < Player::MAX_HEALTH / 2; icon++)
|
||||||
{
|
{
|
||||||
if(blink)
|
if(blink)
|
||||||
@@ -196,11 +197,15 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
|||||||
// Full
|
// Full
|
||||||
if(bHasPoison)
|
if(bHasPoison)
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"FullPoisonFlash",nullptr,L"FullPoisonFlash");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"FullPoisonFlashHardcore" : L"FullPoisonFlash", nullptr,
|
||||||
|
isHardcore ? L"FullPoisonFlashHardcore" : L"FullPoisonFlash");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"FullFlash",nullptr,L"FullFlash");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"FullFlashHardcore" : L"FullFlash", nullptr,
|
||||||
|
isHardcore ? L"FullFlashHardcore" : L"FullFlash");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (icon * 2 + 1 == iLastHealth || icon * 2 + 1 == iHealth)
|
else if (icon * 2 + 1 == iLastHealth || icon * 2 + 1 == iHealth)
|
||||||
@@ -208,17 +213,23 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
|||||||
// Half
|
// Half
|
||||||
if(bHasPoison)
|
if(bHasPoison)
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"HalfPoisonFlash",nullptr,L"HalfPoisonFlash");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"HalfPoisonFlashHardcore" : L"HalfPoisonFlash", nullptr,
|
||||||
|
isHardcore ? L"HalfPoisonFlashHardcore" : L"HalfPoisonFlash");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"HalfFlash",nullptr,L"HalfFlash");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"HalfFlashHardcore" : L"HalfFlash", nullptr,
|
||||||
|
isHardcore ? L"HalfFlashHardcore" : L"HalfFlash");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Empty
|
// Empty
|
||||||
m_healthIcon[icon].PlayVisualRange(L"NormalFlash",nullptr,L"NormalFlash");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"NormalFlashHardcore" : L"NormalFlash", nullptr,
|
||||||
|
isHardcore ? L"NormalFlashHardcore" : L"NormalFlash");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -228,11 +239,15 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
|||||||
// Full
|
// Full
|
||||||
if(bHasPoison)
|
if(bHasPoison)
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"FullPoison",nullptr,L"FullPoison");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"FullPoisonHardcore" : L"FullPoison", nullptr,
|
||||||
|
isHardcore ? L"FullPoisonHardcore" : L"FullPoison");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"Full",nullptr,L"Full");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"FullHardcore" : L"Full", nullptr,
|
||||||
|
isHardcore ? L"FullHardcore" : L"Full");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (icon * 2 + 1 == iHealth)
|
else if (icon * 2 + 1 == iHealth)
|
||||||
@@ -240,17 +255,23 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
|||||||
// Half
|
// Half
|
||||||
if(bHasPoison)
|
if(bHasPoison)
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"HalfPoison",nullptr,L"HalfPoison");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"HalfPoisonHardcore" : L"HalfPoison", nullptr,
|
||||||
|
isHardcore ? L"HalfPoisonHardcore" : L"HalfPoison");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_healthIcon[icon].PlayVisualRange(L"Half",nullptr,L"Half");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"HalfHardcore" : L"Half", nullptr,
|
||||||
|
isHardcore ? L"HalfHardcore" : L"Half");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Empty
|
// Empty
|
||||||
m_healthIcon[icon].PlayVisualRange(L"Normal",nullptr,L"Normal");
|
m_healthIcon[icon].PlayVisualRange(
|
||||||
|
isHardcore ? L"NormalHardcore" : L"Normal", nullptr,
|
||||||
|
isHardcore ? L"NormalHardcore" : L"Normal");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "..\Minecraft.World\net.minecraft.h"
|
#include "..\Minecraft.World\net.minecraft.h"
|
||||||
#include "..\Minecraft.World\StringHelpers.h"
|
#include "..\Minecraft.World\StringHelpers.h"
|
||||||
#include "..\Minecraft.World\Random.h"
|
#include "..\Minecraft.World\Random.h"
|
||||||
|
#include "..\Minecraft.World\ArabicShaping.h"
|
||||||
|
|
||||||
Font::Font(Options *options, const wstring& name, Textures* textures, bool enforceUnicode, ResourceLocation *textureLocation, int cols, int rows, int charWidth, int charHeight, unsigned short charMap[]/* = nullptr */) : textures(textures)
|
Font::Font(Options *options, const wstring& name, Textures* textures, bool enforceUnicode, ResourceLocation *textureLocation, int cols, int rows, int charWidth, int charHeight, unsigned short charMap[]/* = nullptr */) : textures(textures)
|
||||||
{
|
{
|
||||||
@@ -16,7 +17,7 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
|
|||||||
charWidths = new int[charC];
|
charWidths = new int[charC];
|
||||||
|
|
||||||
// 4J - added initialisers
|
// 4J - added initialisers
|
||||||
memset(charWidths, 0, charC);
|
memset(charWidths, 0, charC * sizeof(int));
|
||||||
|
|
||||||
enforceUnicodeSheet = false;
|
enforceUnicodeSheet = false;
|
||||||
bidirectional = false;
|
bidirectional = false;
|
||||||
@@ -26,6 +27,19 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
|
|||||||
m_underline = false;
|
m_underline = false;
|
||||||
m_strikethrough = false;
|
m_strikethrough = false;
|
||||||
|
|
||||||
|
memset(unicodeTexID, 0, sizeof(unicodeTexID));
|
||||||
|
memset(unicodeWidth, 0, sizeof(unicodeWidth));
|
||||||
|
lastBoundTexture = 0;
|
||||||
|
|
||||||
|
// Load unicode glyph sizes
|
||||||
|
FILE *glyphFile = nullptr;
|
||||||
|
fopen_s(&glyphFile, "Common/res/1_2_2/font/glyph_sizes.bin", "rb");
|
||||||
|
if (glyphFile)
|
||||||
|
{
|
||||||
|
fread(unicodeWidth, 1, 65536, glyphFile);
|
||||||
|
fclose(glyphFile);
|
||||||
|
}
|
||||||
|
|
||||||
// Set up member variables
|
// Set up member variables
|
||||||
m_cols = cols;
|
m_cols = cols;
|
||||||
m_rows = rows;
|
m_rows = rows;
|
||||||
@@ -261,7 +275,87 @@ void Font::drawLiteral(const wstring& str, int x, int y, int color)
|
|||||||
yPos = static_cast<float>(y);
|
yPos = static_cast<float>(y);
|
||||||
wstring cleanStr = sanitize(str);
|
wstring cleanStr = sanitize(str);
|
||||||
for (size_t i = 0; i < cleanStr.length(); ++i)
|
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||||
renderCharacter(cleanStr.at(i));
|
{
|
||||||
|
wchar_t c = cleanStr.at(i);
|
||||||
|
if (isUnicodeGlyphChar(c))
|
||||||
|
{
|
||||||
|
renderUnicodeCharacter(c);
|
||||||
|
textures->bindTexture(m_textureLocation);
|
||||||
|
lastBoundTexture = fontTexture;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
renderCharacter(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like sanitize() but skips the shapeArabicText() call - for pre-shaped strings.
|
||||||
|
wstring Font::sanitizePreshaped(const wstring& str)
|
||||||
|
{
|
||||||
|
wstring sb = str;
|
||||||
|
for (unsigned int i = 0; i < sb.length(); i++)
|
||||||
|
{
|
||||||
|
if (CharacterExists(sb[i]))
|
||||||
|
sb[i] = MapCharacter(sb[i]);
|
||||||
|
else if (unicodeWidth[sb[i]] != 0)
|
||||||
|
{
|
||||||
|
// Leave as-is: raw codepoint for glyph page rendering
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::drawLiteralPreshaped(const wstring& str, int x, int y, int color)
|
||||||
|
{
|
||||||
|
if (str.empty()) return;
|
||||||
|
if ((color & 0xFC000000) == 0) color |= 0xFF000000;
|
||||||
|
textures->bindTexture(m_textureLocation);
|
||||||
|
glColor4f((color >> 16 & 255) / 255.0F, (color >> 8 & 255) / 255.0F, (color & 255) / 255.0F, (color >> 24 & 255) / 255.0F);
|
||||||
|
xPos = static_cast<float>(x);
|
||||||
|
yPos = static_cast<float>(y);
|
||||||
|
wstring cleanStr = sanitizePreshaped(str);
|
||||||
|
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||||
|
{
|
||||||
|
wchar_t c = cleanStr.at(i);
|
||||||
|
if (isUnicodeGlyphChar(c))
|
||||||
|
{
|
||||||
|
renderUnicodeCharacter(c);
|
||||||
|
textures->bindTexture(m_textureLocation);
|
||||||
|
lastBoundTexture = fontTexture;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
renderCharacter(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::drawShadowLiteralPreshaped(const wstring& str, int x, int y, int color)
|
||||||
|
{
|
||||||
|
int shadowColor = (color & 0xFCFCFC) >> 2 | (color & 0xFF000000);
|
||||||
|
drawLiteralPreshaped(str, x + 1, y + 1, shadowColor);
|
||||||
|
drawLiteralPreshaped(str, x, y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Font::widthPreshaped(const wstring& str)
|
||||||
|
{
|
||||||
|
wstring cleanStr = sanitizePreshaped(str);
|
||||||
|
if (cleanStr.empty()) return 0;
|
||||||
|
int len = 0;
|
||||||
|
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||||
|
{
|
||||||
|
wchar_t wc = cleanStr.at(i);
|
||||||
|
if (isUnicodeGlyphChar(wc))
|
||||||
|
len += (int)unicodeCharWidth(wc);
|
||||||
|
else
|
||||||
|
len += charWidths[static_cast<unsigned>(wc)];
|
||||||
|
}
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::drawShadowWordWrap(const wstring &str, int x, int y, int w, int color, int h)
|
void Font::drawShadowWordWrap(const wstring &str, int x, int y, int w, int color, int h)
|
||||||
@@ -345,7 +439,7 @@ void Font::draw(const wstring &str, bool dropShadow)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "noise" for crazy splash screen message
|
// "noise" for crazy splash screen message
|
||||||
if (noise)
|
if (noise && !isUnicodeGlyphChar(c))
|
||||||
{
|
{
|
||||||
int newc;
|
int newc;
|
||||||
do
|
do
|
||||||
@@ -355,7 +449,18 @@ void Font::draw(const wstring &str, bool dropShadow)
|
|||||||
c = newc;
|
c = newc;
|
||||||
}
|
}
|
||||||
|
|
||||||
addCharacterQuad(c);
|
if (isUnicodeGlyphChar(c))
|
||||||
|
{
|
||||||
|
t->end();
|
||||||
|
renderUnicodeCharacter(c);
|
||||||
|
textures->bindTexture(m_textureLocation);
|
||||||
|
lastBoundTexture = fontTexture;
|
||||||
|
t->begin();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addCharacterQuad(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t->end();
|
t->end();
|
||||||
@@ -396,11 +501,22 @@ int Font::width(const wstring& str)
|
|||||||
++i;
|
++i;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
len += charWidths[167];
|
if (isUnicodeGlyphChar(167))
|
||||||
|
len += (int)unicodeCharWidth(167);
|
||||||
|
else
|
||||||
|
len += charWidths[167];
|
||||||
if (i + 1 < cleanStr.length())
|
if (i + 1 < cleanStr.length())
|
||||||
len += charWidths[static_cast<unsigned>(cleanStr[++i])];
|
{
|
||||||
|
wchar_t nextC = cleanStr[++i];
|
||||||
|
if (isUnicodeGlyphChar(nextC))
|
||||||
|
len += (int)unicodeCharWidth(nextC);
|
||||||
|
else if (static_cast<unsigned>(nextC) < static_cast<unsigned>(m_cols * m_rows))
|
||||||
|
len += charWidths[static_cast<unsigned>(nextC)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (isUnicodeGlyphChar(c))
|
||||||
|
len += (int)unicodeCharWidth(c);
|
||||||
else
|
else
|
||||||
len += charWidths[c];
|
len += charWidths[c];
|
||||||
}
|
}
|
||||||
@@ -414,13 +530,19 @@ int Font::widthLiteral(const wstring& str)
|
|||||||
if (cleanStr == L"") return 0;
|
if (cleanStr == L"") return 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
for (size_t i = 0; i < cleanStr.length(); ++i)
|
for (size_t i = 0; i < cleanStr.length(); ++i)
|
||||||
len += charWidths[static_cast<unsigned>(cleanStr.at(i))];
|
{
|
||||||
|
wchar_t wc = cleanStr.at(i);
|
||||||
|
if (isUnicodeGlyphChar(wc))
|
||||||
|
len += (int)unicodeCharWidth(wc);
|
||||||
|
else
|
||||||
|
len += charWidths[static_cast<unsigned>(wc)];
|
||||||
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring Font::sanitize(const wstring& str)
|
wstring Font::sanitize(const wstring& str)
|
||||||
{
|
{
|
||||||
wstring sb = str;
|
wstring sb = shapeArabicText(str);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < sb.length(); i++)
|
for (unsigned int i = 0; i < sb.length(); i++)
|
||||||
{
|
{
|
||||||
@@ -428,6 +550,10 @@ wstring Font::sanitize(const wstring& str)
|
|||||||
{
|
{
|
||||||
sb[i] = MapCharacter(sb[i]);
|
sb[i] = MapCharacter(sb[i]);
|
||||||
}
|
}
|
||||||
|
else if (unicodeWidth[sb[i]] != 0)
|
||||||
|
{
|
||||||
|
// Leave as-is: raw codepoint for glyph page rendering
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If this character isn't supported, just show the first character (empty square box character)
|
// If this character isn't supported, just show the first character (empty square box character)
|
||||||
@@ -671,33 +797,22 @@ void Font::renderFakeCB(IntBuffer *ib)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void Font::loadUnicodePage(int page)
|
void Font::loadUnicodePage(int page)
|
||||||
{
|
{
|
||||||
wchar_t fileName[25];
|
wchar_t fileName[40];
|
||||||
//String fileName = String.format("/1_2_2/font/glyph_%02X.png", page);
|
swprintf(fileName, 40, L"/1_2_2/font/glyph_%02X.png", page);
|
||||||
swprintf(fileName,25,L"/1_2_2/font/glyph_%02X.png",page);
|
|
||||||
BufferedImage *image = new BufferedImage(fileName);
|
BufferedImage *image = new BufferedImage(fileName);
|
||||||
//try
|
|
||||||
//{
|
|
||||||
// image = ImageIO.read(Textures.class.getResourceAsStream(fileName.toString()));
|
|
||||||
//}
|
|
||||||
//catch (IOException e)
|
|
||||||
//{
|
|
||||||
// throw new RuntimeException(e);
|
|
||||||
//}
|
|
||||||
|
|
||||||
unicodeTexID[page] = textures->getTexture(image);
|
unicodeTexID[page] = textures->getTexture(image);
|
||||||
lastBoundTexture = unicodeTexID[page];
|
lastBoundTexture = unicodeTexID[page];
|
||||||
|
delete image;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::renderUnicodeCharacter(wchar_t c)
|
void Font::renderUnicodeCharacter(wchar_t c)
|
||||||
{
|
{
|
||||||
if (unicodeWidth[c] == 0)
|
if (unicodeWidth[c] == 0)
|
||||||
{
|
|
||||||
// System.out.println("no-width char " + c);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
int page = c / 256;
|
int page = c / 256;
|
||||||
|
|
||||||
@@ -709,19 +824,17 @@ void Font::renderUnicodeCharacter(wchar_t c)
|
|||||||
lastBoundTexture = unicodeTexID[page];
|
lastBoundTexture = unicodeTexID[page];
|
||||||
}
|
}
|
||||||
|
|
||||||
// first column with non-trans pixels
|
|
||||||
int firstLeft = unicodeWidth[c] >> 4;
|
int firstLeft = unicodeWidth[c] >> 4;
|
||||||
// last column with non-trans pixels
|
|
||||||
int firstRight = unicodeWidth[c] & 0xF;
|
int firstRight = unicodeWidth[c] & 0xF;
|
||||||
|
|
||||||
float left = firstLeft;
|
float left = (float)firstLeft;
|
||||||
float right = firstRight + 1;
|
float right = (float)(firstRight + 1);
|
||||||
|
|
||||||
float xOff = c % 16 * 16 + left;
|
float xOff = (c % 16) * 16 + left;
|
||||||
float yOff = (c & 0xFF) / 16 * 16;
|
float yOff = ((c & 0xFF) / 16) * 16;
|
||||||
float width = right - left - .02f;
|
float width = right - left - .02f;
|
||||||
|
|
||||||
Tesselator *t = Tesselator::getInstance();
|
Tesselator *t = Tesselator::getInstance();
|
||||||
t->begin(GL_TRIANGLE_STRIP);
|
t->begin(GL_TRIANGLE_STRIP);
|
||||||
t->tex(xOff / 256.0F, yOff / 256.0F);
|
t->tex(xOff / 256.0F, yOff / 256.0F);
|
||||||
t->vertex(xPos, yPos, 0.0f);
|
t->vertex(xPos, yPos, 0.0f);
|
||||||
@@ -735,5 +848,17 @@ void Font::renderUnicodeCharacter(wchar_t c)
|
|||||||
|
|
||||||
xPos += (right - left) / 2 + 1;
|
xPos += (right - left) / 2 + 1;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
float Font::unicodeCharWidth(wchar_t c)
|
||||||
|
{
|
||||||
|
if (unicodeWidth[c] == 0) return 0;
|
||||||
|
int firstLeft = unicodeWidth[c] >> 4;
|
||||||
|
int firstRight = unicodeWidth[c] & 0xF;
|
||||||
|
return (firstRight + 1 - firstLeft) / 2.0f + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Font::isUnicodeGlyphChar(wchar_t c)
|
||||||
|
{
|
||||||
|
return c >= m_cols * m_rows && unicodeWidth[c] != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ private:
|
|||||||
|
|
||||||
Textures *textures;
|
Textures *textures;
|
||||||
|
|
||||||
|
int unicodeTexID[256];
|
||||||
|
unsigned char unicodeWidth[65536];
|
||||||
|
int lastBoundTexture;
|
||||||
|
|
||||||
float xPos;
|
float xPos;
|
||||||
float yPos;
|
float yPos;
|
||||||
|
|
||||||
@@ -70,10 +74,18 @@ private:
|
|||||||
void drawLiteral(const wstring& str, int x, int y, int color); // no § parsing
|
void drawLiteral(const wstring& str, int x, int y, int color); // no § parsing
|
||||||
int MapCharacter(wchar_t c); // 4J added
|
int MapCharacter(wchar_t c); // 4J added
|
||||||
bool CharacterExists(wchar_t c); // 4J added
|
bool CharacterExists(wchar_t c); // 4J added
|
||||||
|
void loadUnicodePage(int page);
|
||||||
|
void renderUnicodeCharacter(wchar_t c);
|
||||||
|
float unicodeCharWidth(wchar_t c);
|
||||||
|
bool isUnicodeGlyphChar(wchar_t c);
|
||||||
|
wstring sanitizePreshaped(const wstring& str); // sanitize without re-shaping Arabic
|
||||||
|
void drawLiteralPreshaped(const wstring& str, int x, int y, int color);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int width(const wstring& str);
|
int width(const wstring& str);
|
||||||
int widthLiteral(const wstring& str); // width without skipping § codes (for chat input)
|
int widthLiteral(const wstring& str); // width without skipping § codes (for chat input)
|
||||||
|
int widthPreshaped(const wstring& str); // width of already-shaped text, no re-shaping
|
||||||
|
void drawShadowLiteralPreshaped(const wstring& str, int x, int y, int color);
|
||||||
wstring sanitize(const wstring& str);
|
wstring sanitize(const wstring& str);
|
||||||
void drawWordWrap(const wstring &string, int x, int y, int w, int col, int h); // 4J Added h param
|
void drawWordWrap(const wstring &string, int x, int y, int w, int col, int h); // 4J Added h param
|
||||||
|
|
||||||
|
|||||||
@@ -359,14 +359,17 @@ void GameRenderer::pick(float a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toru - wrapping these methods for backwards compatibility,
|
||||||
|
// no longer setting m_fov as its use doesn't respect applyEffects param in GameRenderer::getFov
|
||||||
void GameRenderer::SetFovVal(float fov)
|
void GameRenderer::SetFovVal(float fov)
|
||||||
{
|
{
|
||||||
m_fov=fov;
|
//m_fov=fov;
|
||||||
|
mc->options->set(Options::Option::FOV, (fov - 70) / 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
float GameRenderer::GetFovVal()
|
float GameRenderer::GetFovVal()
|
||||||
{
|
{
|
||||||
return m_fov;
|
return 70 + mc->options->fov * 40;//m_fov;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::tickFov()
|
void GameRenderer::tickFov()
|
||||||
@@ -390,9 +393,11 @@ float GameRenderer::getFov(float a, bool applyEffects)
|
|||||||
shared_ptr<LocalPlayer> player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
|
shared_ptr<LocalPlayer> player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
|
||||||
int playerIdx = player ? player->GetXboxPad() : 0;
|
int playerIdx = player ? player->GetXboxPad() : 0;
|
||||||
float fov = m_fov;//70;
|
float fov = m_fov;//70;
|
||||||
|
if (fov < 1) fov = 1; // Crash fix
|
||||||
|
|
||||||
if (applyEffects)
|
if (applyEffects)
|
||||||
{
|
{
|
||||||
//fov += mc->options->fov * 40;
|
fov += mc->options->fov * 40;
|
||||||
fov *= oFov[playerIdx] + (this->fov[playerIdx] - oFov[playerIdx]) * a;
|
fov *= oFov[playerIdx] + (this->fov[playerIdx] - oFov[playerIdx]) * a;
|
||||||
}
|
}
|
||||||
if (player->getHealth() <= 0)
|
if (player->getHealth() <= 0)
|
||||||
|
|||||||
@@ -499,11 +499,10 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
|||||||
|
|
||||||
int y0 = 0;
|
int y0 = 0;
|
||||||
|
|
||||||
// No hardcore on console
|
//if (minecraft->level->getLevelData()->isHardcore())
|
||||||
/*if (minecraft->level.getLevelData().isHardcore())
|
//{
|
||||||
{
|
// y0 = 5;
|
||||||
y0 = 5;
|
//}
|
||||||
}*/
|
|
||||||
|
|
||||||
blit(xo, yo, 16 + bg * 9, 9 * y0, 9, 9);
|
blit(xo, yo, 16 + bg * 9, 9 * y0, 9, 9);
|
||||||
if (blink)
|
if (blink)
|
||||||
@@ -854,10 +853,11 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
|||||||
// font.draw(str, x + 1, y, 0xffffff);
|
// font.draw(str, x + 1, y, 0xffffff);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
lastTickA = a;
|
lastTickA = a;
|
||||||
// 4J Stu - This is now displayed in a xui scene
|
// 4J Stu - This is now displayed in a xui scene
|
||||||
#if 0
|
#if 0
|
||||||
// Jukebox CD message
|
// Jukebox CD message
|
||||||
if (overlayMessageTime > 0)
|
if (overlayMessageTime > 0)
|
||||||
{
|
{
|
||||||
float t = overlayMessageTime - a;
|
float t = overlayMessageTime - a;
|
||||||
@@ -1065,7 +1065,7 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
|||||||
vector<wstring> lines;
|
vector<wstring> lines;
|
||||||
|
|
||||||
// Only show version/branch for player 0 to avoid cluttering each splitscreen viewport
|
// Only show version/branch for player 0 to avoid cluttering each splitscreen viewport
|
||||||
if (iPad == 0)
|
if (iPad == 0 && ClientConstants::SHOW_VERSION_WATERMARK)
|
||||||
{
|
{
|
||||||
lines.push_back(ClientConstants::VERSION_STRING);
|
lines.push_back(ClientConstants::VERSION_STRING);
|
||||||
lines.push_back(ClientConstants::BRANCH_STRING);
|
lines.push_back(ClientConstants::BRANCH_STRING);
|
||||||
@@ -1386,6 +1386,9 @@ void Gui::clearMessages(int iPad)
|
|||||||
|
|
||||||
void Gui::addMessage(const wstring& _string,int iPad,bool bIsDeathMessage)
|
void Gui::addMessage(const wstring& _string,int iPad,bool bIsDeathMessage)
|
||||||
{
|
{
|
||||||
|
{ char buf[32]; sprintf_s(buf, "[CHAT] Display (pad=%d): ", iPad); OutputDebugStringA(buf); }
|
||||||
|
OutputDebugStringW(_string.c_str());
|
||||||
|
OutputDebugStringA("\n");
|
||||||
wstring string = _string; // 4J - Take copy of input as it is const
|
wstring string = _string; // 4J - Take copy of input as it is const
|
||||||
//int iScale=1;
|
//int iScale=1;
|
||||||
|
|
||||||
@@ -1607,7 +1610,7 @@ void Gui::renderGraph(int dataLength, int dataPos, int64_t *dataA, float dataASc
|
|||||||
|
|
||||||
t->vertex((float)(xScale*i + 0.5f), (float)( height - aVal + 0.5f), static_cast<float>(0));
|
t->vertex((float)(xScale*i + 0.5f), (float)( height - aVal + 0.5f), static_cast<float>(0));
|
||||||
t->vertex((float)(xScale*i + 0.5f), (float)( height + 0.5f), static_cast<float>(0));
|
t->vertex((float)(xScale*i + 0.5f), (float)( height + 0.5f), static_cast<float>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dataB != NULL )
|
if( dataB != NULL )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -110,6 +110,11 @@ void GuiComponent::drawStringLiteral(Font *font, const wstring& str, int x, int
|
|||||||
font->drawShadowLiteral(str, x, y, color);
|
font->drawShadowLiteral(str, x, y, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GuiComponent::drawStringPreshaped(Font *font, const wstring& str, int x, int y, int color)
|
||||||
|
{
|
||||||
|
font->drawShadowLiteralPreshaped(str, x, y, color);
|
||||||
|
}
|
||||||
|
|
||||||
void GuiComponent::blit(int x, int y, int sx, int sy, int w, int h)
|
void GuiComponent::blit(int x, int y, int sx, int sy, int w, int h)
|
||||||
{
|
{
|
||||||
float us = 1 / 256.0f;
|
float us = 1 / 256.0f;
|
||||||
|
|||||||
@@ -16,5 +16,6 @@ public:
|
|||||||
void drawCenteredString(Font *font, const wstring& str, int x, int y, int color);
|
void drawCenteredString(Font *font, const wstring& str, int x, int y, int color);
|
||||||
void drawString(Font *font, const wstring& str, int x, int y, int color);
|
void drawString(Font *font, const wstring& str, int x, int y, int color);
|
||||||
void drawStringLiteral(Font* font, const wstring& str, int x, int y, int color);
|
void drawStringLiteral(Font* font, const wstring& str, int x, int y, int color);
|
||||||
|
void drawStringPreshaped(Font* font, const wstring& str, int x, int y, int color);
|
||||||
void blit(int x, int y, int sx, int sy, int w, int h);
|
void blit(int x, int y, int sx, int sy, int w, int h);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6894,6 +6894,22 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Common\UI\UIUnicodeBitmapFont.h">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Common\UI\UIComponent_Chat.h">
|
<ClInclude Include="Common\UI\UIComponent_Chat.h">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||||
@@ -29623,6 +29639,22 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Common\UI\UIUnicodeBitmapFont.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_NO_TU|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|PSVita'">false</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="Common\UI\UIComponent_Chat.cpp">
|
<ClCompile Include="Common\UI\UIComponent_Chat.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||||
|
|||||||
@@ -2953,6 +2953,9 @@
|
|||||||
<ClInclude Include="Common\UI\UIBitmapFont.h">
|
<ClInclude Include="Common\UI\UIBitmapFont.h">
|
||||||
<Filter>Common\Source Files\UI</Filter>
|
<Filter>Common\Source Files\UI</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Common\UI\UIUnicodeBitmapFont.h">
|
||||||
|
<Filter>Common\Source Files\UI</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Common\UI\UITTFFont.h">
|
<ClInclude Include="Common\UI\UITTFFont.h">
|
||||||
<Filter>Common\Source Files\UI</Filter>
|
<Filter>Common\Source Files\UI</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -5199,6 +5202,9 @@
|
|||||||
<ClCompile Include="Common\UI\UIBitmapFont.cpp">
|
<ClCompile Include="Common\UI\UIBitmapFont.cpp">
|
||||||
<Filter>Common\Source Files\UI</Filter>
|
<Filter>Common\Source Files\UI</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Common\UI\UIUnicodeBitmapFont.cpp">
|
||||||
|
<Filter>Common\Source Files\UI</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="Common\UI\UITTFFont.cpp">
|
<ClCompile Include="Common\UI\UITTFFont.cpp">
|
||||||
<Filter>Common\Source Files\UI</Filter>
|
<Filter>Common\Source Files\UI</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "1"
|
|
||||||
"EXCLUDED_FILE0" = "Durango\\Autogenerated.appxmanifest"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -73,6 +73,11 @@
|
|||||||
#include "Common\UI\UIFontData.h"
|
#include "Common\UI\UIFontData.h"
|
||||||
#include "DLCTexturePack.h"
|
#include "DLCTexturePack.h"
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#include "Windows64/stb_image_write.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __ORBIS__
|
#ifdef __ORBIS__
|
||||||
#include "Orbis\Network\PsPlusUpsellWrapper_Orbis.h"
|
#include "Orbis\Network\PsPlusUpsellWrapper_Orbis.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -1549,6 +1554,9 @@ void Minecraft::run_middle()
|
|||||||
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_RENDER_DEBUG;
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_RENDER_DEBUG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_SCREENSHOT))
|
||||||
|
localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_SCREENSHOT;
|
||||||
|
|
||||||
// In flying mode, Shift held = sneak/descend
|
// In flying mode, Shift held = sneak/descend
|
||||||
if(g_KBMInput.IsKBMActive() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SNEAK))
|
if(g_KBMInput.IsKBMActive() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SNEAK))
|
||||||
{
|
{
|
||||||
@@ -3737,6 +3745,80 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
|||||||
//options->thirdPersonView = !options->thirdPersonView;
|
//options->thirdPersonView = !options->thirdPersonView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if(player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SCREENSHOT))
|
||||||
|
{
|
||||||
|
extern ID3D11Device* g_pd3dDevice;
|
||||||
|
extern ID3D11DeviceContext* g_pImmediateContext;
|
||||||
|
extern IDXGISwapChain* g_pSwapChain;
|
||||||
|
|
||||||
|
ID3D11Texture2D* pBackBuffer = nullptr;
|
||||||
|
HRESULT hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBuffer);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
pBackBuffer->GetDesc(&desc);
|
||||||
|
desc.Usage = D3D11_USAGE_STAGING;
|
||||||
|
desc.BindFlags = 0;
|
||||||
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||||
|
desc.MiscFlags = 0;
|
||||||
|
|
||||||
|
ID3D11Texture2D* pStaging = nullptr;
|
||||||
|
hr = g_pd3dDevice->CreateTexture2D(&desc, nullptr, &pStaging);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
g_pImmediateContext->CopyResource(pStaging, pBackBuffer);
|
||||||
|
|
||||||
|
// Build path next to the executable
|
||||||
|
wchar_t exePath[MAX_PATH];
|
||||||
|
GetModuleFileNameW(NULL, exePath, MAX_PATH);
|
||||||
|
wchar_t* lastSlash = wcsrchr(exePath, L'\\');
|
||||||
|
if (lastSlash) *(lastSlash + 1) = L'\0';
|
||||||
|
wstring screenshotDirPath = wstring(exePath) + L"screenshots";
|
||||||
|
CreateDirectoryW(screenshotDirPath.c_str(), NULL);
|
||||||
|
|
||||||
|
SYSTEMTIME st;
|
||||||
|
GetLocalTime(&st);
|
||||||
|
wchar_t filename[128];
|
||||||
|
swprintf_s(filename, L"%04d-%02d-%02d_%02d.%02d.%02d.png",
|
||||||
|
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
|
||||||
|
wstring screenshotPath = screenshotDirPath + L"\\" + filename;
|
||||||
|
|
||||||
|
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||||
|
hr = g_pImmediateContext->Map(pStaging, 0, D3D11_MAP_READ, 0, &mapped);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Copy rows and force alpha to fully opaque
|
||||||
|
unsigned char* rgba = new unsigned char[desc.Width * desc.Height * 4];
|
||||||
|
for (UINT row = 0; row < desc.Height; row++)
|
||||||
|
{
|
||||||
|
unsigned char* src = (unsigned char*)mapped.pData + row * mapped.RowPitch;
|
||||||
|
unsigned char* dst = rgba + row * desc.Width * 4;
|
||||||
|
memcpy(dst, src, desc.Width * 4);
|
||||||
|
for (UINT x = 0; x < desc.Width; x++)
|
||||||
|
dst[x * 4 + 3] = 0xFF;
|
||||||
|
}
|
||||||
|
g_pImmediateContext->Unmap(pStaging, 0);
|
||||||
|
|
||||||
|
// Save PNG via stb_image_write
|
||||||
|
string narrowPath(screenshotPath.begin(), screenshotPath.end());
|
||||||
|
int writeResult = stbi_write_png(narrowPath.c_str(), desc.Width, desc.Height, 4, rgba, desc.Width * 4);
|
||||||
|
delete[] rgba;
|
||||||
|
|
||||||
|
// Send local-only chat message on success
|
||||||
|
if (writeResult)
|
||||||
|
{
|
||||||
|
wstring msg = L"Saved screenshot to " + wstring(filename);
|
||||||
|
gui->addMessage(msg, iPad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pStaging->Release();
|
||||||
|
}
|
||||||
|
pBackBuffer->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_GAME_INFO)) && gameMode->isInputAllowed(MINECRAFT_ACTION_GAME_INFO))
|
if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_GAME_INFO)) && gameMode->isInputAllowed(MINECRAFT_ACTION_GAME_INFO))
|
||||||
{
|
{
|
||||||
ui.NavigateToScene(iPad,eUIScene_InGameInfoMenu);
|
ui.NavigateToScene(iPad,eUIScene_InGameInfoMenu);
|
||||||
|
|||||||
@@ -561,6 +561,7 @@ MinecraftServer::MinecraftServer()
|
|||||||
m_serverPausedEvent = new C4JThread::Event;
|
m_serverPausedEvent = new C4JThread::Event;
|
||||||
|
|
||||||
m_saveOnExit = false;
|
m_saveOnExit = false;
|
||||||
|
m_deleteWorldOnExit = false;
|
||||||
m_suspending = false;
|
m_suspending = false;
|
||||||
|
|
||||||
m_ugcPlayersVersion = 0;
|
m_ugcPlayersVersion = 0;
|
||||||
@@ -887,6 +888,15 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
|
|||||||
// }
|
// }
|
||||||
ProgressRenderer *mcprogress = Minecraft::GetInstance()->progressRenderer;
|
ProgressRenderer *mcprogress = Minecraft::GetInstance()->progressRenderer;
|
||||||
|
|
||||||
|
// 4J Added - store save folder name for potential hardcore world deletion
|
||||||
|
{
|
||||||
|
char szSaveFolder[MAX_SAVEFILENAME_LENGTH] = {};
|
||||||
|
StorageManager.GetSaveUniqueFilename(szSaveFolder);
|
||||||
|
wchar_t wSaveFolder[MAX_SAVEFILENAME_LENGTH] = {};
|
||||||
|
mbstowcs(wSaveFolder, szSaveFolder, MAX_SAVEFILENAME_LENGTH - 1);
|
||||||
|
m_saveFolderName = wSaveFolder;
|
||||||
|
}
|
||||||
|
|
||||||
// 4J TODO - free levels here if there are already some?
|
// 4J TODO - free levels here if there are already some?
|
||||||
levels = ServerLevelArray(3);
|
levels = ServerLevelArray(3);
|
||||||
|
|
||||||
@@ -997,6 +1007,9 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
|
|||||||
#endif
|
#endif
|
||||||
levels[i]->getLevelData()->setGameType(gameType);
|
levels[i]->getLevelData()->setGameType(gameType);
|
||||||
|
|
||||||
|
// Apply hardcore flag from host option to level data so loaded worlds respect server.properties
|
||||||
|
levels[i]->getLevelData()->setHardcore(isHardcore());
|
||||||
|
|
||||||
if(app.getLevelGenerationOptions() != nullptr)
|
if(app.getLevelGenerationOptions() != nullptr)
|
||||||
{
|
{
|
||||||
LevelGenerationOptions *mapOptions = app.getLevelGenerationOptions();
|
LevelGenerationOptions *mapOptions = app.getLevelGenerationOptions();
|
||||||
@@ -1642,7 +1655,7 @@ bool MinecraftServer::isNetherEnabled()
|
|||||||
|
|
||||||
bool MinecraftServer::isHardcore()
|
bool MinecraftServer::isHardcore()
|
||||||
{
|
{
|
||||||
return false;
|
return app.GetGameHostOption(eGameHostOption_Hardcore) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MinecraftServer::getOperatorUserPermissionLevel()
|
int MinecraftServer::getOperatorUserPermissionLevel()
|
||||||
|
|||||||
@@ -265,6 +265,8 @@ private:
|
|||||||
private:
|
private:
|
||||||
// 4J Added
|
// 4J Added
|
||||||
bool m_saveOnExit;
|
bool m_saveOnExit;
|
||||||
|
bool m_deleteWorldOnExit; // 4J Added - for hardcore mode world deletion
|
||||||
|
wstring m_saveFolderName; // 4J Added - stored for hardcore world deletion
|
||||||
bool m_suspending;
|
bool m_suspending;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -278,6 +280,9 @@ public:
|
|||||||
void chunkPacketManagement_PostTick();
|
void chunkPacketManagement_PostTick();
|
||||||
|
|
||||||
void setSaveOnExit(bool save) { m_saveOnExit = save; s_bSaveOnExitAnswered = true; }
|
void setSaveOnExit(bool save) { m_saveOnExit = save; s_bSaveOnExitAnswered = true; }
|
||||||
|
void setDeleteWorldOnExit(bool del) { m_deleteWorldOnExit = del; }
|
||||||
|
bool getDeleteWorldOnExit() const { return m_deleteWorldOnExit; }
|
||||||
|
const wstring& getSaveFolderName() const { return m_saveFolderName; }
|
||||||
void Suspend();
|
void Suspend();
|
||||||
bool IsSuspending();
|
bool IsSuspending();
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
""
|
|
||||||
{
|
|
||||||
"FILE_VERSION" = "9237"
|
|
||||||
"ENLISTMENT_CHOICE" = "NEVER"
|
|
||||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
|
||||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
|
||||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
|
||||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
|
||||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
|
||||||
}
|
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "..\Minecraft.World\StringHelpers.h"
|
#include "..\Minecraft.World\StringHelpers.h"
|
||||||
#include "..\Minecraft.World\Socket.h"
|
#include "..\Minecraft.World\Socket.h"
|
||||||
#include "..\Minecraft.World\Achievements.h"
|
#include "..\Minecraft.World\Achievements.h"
|
||||||
|
#include "..\Minecraft.World\LevelData.h"
|
||||||
#include "..\Minecraft.World\net.minecraft.h"
|
#include "..\Minecraft.World\net.minecraft.h"
|
||||||
#include "EntityTracker.h"
|
#include "EntityTracker.h"
|
||||||
#include "ServerConnection.h"
|
#include "ServerConnection.h"
|
||||||
@@ -142,6 +143,14 @@ void PlayerConnection::tick()
|
|||||||
{
|
{
|
||||||
dropSpamTickCount--;
|
dropSpamTickCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure server-side player tick runs even when no move packet was received this tick.
|
||||||
|
// Without this, environmental damage (drowning, fire, lava) is never applied to clients
|
||||||
|
// that don't send frequent move packets.
|
||||||
|
if (!didTick && player != nullptr)
|
||||||
|
{
|
||||||
|
player->doTick(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason)
|
void PlayerConnection::disconnect(DisconnectPacket::eDisconnectReason reason)
|
||||||
@@ -1109,22 +1118,12 @@ void PlayerConnection::handleClientCommand(shared_ptr<ClientCommandPacket> packe
|
|||||||
{
|
{
|
||||||
player = server->getPlayers()->respawn(player, player->m_enteredEndExitPortal?0:player->dimension, true);
|
player = server->getPlayers()->respawn(player, player->m_enteredEndExitPortal?0:player->dimension, true);
|
||||||
}
|
}
|
||||||
//else if (player.getLevel().getLevelData().isHardcore())
|
else if (player->level->getLevelData()->isHardcore())
|
||||||
//{
|
{
|
||||||
// if (server.isSingleplayer() && player.name.equals(server.getSingleplayerName()))
|
// Hardcore mode — server rejects respawn. Ban and disconnect are already
|
||||||
// {
|
// handled in ServerPlayer::die() via banPlayerForHardcoreDeath().
|
||||||
// player.connection.disconnect("You have died. Game over, man, it's game over!");
|
return;
|
||||||
// server.selfDestruct();
|
}
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// BanEntry ban = new BanEntry(player.name);
|
|
||||||
// ban.setReason("Death in Hardcore");
|
|
||||||
|
|
||||||
// server.getPlayers().getBans().add(ban);
|
|
||||||
// player.connection.disconnect("You have died. Game over, man, it's game over!");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (player->getHealth() > 0) return;
|
if (player->getHealth() > 0) return;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "ConsoleInputSource.h"
|
#include "ConsoleInputSource.h"
|
||||||
#include "..\Minecraft.World\PacketListener.h"
|
#include "..\Minecraft.World\PacketListener.h"
|
||||||
#include "..\Minecraft.World\JavaIntHash.h"
|
#include "..\Minecraft.World\JavaIntHash.h"
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
class MinecraftServer;
|
class MinecraftServer;
|
||||||
class Connection;
|
class Connection;
|
||||||
@@ -130,8 +131,8 @@ public:
|
|||||||
|
|
||||||
void setShowOnMaps(bool bVal);
|
void setShowOnMaps(bool bVal);
|
||||||
|
|
||||||
void setWasKicked() { m_bWasKicked = true; }
|
void setWasKicked() { m_bWasKicked.store(true); }
|
||||||
bool getWasKicked() { return m_bWasKicked; }
|
bool getWasKicked() { return m_bWasKicked.load(); }
|
||||||
|
|
||||||
// 4J Added
|
// 4J Added
|
||||||
bool hasClientTickedOnce() { return m_bHasClientTickedOnce; }
|
bool hasClientTickedOnce() { return m_bHasClientTickedOnce; }
|
||||||
@@ -140,5 +141,5 @@ private:
|
|||||||
bool m_bCloseOnTick;
|
bool m_bCloseOnTick;
|
||||||
vector<wstring> m_texturesRequested;
|
vector<wstring> m_texturesRequested;
|
||||||
|
|
||||||
bool m_bWasKicked;
|
std::atomic<bool> m_bWasKicked{false};
|
||||||
};
|
};
|
||||||
@@ -39,6 +39,10 @@
|
|||||||
|
|
||||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||||
#include "..\Minecraft.Server\Access\Access.h"
|
#include "..\Minecraft.Server\Access\Access.h"
|
||||||
|
#include "..\Minecraft.Server\Common\StringUtils.h"
|
||||||
|
#include "..\Minecraft.Server\ServerLogger.h"
|
||||||
|
#include "..\Minecraft.Server\ServerLogManager.h"
|
||||||
|
#include "..\Minecraft.Server\ServerProperties.h"
|
||||||
extern bool g_Win64DedicatedServer;
|
extern bool g_Win64DedicatedServer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -67,6 +71,7 @@ PlayerList::PlayerList(MinecraftServer *server)
|
|||||||
int rawMax = server->settings->getInt(L"max-players", 8);
|
int rawMax = server->settings->getInt(L"max-players", 8);
|
||||||
maxPlayers = static_cast<unsigned int>(Mth::clamp(rawMax, 1, MINECRAFT_NET_MAX_PLAYERS));
|
maxPlayers = static_cast<unsigned int>(Mth::clamp(rawMax, 1, MINECRAFT_NET_MAX_PLAYERS));
|
||||||
doWhiteList = false;
|
doWhiteList = false;
|
||||||
|
InitializeCriticalSection(&m_banCS);
|
||||||
InitializeCriticalSection(&m_kickPlayersCS);
|
InitializeCriticalSection(&m_kickPlayersCS);
|
||||||
InitializeCriticalSection(&m_closePlayersCS);
|
InitializeCriticalSection(&m_closePlayersCS);
|
||||||
}
|
}
|
||||||
@@ -80,6 +85,7 @@ PlayerList::~PlayerList()
|
|||||||
player->gameMode = nullptr;
|
player->gameMode = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeleteCriticalSection(&m_banCS);
|
||||||
DeleteCriticalSection(&m_kickPlayersCS);
|
DeleteCriticalSection(&m_kickPlayersCS);
|
||||||
DeleteCriticalSection(&m_closePlayersCS);
|
DeleteCriticalSection(&m_closePlayersCS);
|
||||||
}
|
}
|
||||||
@@ -271,7 +277,8 @@ bool PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer>
|
|||||||
static_cast<BYTE>(playerIndex), level->useNewSeaLevel(),
|
static_cast<BYTE>(playerIndex), level->useNewSeaLevel(),
|
||||||
player->getAllPlayerGamePrivileges(),
|
player->getAllPlayerGamePrivileges(),
|
||||||
level->getLevelData()->getXZSize(),
|
level->getLevelData()->getXZSize(),
|
||||||
level->getLevelData()->getHellScale()));
|
level->getLevelData()->getHellScale(),
|
||||||
|
level->getLevelData()->isHardcore()));
|
||||||
playerConnection->send(std::make_shared<SetSpawnPositionPacket>(spawnPos->x, spawnPos->y, spawnPos->z));
|
playerConnection->send(std::make_shared<SetSpawnPositionPacket>(spawnPos->x, spawnPos->y, spawnPos->z));
|
||||||
playerConnection->send(std::make_shared<PlayerAbilitiesPacket>(&player->abilities));
|
playerConnection->send(std::make_shared<PlayerAbilitiesPacket>(&player->abilities));
|
||||||
playerConnection->send(std::make_shared<SetCarriedItemPacket>(player->inventory->selected));
|
playerConnection->send(std::make_shared<SetCarriedItemPacket>(player->inventory->selected));
|
||||||
@@ -702,6 +709,13 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay
|
|||||||
// necessary)
|
// necessary)
|
||||||
updatePlayerGameMode(player, serverPlayer, level);
|
updatePlayerGameMode(player, serverPlayer, level);
|
||||||
|
|
||||||
|
// 4J Added: Hardcore mode — force Adventure mode on respawn
|
||||||
|
if (server->getLevel(0)->getLevelData()->isHardcore())
|
||||||
|
{
|
||||||
|
player->gameMode->setGameModeForPlayer(GameType::ADVENTURE);
|
||||||
|
player->connection->send(std::make_shared<GameEventPacket>(GameEventPacket::CHANGE_GAME_MODE, GameType::ADVENTURE->getId()));
|
||||||
|
}
|
||||||
|
|
||||||
if(serverPlayer->wonGame && targetDimension == oldDimension && serverPlayer->getHealth() > 0)
|
if(serverPlayer->wonGame && targetDimension == oldDimension && serverPlayer->getHealth() > 0)
|
||||||
{
|
{
|
||||||
// If the player is still alive and respawning to the same dimension, they are just being added back from someone else viewing the Win screen
|
// If the player is still alive and respawning to the same dimension, they are just being added back from someone else viewing the Win screen
|
||||||
@@ -739,7 +753,7 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay
|
|||||||
|
|
||||||
player->connection->send( std::make_shared<RespawnPacket>( static_cast<char>(player->dimension), player->level->getSeed(), player->level->getMaxBuildHeight(),
|
player->connection->send( std::make_shared<RespawnPacket>( static_cast<char>(player->dimension), player->level->getSeed(), player->level->getMaxBuildHeight(),
|
||||||
player->gameMode->getGameModeForPlayer(), level->difficulty, level->getLevelData()->getGenerator(),
|
player->gameMode->getGameModeForPlayer(), level->difficulty, level->getLevelData()->getGenerator(),
|
||||||
player->level->useNewSeaLevel(), player->entityId, level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale() ) );
|
player->level->useNewSeaLevel(), player->entityId, level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale(), level->getLevelData()->isHardcore() ) );
|
||||||
player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot);
|
player->connection->teleport(player->x, player->y, player->z, player->yRot, player->xRot);
|
||||||
player->connection->send( std::make_shared<SetExperiencePacket>( player->experienceProgress, player->totalExperience, player->experienceLevel) );
|
player->connection->send( std::make_shared<SetExperiencePacket>( player->experienceProgress, player->totalExperience, player->experienceLevel) );
|
||||||
|
|
||||||
@@ -856,7 +870,7 @@ void PlayerList::toggleDimension(shared_ptr<ServerPlayer> player, int targetDime
|
|||||||
|
|
||||||
player->connection->send(std::make_shared<RespawnPacket>(static_cast<char>(player->dimension), newLevel->getSeed(), newLevel->getMaxBuildHeight(),
|
player->connection->send(std::make_shared<RespawnPacket>(static_cast<char>(player->dimension), newLevel->getSeed(), newLevel->getMaxBuildHeight(),
|
||||||
player->gameMode->getGameModeForPlayer(), newLevel->difficulty, newLevel->getLevelData()->getGenerator(),
|
player->gameMode->getGameModeForPlayer(), newLevel->difficulty, newLevel->getLevelData()->getGenerator(),
|
||||||
newLevel->useNewSeaLevel(), player->entityId, newLevel->getLevelData()->getXZSize(), newLevel->getLevelData()->getHellScale()));
|
newLevel->useNewSeaLevel(), player->entityId, newLevel->getLevelData()->getXZSize(), newLevel->getLevelData()->getHellScale(), newLevel->getLevelData()->isHardcore()));
|
||||||
|
|
||||||
oldLevel->removeEntityImmediately(player);
|
oldLevel->removeEntityImmediately(player);
|
||||||
player->removed = false;
|
player->removed = false;
|
||||||
@@ -1670,6 +1684,7 @@ bool PlayerList::isXuidBanned(PlayerUID xuid)
|
|||||||
|
|
||||||
bool banned = false;
|
bool banned = false;
|
||||||
|
|
||||||
|
EnterCriticalSection(&m_banCS);
|
||||||
for(PlayerUID it : m_bannedXuids)
|
for(PlayerUID it : m_bannedXuids)
|
||||||
{
|
{
|
||||||
if( ProfileManager.AreXUIDSEqual( xuid, it ) )
|
if( ProfileManager.AreXUIDSEqual( xuid, it ) )
|
||||||
@@ -1678,6 +1693,7 @@ bool PlayerList::isXuidBanned(PlayerUID xuid)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LeaveCriticalSection(&m_banCS);
|
||||||
|
|
||||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||||
if (!banned && g_Win64DedicatedServer)
|
if (!banned && g_Win64DedicatedServer)
|
||||||
@@ -1689,6 +1705,107 @@ bool PlayerList::isXuidBanned(PlayerUID xuid)
|
|||||||
return banned;
|
return banned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerList::banXuid(PlayerUID xuid)
|
||||||
|
{
|
||||||
|
// 4J Added - for hardcore mode ban-on-death
|
||||||
|
// Ban a player's XUID. Used when a player dies in a hardcore multiplayer world.
|
||||||
|
if(xuid == INVALID_XUID) return;
|
||||||
|
|
||||||
|
EnterCriticalSection(&m_banCS);
|
||||||
|
|
||||||
|
// Check if already banned
|
||||||
|
bool alreadyBanned = false;
|
||||||
|
for(PlayerUID it : m_bannedXuids)
|
||||||
|
{
|
||||||
|
if( ProfileManager.AreXUIDSEqual( xuid, it ) )
|
||||||
|
{
|
||||||
|
alreadyBanned = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!alreadyBanned)
|
||||||
|
{
|
||||||
|
m_bannedXuids.push_back(xuid);
|
||||||
|
app.DebugPrintf("PlayerList::banXuid - Player XUID banned for hardcore death\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&m_banCS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerList::banPlayerForHardcoreDeath(ServerPlayer *player)
|
||||||
|
{
|
||||||
|
if (player == nullptr) return;
|
||||||
|
|
||||||
|
// Always apply the in-memory XUID ban (works for both client-hosted and dedicated)
|
||||||
|
banXuid(player->getOnlineXuid());
|
||||||
|
|
||||||
|
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||||
|
if (g_Win64DedicatedServer)
|
||||||
|
{
|
||||||
|
const std::string playerName = ServerRuntime::StringUtils::WideToUtf8(player->getName());
|
||||||
|
|
||||||
|
ServerRuntime::Access::BanMetadata metadata = ServerRuntime::Access::BanManager::BuildDefaultMetadata("Hardcore Death");
|
||||||
|
metadata.reason = "Died in hardcore mode";
|
||||||
|
|
||||||
|
// Ban online XUID
|
||||||
|
ServerRuntime::Access::AddPlayerBan(player->getOnlineXuid(), playerName, metadata);
|
||||||
|
|
||||||
|
// Also ban offline XUID if it differs (follows CliCommandBan pattern)
|
||||||
|
PlayerUID offlineXuid = player->getXuid();
|
||||||
|
if (offlineXuid != INVALID_XUID && offlineXuid != player->getOnlineXuid())
|
||||||
|
{
|
||||||
|
ServerRuntime::Access::AddPlayerBan(offlineXuid, playerName, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ban the player's IP address (uses same access path as CliCommandBanIp)
|
||||||
|
auto serverConfig = ServerRuntime::LoadServerPropertiesConfig();
|
||||||
|
if (serverConfig.hardcoreBanIp)
|
||||||
|
{
|
||||||
|
if (player->connection != nullptr && player->connection->connection != nullptr && player->connection->connection->getSocket() != nullptr)
|
||||||
|
{
|
||||||
|
const unsigned char smallId = player->connection->connection->getSocket()->getSmallId();
|
||||||
|
std::string ip;
|
||||||
|
if (smallId != 0 && ServerRuntime::ServerLogManager::TryGetConnectionRemoteIp(smallId, &ip))
|
||||||
|
{
|
||||||
|
ServerRuntime::Access::AddIpBan(ip, metadata);
|
||||||
|
ServerRuntime::LogInfof("Hardcore", "Player %s banned (XUID + IP %s) for dying in hardcore mode.", playerName.c_str(), ip.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerRuntime::LogInfof("Hardcore", "Player %s banned (XUID only, IP not available) for dying in hardcore mode.", playerName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerRuntime::LogInfof("Hardcore", "Player %s banned (XUID only, no connection) for dying in hardcore mode.", playerName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServerRuntime::LogInfof("Hardcore", "Player %s banned (XUID only, IP ban disabled) for dying in hardcore mode.", playerName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send ban reason then defer the actual close to the next tick, because this
|
||||||
|
// method runs mid-tick inside ServerPlayer::die(). A synchronous disconnect
|
||||||
|
// can invalidate the player/connection while the tick is still executing.
|
||||||
|
if (player->connection != nullptr)
|
||||||
|
{
|
||||||
|
player->connection->send(std::make_shared<DisconnectPacket>(DisconnectPacket::eDisconnect_Banned));
|
||||||
|
player->connection->closeOnTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// Client-hosted: force-save so the host cannot circumvent death by quitting without saving.
|
||||||
|
// On dedicated server the autosave handles persistence, so skip the forced save to avoid
|
||||||
|
// the client getting stuck on a "host is saving" screen during disconnect.
|
||||||
|
app.SetXuiServerAction(ProfileManager.GetPrimaryPad(), eXuiServerAction_SaveGame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AP added for Vita so the range can be increased once the level starts
|
// AP added for Vita so the range can be increased once the level starts
|
||||||
void PlayerList::setViewDistance(int newViewDistance)
|
void PlayerList::setViewDistance(int newViewDistance)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ private:
|
|||||||
|
|
||||||
// 4J Added
|
// 4J Added
|
||||||
vector<PlayerUID> m_bannedXuids;
|
vector<PlayerUID> m_bannedXuids;
|
||||||
|
CRITICAL_SECTION m_banCS; // 4J Added - protects m_bannedXuids for concurrent access
|
||||||
deque<BYTE> m_smallIdsToKick;
|
deque<BYTE> m_smallIdsToKick;
|
||||||
CRITICAL_SECTION m_kickPlayersCS;
|
CRITICAL_SECTION m_kickPlayersCS;
|
||||||
deque<BYTE> m_smallIdsToClose;
|
deque<BYTE> m_smallIdsToClose;
|
||||||
@@ -135,6 +136,8 @@ public:
|
|||||||
void closePlayerConnectionBySmallId(BYTE networkSmallId);
|
void closePlayerConnectionBySmallId(BYTE networkSmallId);
|
||||||
void queueSmallIdForRecycle(BYTE smallId);
|
void queueSmallIdForRecycle(BYTE smallId);
|
||||||
bool isXuidBanned(PlayerUID xuid);
|
bool isXuidBanned(PlayerUID xuid);
|
||||||
|
void banXuid(PlayerUID xuid); // 4J Added - for hardcore mode ban-on-death
|
||||||
|
void banPlayerForHardcoreDeath(ServerPlayer *player); // Persistent XUID + IP ban on hardcore death
|
||||||
// AP added for Vita so the range can be increased once the level starts
|
// AP added for Vita so the range can be increased once the level starts
|
||||||
void setViewDistance(int newViewDistance);
|
void setViewDistance(int newViewDistance);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -303,6 +303,12 @@ void SelectWorldScreen::WorldSelectionList::renderItem(int i, int x, int y, int
|
|||||||
info = parent->conversionLang + L" " + info;
|
info = parent->conversionLang + L" " + info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4J Added: Show [Hardcore] badge for hardcore worlds
|
||||||
|
if (levelSummary->isHardcore())
|
||||||
|
{
|
||||||
|
name = name + L" [Hardcore]";
|
||||||
|
}
|
||||||
|
|
||||||
parent->drawString(parent->font, name, x + 2, y + 1, 0xffffff);
|
parent->drawString(parent->font, name, x + 2, y + 1, 0xffffff);
|
||||||
parent->drawString(parent->font, id, x + 2, y + 12, 0x808080);
|
parent->drawString(parent->font, id, x + 2, y + 12, 0x808080);
|
||||||
parent->drawString(parent->font, info, x + 2, y + 12 + 10, 0x808080);
|
parent->drawString(parent->font, info, x + 2, y + 12 + 10, 0x808080);
|
||||||
|
|||||||
@@ -569,6 +569,17 @@ void ServerPlayer::die(DamageSource *source)
|
|||||||
{
|
{
|
||||||
server->getPlayers()->broadcastAll(getCombatTracker()->getDeathMessagePacket());
|
server->getPlayers()->broadcastAll(getCombatTracker()->getDeathMessagePacket());
|
||||||
|
|
||||||
|
// 4J Added: Hardcore mode — switch to Adventure mode on death (can look but not break/place blocks)
|
||||||
|
if (level->getLevelData()->isHardcore())
|
||||||
|
{
|
||||||
|
setGameMode(GameType::ADVENTURE);
|
||||||
|
|
||||||
|
// Ban this player's XUID and queue disconnect.
|
||||||
|
// The force-save is triggered inside banPlayerForHardcoreDeath after the
|
||||||
|
// disconnect is queued, so the client doesn't get stuck on a save screen.
|
||||||
|
server->getPlayers()->banPlayerForHardcoreDeath(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (!level->getGameRules()->getBoolean(GameRules::RULE_KEEPINVENTORY))
|
if (!level->getGameRules()->getBoolean(GameRules::RULE_KEEPINVENTORY))
|
||||||
{
|
{
|
||||||
inventory->dropAll();
|
inventory->dropAll();
|
||||||
@@ -1609,9 +1620,9 @@ bool ServerPlayer::hasPermission(EGameCommand command)
|
|||||||
//
|
//
|
||||||
// // 4J - Don't need
|
// // 4J - Don't need
|
||||||
// //if (server.isSingleplayer() && server.getSingleplayerName().equals(name))
|
// //if (server.isSingleplayer() && server.getSingleplayerName().equals(name))
|
||||||
// //{
|
/// //{
|
||||||
// // server.setDifficulty(packet.getDifficulty());
|
// // server.setDifficulty(packet.getDifficulty());
|
||||||
// //}
|
/// //}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
int ServerPlayer::getViewDistance()
|
int ServerPlayer::getViewDistance()
|
||||||
|
|||||||
@@ -34,10 +34,8 @@ public:
|
|||||||
static const int KEY_DEBUG_MENU = VK_F4;
|
static const int KEY_DEBUG_MENU = VK_F4;
|
||||||
static const int KEY_THIRD_PERSON = VK_F5;
|
static const int KEY_THIRD_PERSON = VK_F5;
|
||||||
static const int KEY_DEBUG_CONSOLE = VK_F6;
|
static const int KEY_DEBUG_CONSOLE = VK_F6;
|
||||||
static const int KEY_HOST_SETTINGS = VK_F8;
|
static const int KEY_HOST_SETTINGS = VK_TAB;
|
||||||
static const int KEY_FULLSCREEN = VK_F11;
|
static const int KEY_FULLSCREEN = VK_F11;
|
||||||
|
|
||||||
// todo: implement and shi
|
|
||||||
static const int KEY_SCREENSHOT = VK_F2;
|
static const int KEY_SCREENSHOT = VK_F2;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
@@ -563,7 +563,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
else if (vk == VK_MENU)
|
else if (vk == VK_MENU)
|
||||||
vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU;
|
vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU;
|
||||||
g_KBMInput.OnKeyDown(vk);
|
g_KBMInput.OnKeyDown(vk);
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
case WM_KEYUP:
|
case WM_KEYUP:
|
||||||
case WM_SYSKEYUP:
|
case WM_SYSKEYUP:
|
||||||
@@ -661,7 +661,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -673,23 +673,23 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
//
|
//
|
||||||
ATOM MyRegisterClass(HINSTANCE hInstance)
|
ATOM MyRegisterClass(HINSTANCE hInstance)
|
||||||
{
|
{
|
||||||
WNDCLASSEX wcex;
|
WNDCLASSEXW wcex;
|
||||||
|
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
wcex.cbSize = sizeof(WNDCLASSEXW);
|
||||||
|
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
wcex.lpfnWndProc = WndProc;
|
wcex.lpfnWndProc = WndProc;
|
||||||
wcex.cbClsExtra = 0;
|
wcex.cbClsExtra = 0;
|
||||||
wcex.cbWndExtra = 0;
|
wcex.cbWndExtra = 0;
|
||||||
wcex.hInstance = hInstance;
|
wcex.hInstance = hInstance;
|
||||||
wcex.hIcon = LoadIcon(hInstance, "Minecraft");
|
wcex.hIcon = LoadIconW(hInstance, L"Minecraft");
|
||||||
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||||
wcex.lpszMenuName = "Minecraft";
|
wcex.lpszMenuName = L"Minecraft";
|
||||||
wcex.lpszClassName = "MinecraftClass";
|
wcex.lpszClassName = L"MinecraftClass";
|
||||||
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_MINECRAFTWINDOWS));
|
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_MINECRAFTWINDOWS));
|
||||||
|
|
||||||
return RegisterClassEx(&wcex);
|
return RegisterClassExW(&wcex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -709,8 +709,8 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|||||||
RECT wr = {0, 0, g_rScreenWidth, g_rScreenHeight}; // set the size, but not the position
|
RECT wr = {0, 0, g_rScreenWidth, g_rScreenHeight}; // set the size, but not the position
|
||||||
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
|
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
|
||||||
|
|
||||||
g_hWnd = CreateWindow( "MinecraftClass",
|
g_hWnd = CreateWindowW( L"MinecraftClass",
|
||||||
"Minecraft",
|
L"Minecraft",
|
||||||
WS_OVERLAPPEDWINDOW,
|
WS_OVERLAPPEDWINDOW,
|
||||||
CW_USEDEFAULT,
|
CW_USEDEFAULT,
|
||||||
0,
|
0,
|
||||||
|
|||||||