Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 49c1f2c1da |
@@ -1,3 +0,0 @@
|
||||
.github/workflows/docker-nightly.yml merge=ours
|
||||
.github/workflows/nightly.yml merge=ours
|
||||
docker-compose.dedicated-server.ghcr.yml merge=ours
|
||||
|
||||
|
Before Width: | Height: | Size: 778 KiB |
@@ -0,0 +1,31 @@
|
||||
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 }}
|
||||
@@ -0,0 +1,32 @@
|
||||
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"
|
||||
@@ -0,0 +1,160 @@
|
||||
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
|
||||
@@ -1,167 +0,0 @@
|
||||
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-*
|
||||
@@ -1,7 +1,15 @@
|
||||
name: Nightly Releases
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
- 'feature/dedicated-server'
|
||||
paths-ignore:
|
||||
- '.gitignore'
|
||||
- '*.md'
|
||||
- '.github/*.md'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
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,7 +26,6 @@ mono_crash.*
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x64_*/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
@@ -408,10 +407,39 @@ enc_temp_folder/
|
||||
Minecraft.Client/Schematics/
|
||||
Minecraft.Client/Windows64/GameHDD/
|
||||
|
||||
# CMake build output
|
||||
build/
|
||||
# Intermediate build files (per-project)
|
||||
Minecraft.Client/x64/
|
||||
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*/
|
||||
_server_asset_probe/
|
||||
server-data/
|
||||
# Visual Studio Per-User Config
|
||||
*.user
|
||||
/out
|
||||
|
||||
@@ -13,101 +13,232 @@ if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
message(FATAL_ERROR "Use a 64-bit generator/toolchain (x64).")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES
|
||||
"Debug"
|
||||
"Release"
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
function(configure_compiler_target target)
|
||||
# MSVC and compatible compilers (like Clang-cl)
|
||||
if (MSVC)
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<AND:$<CONFIG:Debug>,$<COMPILE_LANGUAGE:C,CXX>>:/W3>
|
||||
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/W0>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
|
||||
$<$<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()
|
||||
function(configure_msvc_target target)
|
||||
target_compile_options(${target} PRIVATE
|
||||
$<$<AND:$<NOT:$<CONFIG:Release>>,$<COMPILE_LANGUAGE:C,CXX>>:/W3>
|
||||
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/W0>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:/FS>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
|
||||
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/GL /O2 /Oi /GT /GF>
|
||||
)
|
||||
endfunction()
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/WorldSources.cmake")
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake")
|
||||
|
||||
# ---
|
||||
# Configuration
|
||||
# ---
|
||||
set(MINECRAFT_SHARED_DEFINES
|
||||
_LARGE_WORLDS
|
||||
_DEBUG_MENUS_ENABLED
|
||||
$<$<CONFIG:Debug>:_DEBUG>
|
||||
_CRT_NON_CONFORMING_SWPRINTFS
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
list(TRANSFORM MINECRAFT_WORLD_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/")
|
||||
list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/")
|
||||
list(APPEND MINECRAFT_CLIENT_SOURCES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/MinecraftWindows.rc"
|
||||
)
|
||||
|
||||
# Add platform-specific defines
|
||||
list(APPEND MINECRAFT_SHARED_DEFINES ${PLATFORM_DEFINES})
|
||||
|
||||
# ---
|
||||
# Sources
|
||||
# ---
|
||||
add_subdirectory(Minecraft.World)
|
||||
add_subdirectory(Minecraft.Client)
|
||||
if(PLATFORM_NAME STREQUAL "Windows64") # Server is only supported on Windows for now
|
||||
add_subdirectory(Minecraft.Server)
|
||||
add_library(MinecraftWorld STATIC ${MINECRAFT_WORLD_SOURCES})
|
||||
target_include_directories(MinecraftWorld PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers"
|
||||
)
|
||||
target_compile_definitions(MinecraftWorld PRIVATE
|
||||
$<$<CONFIG:Debug>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
||||
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
|
||||
)
|
||||
if(MSVC)
|
||||
configure_msvc_target(MinecraftWorld)
|
||||
endif()
|
||||
|
||||
# ---
|
||||
# Build versioning
|
||||
# ---
|
||||
set(BUILDVER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateBuildVer.cmake")
|
||||
set(BUILDVER_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated/Common/BuildVer.h")
|
||||
add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES})
|
||||
target_include_directories(MinecraftClient 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/"
|
||||
)
|
||||
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()
|
||||
|
||||
add_custom_target(GenerateBuildVer
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
"-DOUTPUT_FILE=${BUILDVER_OUTPUT}"
|
||||
-P "${BUILDVER_SCRIPT}"
|
||||
COMMENT "Generating BuildVer.h..."
|
||||
set_target_properties(MinecraftClient PROPERTIES
|
||||
VS_DEBUGGER_WORKING_DIRECTORY "$<TARGET_FILE_DIR:MinecraftClient>"
|
||||
)
|
||||
|
||||
target_link_libraries(MinecraftClient 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"
|
||||
>
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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")
|
||||
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT MinecraftServer)
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
{
|
||||
"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,14 +1,16 @@
|
||||
# Compile Instructions
|
||||
|
||||
## Visual Studio
|
||||
## Visual Studio (`.sln`)
|
||||
|
||||
1. Clone or download the repository
|
||||
1. Open the repo folder in Visual Studio 2022+.
|
||||
2. Wait for cmake to configure the project and load all assets (this may take a few minutes on the first run).
|
||||
3. Right click a folder in the solution explorer and switch to the 'CMake Targets View'
|
||||
4. Select platform and configuration from the dropdown. EG: `Windows64 - Debug` or `Windows64 - Release`
|
||||
5. Pick the startup project `Minecraft.Client.exe` or `Minecraft.Server.exe` using the debug targets dropdown
|
||||
6. Build and run the project:
|
||||
1. Open `MinecraftConsoles.sln` in Visual Studio 2022.
|
||||
2. Set Startup Project:
|
||||
- Client: `Minecraft.Client`
|
||||
- Dedicated server: `Minecraft.Server`
|
||||
3. Select configuration:
|
||||
- `Debug` (recommended), or
|
||||
- `Release`
|
||||
4. Select platform: `Windows64`.
|
||||
5. Build and run:
|
||||
- `Build > Build Solution` (or `Ctrl+Shift+B`)
|
||||
- Start debugging with `F5`.
|
||||
|
||||
@@ -27,52 +29,50 @@
|
||||
|
||||
Configure (use your VS Community instance explicitly):
|
||||
|
||||
Open `Developer PowerShell for VS` and run:
|
||||
|
||||
```powershell
|
||||
cmake --preset windows64
|
||||
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_GENERATOR_INSTANCE="C:/Program Files/Microsoft Visual Studio/2022/Community"
|
||||
```
|
||||
|
||||
Build Debug:
|
||||
|
||||
```powershell
|
||||
cmake --build --preset windows64-debug --target Minecraft.Client
|
||||
cmake --build build --config Debug --target MinecraftClient
|
||||
```
|
||||
|
||||
Build Release:
|
||||
|
||||
```powershell
|
||||
cmake --build --preset windows64-release --target Minecraft.Client
|
||||
cmake --build build --config Release --target MinecraftClient
|
||||
```
|
||||
|
||||
Build Dedicated Server (Debug):
|
||||
|
||||
```powershell
|
||||
cmake --build --preset windows64-debug --target Minecraft.Server
|
||||
cmake --build build --config Debug --target MinecraftServer
|
||||
```
|
||||
|
||||
Build Dedicated Server (Release):
|
||||
|
||||
```powershell
|
||||
cmake --build --preset windows64-release --target Minecraft.Server
|
||||
cmake --build build --config Release --target MinecraftServer
|
||||
```
|
||||
|
||||
Run executable:
|
||||
|
||||
```powershell
|
||||
cd .\build\windows64\Minecraft.Client\Debug
|
||||
.\Minecraft.Client.exe
|
||||
cd .\build\Debug
|
||||
.\MinecraftClient.exe
|
||||
```
|
||||
|
||||
Run dedicated server:
|
||||
|
||||
```powershell
|
||||
cd .\build\windows64\Minecraft.Server\Debug
|
||||
cd .\build\Debug
|
||||
.\Minecraft.Server.exe -port 25565 -bind 0.0.0.0 -name DedicatedServer
|
||||
```
|
||||
|
||||
Notes:
|
||||
- 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.
|
||||
- Post-build asset copy is automatic for `Minecraft.Client` in CMake (Debug and Release variants).
|
||||
- Post-build asset copy is automatic for `MinecraftClient` in CMake (Debug and Release variants).
|
||||
- The game relies on relative paths (for example `Common\Media\...`), so launching from the output directory is required.
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
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,7 +6,6 @@
|
||||
#include "..\Minecraft.World\SharedConstants.h"
|
||||
#include "..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\Minecraft.World\ChatPacket.h"
|
||||
#include "..\Minecraft.World\ArabicShaping.h"
|
||||
|
||||
const wstring ChatScreen::allowedChars = SharedConstants::acceptableLetters;
|
||||
vector<wstring> ChatScreen::s_chatHistory;
|
||||
@@ -15,12 +14,7 @@ wstring ChatScreen::s_historyDraft;
|
||||
|
||||
bool ChatScreen::isAllowedChatChar(wchar_t c)
|
||||
{
|
||||
if (c < 0x20) return false;
|
||||
// Block Unicode bidirectional override characters that can be used to
|
||||
// spoof chat messages or impersonate players.
|
||||
if (c >= 0x202A && c <= 0x202E) return false; // LRE, RLE, PDF, LRO, RLO
|
||||
if (c >= 0x2066 && c <= 0x2069) return false; // LRI, RLI, FSI, PDI
|
||||
return true;
|
||||
return c >= 0x20 && (c == L'\u00A7' || allowedChars.empty() || allowedChars.find(c) != wstring::npos);
|
||||
}
|
||||
|
||||
ChatScreen::ChatScreen()
|
||||
@@ -99,9 +93,6 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
||||
if (eventKey == Keyboard::KEY_RETURN)
|
||||
{
|
||||
wstring trim = trimString(message);
|
||||
{ char buf[64]; sprintf_s(buf, "[CHAT] Sending (%d chars): ", (int)trim.length()); OutputDebugStringA(buf); }
|
||||
OutputDebugStringW(trim.c_str());
|
||||
OutputDebugStringA("\n");
|
||||
if (trim.length() > 0)
|
||||
{
|
||||
if (!minecraft->handleClientSideCommand(trim))
|
||||
@@ -144,7 +135,6 @@ void ChatScreen::keyPressed(wchar_t ch, int eventKey)
|
||||
{
|
||||
message.insert(cursorIndex, 1, ch);
|
||||
cursorIndex++;
|
||||
{ char buf[64]; sprintf_s(buf, "[CHAT] Char U+%04X accepted (%d chars)\n", (unsigned)ch, (int)message.length()); OutputDebugStringA(buf); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,21 +145,14 @@ void ChatScreen::render(int xm, int ym, float a)
|
||||
int x = 4;
|
||||
drawString(font, prefix, x, height - 12, 0xe0e0e0);
|
||||
x += font->width(prefix);
|
||||
|
||||
// Shape the full message as one unit so letter connections and word order
|
||||
// are correct. Track where the logical cursor maps in the visual string.
|
||||
int visualCursorPos = 0;
|
||||
wstring shaped = shapeArabicText(message, cursorIndex, &visualCursorPos);
|
||||
|
||||
// Render the full shaped message without re-shaping it
|
||||
drawStringPreshaped(font, shaped, x, height - 12, 0xe0e0e0);
|
||||
|
||||
// Place the cursor at the correct visual position
|
||||
wstring beforeCursorVisual = shaped.substr(0, visualCursorPos);
|
||||
int cursorX = x + font->widthPreshaped(beforeCursorVisual);
|
||||
wstring beforeCursor = message.substr(0, cursorIndex);
|
||||
wstring afterCursor = message.substr(cursorIndex);
|
||||
drawStringLiteral(font, beforeCursor, x, height - 12, 0xe0e0e0);
|
||||
x += font->widthLiteral(beforeCursor);
|
||||
if (frame / 6 % 2 == 0)
|
||||
drawString(font, L"_", cursorX, height - 12, 0xe0e0e0);
|
||||
|
||||
drawString(font, L"_", x, height - 12, 0xe0e0e0);
|
||||
x += font->width(L"_");
|
||||
drawStringLiteral(font, afterCursor, x, height - 12, 0xe0e0e0);
|
||||
Screen::render(xm, ym, a);
|
||||
}
|
||||
|
||||
|
||||
@@ -342,7 +342,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
||||
Level *dimensionLevel = minecraft->getLevel( packet->dimension );
|
||||
if( dimensionLevel == nullptr )
|
||||
{
|
||||
level = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||
level = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, false, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||
|
||||
// 4J Stu - We want to share the SavedDataStorage between levels
|
||||
int otherDimensionId = packet->dimension == 0 ? -1 : 0;
|
||||
@@ -411,7 +411,7 @@ void ClientConnection::handleLogin(shared_ptr<LoginPacket> packet)
|
||||
activeLevel = minecraft->getLevel(otherDimensionId);
|
||||
}
|
||||
|
||||
MultiPlayerLevel *dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||
MultiPlayerLevel *dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->seed, GameType::byId(packet->gameType), false, false, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||
|
||||
dimensionLevel->savedDataStorage = activeLevel->savedDataStorage;
|
||||
|
||||
@@ -2870,7 +2870,7 @@ void ClientConnection::handleRespawn(shared_ptr<RespawnPacket> packet)
|
||||
MultiPlayerLevel *dimensionLevel = (MultiPlayerLevel *)minecraft->getLevel( packet->dimension );
|
||||
if( dimensionLevel == nullptr )
|
||||
{
|
||||
dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->mapSeed, packet->playerGameType, false, packet->m_isHardcore, packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||
dimensionLevel = new MultiPlayerLevel(this, new LevelSettings(packet->mapSeed, packet->playerGameType, false, minecraft->level->getLevelData()->isHardcore(), packet->m_newSeaLevel, packet->m_pLevelType, packet->m_xzSize, packet->m_hellScale), packet->dimension, packet->difficulty);
|
||||
|
||||
// 4J Stu - We want to shared the savedDataStorage between both levels
|
||||
//if( dimensionLevel->savedDataStorage != nullptr )
|
||||
@@ -3315,9 +3315,7 @@ void ClientConnection::handleTileEditorOpen(shared_ptr<TileEditorOpenPacket> pac
|
||||
|
||||
void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
||||
{
|
||||
app.DebugPrintf("[SIGN] handleSignUpdate at (%d, %d, %d):\n", packet->x, packet->y, packet->z);
|
||||
for (int i = 0; i < MAX_SIGN_LINES; i++)
|
||||
app.DebugPrintf("[SIGN] Line%d: \"%ls\"\n", i+1, packet->lines[i].c_str());
|
||||
app.DebugPrintf("ClientConnection::handleSignUpdate - ");
|
||||
if (minecraft->level->hasChunkAt(packet->x, packet->y, packet->z))
|
||||
{
|
||||
shared_ptr<TileEntity> te = minecraft->level->getTileEntity(packet->x, packet->y, packet->z);
|
||||
@@ -3331,7 +3329,7 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
||||
ste->SetMessage(i,packet->lines[i]);
|
||||
}
|
||||
|
||||
app.DebugPrintf("[SIGN] verified=%d censored=%d\n", packet->m_bVerified, packet->m_bCensored);
|
||||
app.DebugPrintf("verified = %d\tCensored = %d\n",packet->m_bVerified,packet->m_bCensored);
|
||||
ste->SetVerified(packet->m_bVerified);
|
||||
ste->SetCensored(packet->m_bCensored);
|
||||
|
||||
@@ -3339,12 +3337,12 @@ void ClientConnection::handleSignUpdate(shared_ptr<SignUpdatePacket> packet)
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("[SIGN] ERROR: tile entity is not a SignTileEntity\n");
|
||||
app.DebugPrintf("dynamic_pointer_cast<SignTileEntity>(te) == nullptr\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("[SIGN] ERROR: chunk not loaded at position\n");
|
||||
app.DebugPrintf("hasChunkAt failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
#include "stdafx.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::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,8 +15,5 @@ public:
|
||||
static const wstring VERSION_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;
|
||||
};
|
||||
@@ -45,7 +45,6 @@
|
||||
#define GAME_HOST_OPTION_BITMASK_DOTILEDROPS 0x08000000
|
||||
#define GAME_HOST_OPTION_BITMASK_NATURALREGEN 0x10000000
|
||||
#define GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE 0x20000000
|
||||
#define GAME_HOST_OPTION_BITMASK_HARDCORE 0x40000000 // 4J Added - for hardcore mode
|
||||
#define GAME_HOST_OPTION_BITMASK_ALL 0xFFFFFFFF
|
||||
|
||||
#define GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT 20
|
||||
|
||||
@@ -648,7 +648,6 @@ enum eGameHostOption
|
||||
eGameHostOption_DoTileDrops,
|
||||
eGameHostOption_NaturalRegeneration,
|
||||
eGameHostOption_DoDaylightCycle,
|
||||
eGameHostOption_Hardcore, // 4J Added - for hardcore mode
|
||||
};
|
||||
|
||||
// 4J-PB - If any new DLC items are added to the TMSFiles, this array needs updated
|
||||
@@ -879,8 +878,7 @@ enum EControllerActions
|
||||
MINECRAFT_ACTION_SPAWN_CREEPER,
|
||||
MINECRAFT_ACTION_CHANGE_SKIN,
|
||||
MINECRAFT_ACTION_FLY_TOGGLE,
|
||||
MINECRAFT_ACTION_RENDER_DEBUG,
|
||||
MINECRAFT_ACTION_SCREENSHOT
|
||||
MINECRAFT_ACTION_RENDER_DEBUG
|
||||
};
|
||||
|
||||
enum eMCLang
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#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,16 +8084,6 @@ void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOpt
|
||||
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
|
||||
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
|
||||
break;
|
||||
case eGameHostOption_Hardcore: // 4J Added - for hardcore mode
|
||||
if(uiVal!=0)
|
||||
{
|
||||
uiHostSettings |= GAME_HOST_OPTION_BITMASK_HARDCORE;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HARDCORE;
|
||||
}
|
||||
break;
|
||||
case eGameHostOption_All:
|
||||
uiHostSettings=uiVal;
|
||||
break;
|
||||
@@ -8195,9 +8185,6 @@ unsigned int CMinecraftApp::GetGameHostOption(unsigned int uiHostSettings, eGame
|
||||
case eGameHostOption_DoDaylightCycle:
|
||||
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE);
|
||||
break;
|
||||
case eGameHostOption_Hardcore: // 4J Added - for hardcore mode
|
||||
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_HARDCORE) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -805,10 +805,6 @@ public:
|
||||
void SetCorruptSaveDeleted(bool bVal) {m_bCorruptSaveDeleted=bVal;}
|
||||
bool GetCorruptSaveDeleted(void) {return m_bCorruptSaveDeleted;}
|
||||
|
||||
// 4J Added: Store save folder name for hardcore world deletion on Win64
|
||||
void SetCurrentSaveFolderName(const wstring& name) { m_currentSaveFolderName = name; }
|
||||
const wstring& GetCurrentSaveFolderName() const { return m_currentSaveFolderName; }
|
||||
|
||||
void EnterSaveNotificationSection();
|
||||
void LeaveSaveNotificationSection();
|
||||
private:
|
||||
@@ -830,7 +826,6 @@ private:
|
||||
CRITICAL_SECTION csAdditionalSkinBoxes;
|
||||
CRITICAL_SECTION csAnimOverrideBitmask;
|
||||
bool m_bCorruptSaveDeleted;
|
||||
wstring m_currentSaveFolderName; // 4J Added: for hardcore world deletion on Win64
|
||||
|
||||
DWORD m_dwAdditionalModelParts[XUSER_MAX_COUNT];
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 129 B |
|
Before Width: | Height: | Size: 149 B |
|
Before Width: | Height: | Size: 135 B |
|
Before Width: | Height: | Size: 153 B |
|
Before Width: | Height: | Size: 163 B |
|
Before Width: | Height: | Size: 122 B |
|
Before Width: | Height: | Size: 117 B |
|
Before Width: | Height: | Size: 125 B |
|
Before Width: | Height: | Size: 135 B |
@@ -38220,56 +38220,6 @@
|
||||
<Time>19</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>NormalHardcore</Name>
|
||||
<Time>20</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>HalfHardcore</Name>
|
||||
<Time>21</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>FullHardcore</Name>
|
||||
<Time>22</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>HalfPoisonHardcore</Name>
|
||||
<Time>23</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>FullPoisonHardcore</Name>
|
||||
<Time>24</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>NormalFlashHardcore</Name>
|
||||
<Time>25</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>HalfFlashHardcore</Name>
|
||||
<Time>26</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>FullFlashHardcore</Name>
|
||||
<Time>27</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>HalfPoisonFlashHardcore</Name>
|
||||
<Time>28</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
<NamedFrame>
|
||||
<Name>FullPoisonFlashHardcore</Name>
|
||||
<Time>29</Time>
|
||||
<Command>stop</Command>
|
||||
</NamedFrame>
|
||||
</NamedFrames>
|
||||
<Timeline>
|
||||
<Id>Border</Id>
|
||||
@@ -38324,16 +38274,6 @@
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>Graphics\HUD\Health_Background_Flash.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>20</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>Graphics\HUD\Health_Background_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>25</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>Graphics\HUD\Health_Background_Hardcore_Flash.png</Prop>
|
||||
</KeyFrame>
|
||||
</Timeline>
|
||||
<Timeline>
|
||||
<Id>Heart</Id>
|
||||
@@ -38459,66 +38399,6 @@
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\HorseHealth_Half_Flash.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>20</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>false</Prop>
|
||||
<Prop></Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>21</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Half_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>22</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Full_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>23</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Half_Poison_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>24</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Full_Poison_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>25</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>false</Prop>
|
||||
<Prop></Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>26</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Half_Flash_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>27</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Full_Flash_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>28</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Half_Poison_Flash_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
<KeyFrame>
|
||||
<Time>29</Time>
|
||||
<Interpolation>0</Interpolation>
|
||||
<Prop>true</Prop>
|
||||
<Prop>Graphics\HUD\Health_Full_Poison_Flash_Hardcore.png</Prop>
|
||||
</KeyFrame>
|
||||
</Timeline>
|
||||
</Timelines>
|
||||
</XuiVisual>
|
||||
|
||||
@@ -410,72 +410,11 @@ int IUIScene_PauseMenu::ExitWorldThreadProc( void* lpParameter )
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
static bool Win64_DeleteSaveDirectory(const wchar_t* wPath)
|
||||
{
|
||||
wchar_t wSearch[MAX_PATH];
|
||||
swprintf_s(wSearch, MAX_PATH, L"%s\\*", wPath);
|
||||
WIN32_FIND_DATAW fd;
|
||||
HANDLE hFind = FindFirstFileW(wSearch, &fd);
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (wcscmp(fd.cFileName, L".") == 0 || wcscmp(fd.cFileName, L"..") == 0) continue;
|
||||
wchar_t wChild[MAX_PATH];
|
||||
swprintf_s(wChild, MAX_PATH, L"%s\\%s", wPath, fd.cFileName);
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
Win64_DeleteSaveDirectory(wChild);
|
||||
else
|
||||
DeleteFileW(wChild);
|
||||
} while (FindNextFileW(hFind, &fd));
|
||||
FindClose(hFind);
|
||||
}
|
||||
return RemoveDirectoryW(wPath) != 0;
|
||||
}
|
||||
#endif // _WINDOWS64
|
||||
|
||||
// This function performs the meat of exiting from a level. It should be called from a thread other than the main thread.
|
||||
void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
|
||||
{
|
||||
Minecraft *pMinecraft=Minecraft::GetInstance();
|
||||
|
||||
// 4J Added: Capture hardcore delete info before the server is destroyed
|
||||
#ifdef _WINDOWS64
|
||||
bool shouldDeleteHardcoreWorld = false;
|
||||
wstring hardcoreSaveFolderName;
|
||||
if (MinecraftServer::getInstance() != nullptr && MinecraftServer::getInstance()->getDeleteWorldOnExit())
|
||||
{
|
||||
shouldDeleteHardcoreWorld = true;
|
||||
// Try 1: Use the save folder name stored by UIScene_LoadMenu::StartGameFromSave (works for existing saves)
|
||||
hardcoreSaveFolderName = app.GetCurrentSaveFolderName();
|
||||
if (!hardcoreSaveFolderName.empty())
|
||||
{
|
||||
app.DebugPrintf("Hardcore mode: save folder from app = '%ls'\n", hardcoreSaveFolderName.c_str());
|
||||
}
|
||||
// Try 2: StorageManager (may work for new saves after first autosave)
|
||||
if (hardcoreSaveFolderName.empty())
|
||||
{
|
||||
char szSaveFolder[MAX_SAVEFILENAME_LENGTH] = {};
|
||||
StorageManager.GetSaveUniqueFilename(szSaveFolder);
|
||||
if (szSaveFolder[0] != '\0')
|
||||
{
|
||||
wchar_t wSaveFolder[MAX_SAVEFILENAME_LENGTH] = {};
|
||||
mbstowcs(wSaveFolder, szSaveFolder, MAX_SAVEFILENAME_LENGTH - 1);
|
||||
hardcoreSaveFolderName = wSaveFolder;
|
||||
app.DebugPrintf("Hardcore mode: save folder from StorageManager = '%s'\n", szSaveFolder);
|
||||
}
|
||||
}
|
||||
// Try 3: Stored during loadLevel
|
||||
if (hardcoreSaveFolderName.empty())
|
||||
{
|
||||
hardcoreSaveFolderName = MinecraftServer::getInstance()->getSaveFolderName();
|
||||
app.DebugPrintf("Hardcore mode: save folder from server = '%ls'\n", hardcoreSaveFolderName.c_str());
|
||||
}
|
||||
MinecraftServer::getInstance()->setDeleteWorldOnExit(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
int exitReasonStringId = pMinecraft->progressRenderer->getCurrentTitle();
|
||||
int exitReasonTitleId = IDS_CONNECTION_LOST;
|
||||
|
||||
@@ -686,17 +625,6 @@ void IUIScene_PauseMenu::_ExitWorld(LPVOID lpParameter)
|
||||
{
|
||||
Sleep(1);
|
||||
}
|
||||
// 4J Added: Hardcore mode — delete world save data now that the server is fully stopped
|
||||
#ifdef _WINDOWS64
|
||||
if (shouldDeleteHardcoreWorld && !hardcoreSaveFolderName.empty())
|
||||
{
|
||||
wchar_t wFolderPath[MAX_PATH] = {};
|
||||
swprintf_s(wFolderPath, MAX_PATH, L"Windows64\\GameHDD\\%s", hardcoreSaveFolderName.c_str());
|
||||
app.DebugPrintf("Hardcore mode: Deleting world save folder '%ls'\n", wFolderPath);
|
||||
Win64_DeleteSaveDirectory(wFolderPath);
|
||||
}
|
||||
#endif
|
||||
|
||||
pMinecraft->setLevel(nullptr,exitReasonStringId,nullptr,saveStats);
|
||||
|
||||
TelemetryManager->Flush();
|
||||
|
||||
@@ -141,9 +141,6 @@ S32 UIBitmapFont::GetCodepointGlyph(U32 codepoint)
|
||||
// 4J-JEV: Change "right single quotation marks" to apostrophies.
|
||||
if (codepoint == 0x2019) codepoint = 0x27;
|
||||
|
||||
if (!m_cFontData->hasGlyph(codepoint))
|
||||
return IGGY_GLYPH_INVALID;
|
||||
|
||||
return m_cFontData->getGlyphId(codepoint);
|
||||
}
|
||||
|
||||
@@ -256,6 +253,19 @@ rrbool UIBitmapFont::GetGlyphBitmap(S32 glyph,F32 pixel_scale,IggyBitmapCharacte
|
||||
while ( (0.5f + glyphScale) * truePixelScale < pixel_scale)
|
||||
glyphScale++;
|
||||
|
||||
// Debug: log each unique (font, pixel_scale) pair
|
||||
{
|
||||
static std::unordered_set<int> s_loggedScaleKeys;
|
||||
// Encode font pointer + quantized scale into a key to log each combo once
|
||||
int scaleKey = (int)(pixel_scale * 100.0f) ^ (int)(uintptr_t)m_cFontData;
|
||||
if (s_loggedScaleKeys.find(scaleKey) == s_loggedScaleKeys.end() && s_loggedScaleKeys.size() < 50) {
|
||||
s_loggedScaleKeys.insert(scaleKey);
|
||||
float tps = truePixelScale;
|
||||
app.DebugPrintf("[FONT-DBG] GetGlyphBitmap: font=%s glyph=%d pixel_scale=%.3f truePixelScale=%.1f glyphScale=%.0f\n",
|
||||
m_cFontData->getFontName().c_str(), glyph, pixel_scale, tps, glyphScale);
|
||||
}
|
||||
}
|
||||
|
||||
// 4J-JEV: Debug code to check which font sizes are being used.
|
||||
#if (!defined _CONTENT_PACKAGE) && (VERBOSE_FONT_OUTPUT > 0)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "UIControl.h"
|
||||
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\..\..\Minecraft.World\JavaMath.h"
|
||||
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||
|
||||
UIControl_Base::UIControl_Base()
|
||||
{
|
||||
@@ -33,16 +32,13 @@ void UIControl_Base::tick()
|
||||
//app.DebugPrintf("Calling SetLabel - '%ls'\n", m_label.c_str());
|
||||
m_bLabelChanged = false;
|
||||
|
||||
// Shape the text before sending to Iggy; m_label stays unshaped for future updates
|
||||
wstring shaped = shapeArabicText(m_label.getString());
|
||||
|
||||
IggyDataValue result;
|
||||
IggyDataValue value[1];
|
||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||
IggyStringUTF16 stringVal;
|
||||
|
||||
stringVal.string = (IggyUTF16*) shaped.c_str();
|
||||
stringVal.length = (int)shaped.length();
|
||||
stringVal.string = (IggyUTF16*) m_label.c_str();
|
||||
stringVal.length = m_label.length();
|
||||
value[0].string16 = stringVal;
|
||||
|
||||
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
|
||||
@@ -60,16 +56,13 @@ void UIControl_Base::setLabel(UIString label, bool instant, bool force)
|
||||
{
|
||||
m_bLabelChanged = false;
|
||||
|
||||
// Shape the text before sending to Iggy; m_label stays unshaped for future updates
|
||||
wstring shaped = shapeArabicText(m_label.getString());
|
||||
|
||||
IggyDataValue result;
|
||||
IggyDataValue value[1];
|
||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||
IggyStringUTF16 stringVal;
|
||||
|
||||
stringVal.string = (IggyUTF16*) shaped.c_str();
|
||||
stringVal.length = (int)shaped.length();
|
||||
stringVal.string = (IggyUTF16*)m_label.c_str();
|
||||
stringVal.length = m_label.length();
|
||||
value[0].string16 = stringVal;
|
||||
|
||||
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_setLabelFunc , 1 , value );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "UI.h"
|
||||
#include "UIControl_Label.h"
|
||||
#include "..\..\..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||
|
||||
UIControl_Label::UIControl_Label()
|
||||
{
|
||||
@@ -23,15 +22,13 @@ void UIControl_Label::init(UIString label)
|
||||
{
|
||||
m_label = label;
|
||||
|
||||
wstring shaped = shapeArabicText(m_label.getString());
|
||||
|
||||
IggyDataValue result;
|
||||
IggyDataValue value[1];
|
||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||
IggyStringUTF16 stringVal;
|
||||
|
||||
stringVal.string = (IggyUTF16*)shaped.c_str();
|
||||
stringVal.length = (int)shaped.length();
|
||||
stringVal.string = (IggyUTF16*)label.c_str();
|
||||
stringVal.length = label.length();
|
||||
value[0].string16 = stringVal;
|
||||
IggyResult out = IggyPlayerCallMethodRS ( m_parentScene->getMovie() , &result, getIggyValuePath() , m_initFunc , 1 , value );
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "UI.h"
|
||||
#include "UIControl_SaveList.h"
|
||||
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||
|
||||
bool UIControl_SaveList::setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName)
|
||||
{
|
||||
@@ -70,14 +69,12 @@ void UIControl_SaveList::addItem(const string &label, const wstring &iconName, i
|
||||
|
||||
void UIControl_SaveList::addItem(const wstring &label, const wstring &iconName, int data)
|
||||
{
|
||||
wstring shaped = shapeArabicText(label);
|
||||
|
||||
IggyDataValue result;
|
||||
IggyDataValue value[3];
|
||||
|
||||
IggyStringUTF16 stringVal;
|
||||
stringVal.string = (IggyUTF16*)shaped.c_str();
|
||||
stringVal.length = static_cast<S32>(shaped.length());
|
||||
stringVal.string = (IggyUTF16*)label.c_str();
|
||||
stringVal.length = static_cast<S32>(label.length());
|
||||
value[0].type = IGGY_DATATYPE_string_UTF16;
|
||||
value[0].string16 = stringVal;
|
||||
|
||||
|
||||
@@ -216,13 +216,23 @@ UIControl_TextInput::EDirectEditResult UIControl_TextInput::tickDirectEdit()
|
||||
if (g_KBMInput.IsKeyPressed('V') && g_KBMInput.IsKeyDown(VK_CONTROL))
|
||||
{
|
||||
wstring pasted = Screen::getClipboard();
|
||||
for (size_t i = 0; i < pasted.length(); i++)
|
||||
wstring sanitized;
|
||||
sanitized.reserve(pasted.length());
|
||||
|
||||
for (wchar_t pc : pasted)
|
||||
{
|
||||
if (pc >= 0x20) // Keep printable characters
|
||||
{
|
||||
if (m_iCharLimit > 0 && (m_editBuffer.length() + sanitized.length()) >= (size_t)m_iCharLimit)
|
||||
break;
|
||||
sanitized += pc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sanitized.empty())
|
||||
{
|
||||
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++;
|
||||
m_editBuffer.insert(m_iCursorPos, sanitized);
|
||||
m_iCursorPos += (int)sanitized.length();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "..\..\EnderDragonRenderer.h"
|
||||
#include "..\..\MultiPlayerLocalPlayer.h"
|
||||
#include "UIFontData.h"
|
||||
#include "UIUnicodeBitmapFont.h"
|
||||
#include "UISplitScreenHelpers.h"
|
||||
#ifdef _WINDOWS64
|
||||
#include "..\..\Windows64\KeyboardMouseInput.h"
|
||||
@@ -194,7 +193,6 @@ UIController::UIController()
|
||||
m_mcTTFFont = nullptr;
|
||||
m_moj7 = nullptr;
|
||||
m_moj11 = nullptr;
|
||||
m_unicodeBitmapFont = nullptr;
|
||||
|
||||
// 4J-JEV: It's important that these remain the same, unless updateCurrentLanguage is going to be called.
|
||||
m_eCurrentFont = m_eTargetFont = eFont_NotLoaded;
|
||||
@@ -309,14 +307,6 @@ void UIController::postInit()
|
||||
IggySetAS3ExternalFunctionCallbackUTF16 ( &UIController::ExternalFunctionCallback, this );
|
||||
IggySetTextureSubstitutionCallbacks ( &UIController::TextureSubstitutionCreateCallback , &UIController::TextureSubstitutionDestroyCallback, this );
|
||||
|
||||
// Load a unicode bitmap font as Iggy's global fallback for characters not
|
||||
// covered by the Mojangles bitmap font (CJK, Thai, Arabic, Korean, etc.).
|
||||
// Uses the same glyph page PNGs as the legacy Font class, with matching
|
||||
// Mojangles metrics for correct vertical alignment.
|
||||
m_unicodeBitmapFont = new UIUnicodeBitmapFont("Mojangles_Unicode_Bitmap", SFontData::Mojangles_7);
|
||||
m_unicodeBitmapFont->registerFont();
|
||||
IggyFontSetFallbackFontUTF8("Mojangles_Unicode_Bitmap", -1, IGGY_FONTFLAG_none);
|
||||
|
||||
SetupFont();
|
||||
//
|
||||
loadSkins();
|
||||
|
||||
@@ -7,7 +7,6 @@ using namespace std;
|
||||
|
||||
class UIAbstractBitmapFont;
|
||||
class UIBitmapFont;
|
||||
class UIUnicodeBitmapFont;
|
||||
class UITTFFont;
|
||||
class UIComponent_DebugUIConsole;
|
||||
class UIComponent_DebugUIMarketingGuide;
|
||||
@@ -64,7 +63,6 @@ private:
|
||||
UIAbstractBitmapFont *m_mcBitmapFont;
|
||||
UITTFFont *m_mcTTFFont;
|
||||
UIBitmapFont *m_moj7, *m_moj11;
|
||||
UIUnicodeBitmapFont *m_unicodeBitmapFont;
|
||||
|
||||
std::mt19937 m_randomGenerator;
|
||||
std::uniform_real_distribution<float> m_randomDistribution;
|
||||
|
||||
@@ -335,11 +335,6 @@ bool CFontData::unicodeIsWhitespace(unsigned int unicode)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CFontData::hasGlyph(unsigned int unicodepoint)
|
||||
{
|
||||
return m_unicodeMap.find(unicodepoint) != m_unicodeMap.end();
|
||||
}
|
||||
|
||||
void CFontData::moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy)
|
||||
{
|
||||
cursor += (dy * m_sFontData->m_uiGlyphMapX) + dx;
|
||||
|
||||
@@ -125,9 +125,6 @@ public:
|
||||
// Returns true if this unicodepoint is whitespace
|
||||
bool unicodeIsWhitespace(unsigned int unicodepoint);
|
||||
|
||||
// Returns true if this unicodepoint exists in the font's glyph map.
|
||||
bool hasGlyph(unsigned int unicodepoint);
|
||||
|
||||
private:
|
||||
|
||||
// Move a pointer in an image dx pixels right and dy pixels down, wrap around in either dimension leads to unknown behaviour.
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#define GAME_CREATE_ONLINE_TIMER_ID 0
|
||||
#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]=
|
||||
{
|
||||
IDS_DIFFICULTY_TITLE_PEACEFUL,
|
||||
@@ -61,9 +59,8 @@ UIScene_CreateWorldMenu::UIScene_CreateWorldMenu(int iPad, void *initData, UILay
|
||||
|
||||
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)]));
|
||||
m_sliderDifficulty.init(TempString,eControl_Difficulty,0,4,app.GetGameSettings(m_iPad,eGameSetting_Difficulty));
|
||||
m_sliderDifficulty.init(TempString,eControl_Difficulty,0,3,app.GetGameSettings(m_iPad,eGameSetting_Difficulty));
|
||||
|
||||
s_bHardcore = false;
|
||||
m_MoreOptionsParams.bGenerateOptions=TRUE;
|
||||
m_MoreOptionsParams.bStructures=TRUE;
|
||||
m_MoreOptionsParams.bFlatWorld=FALSE;
|
||||
@@ -657,13 +654,8 @@ void UIScene_CreateWorldMenu::handleSliderMove(F64 sliderId, F64 currentValue)
|
||||
case eControl_Difficulty:
|
||||
m_sliderDifficulty.handleSliderMove(value);
|
||||
|
||||
// 4J Added: Difficulty value 4 = Hardcore (store actual difficulty as Hard, track hardcore separately)
|
||||
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]));
|
||||
app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value);
|
||||
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
|
||||
m_sliderDifficulty.setLabel(TempString);
|
||||
break;
|
||||
}
|
||||
@@ -831,7 +823,7 @@ void UIScene_CreateWorldMenu::checkStateAndStartGame()
|
||||
// 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0]=IDS_OK;
|
||||
ui.RequestAlertMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
|
||||
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1121,10 +1113,6 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
|
||||
StorageManager.ResetSaveData();
|
||||
// Make our next save default to the name of the level
|
||||
StorageManager.SetSaveTitle((wchar_t *)wWorldName.c_str());
|
||||
#ifdef _WINDOWS64
|
||||
// New world — save folder doesn't exist yet, clear for now (will be set after first autosave)
|
||||
app.SetCurrentSaveFolderName(L"");
|
||||
#endif
|
||||
|
||||
wstring wSeed;
|
||||
if(!pClass->m_MoreOptionsParams.seed.empty() )
|
||||
@@ -1191,9 +1179,7 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
|
||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
|
||||
|
||||
// 4J Added: If hardcore was selected on difficulty slider, set difficulty to Hard and enable hardcore flag
|
||||
app.SetGameHostOption(eGameHostOption_Difficulty, Minecraft::GetInstance()->options->difficulty);
|
||||
app.SetGameHostOption(eGameHostOption_Hardcore, s_bHardcore ? 1 : 0);
|
||||
app.SetGameHostOption(eGameHostOption_Difficulty,Minecraft::GetInstance()->options->difficulty);
|
||||
app.SetGameHostOption(eGameHostOption_FriendsOfFriends,pClass->m_MoreOptionsParams.bAllowFriendsOfFriends);
|
||||
app.SetGameHostOption(eGameHostOption_Gamertags,app.GetGameSettings(pClass->m_iPad,eGameSetting_GamertagsVisible)?1:0);
|
||||
|
||||
|
||||
@@ -480,6 +480,14 @@ 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
|
||||
#else
|
||||
{ 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
|
||||
#ifdef __PS3__
|
||||
{ L"", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
||||
@@ -488,24 +496,6 @@ SCreditTextItemDef UIScene_Credits::gs_aCreditDefs[MAX_CREDIT_STRINGS] =
|
||||
{ L"are trademarks of Dolby Laboratories.", NO_TRANSLATED_STRING, NO_TRANSLATED_STRING,eSmallText }, // extra blank line
|
||||
#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)
|
||||
|
||||
@@ -3,43 +3,24 @@
|
||||
#include "UIScene_DeathMenu.h"
|
||||
#include "IUIScene_PauseMenu.h"
|
||||
#include "..\..\Minecraft.h"
|
||||
#include "..\..\MultiPlayerLevel.h"
|
||||
#include "..\..\MultiplayerLocalPlayer.h"
|
||||
#include "..\..\MinecraftServer.h"
|
||||
#include "..\..\..\Minecraft.World\net.minecraft.world.level.storage.h"
|
||||
|
||||
UIScene_DeathMenu::UIScene_DeathMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
||||
{
|
||||
// Setup all the Iggy references we need for this scene
|
||||
initialiseMovie();
|
||||
|
||||
m_buttonRespawn.init(app.GetString(IDS_RESPAWN),eControl_Respawn);
|
||||
m_buttonExitGame.init(app.GetString(IDS_EXIT_GAME),eControl_ExitGame);
|
||||
|
||||
m_labelTitle.setLabel(app.GetString(IDS_YOU_DIED));
|
||||
|
||||
// 4J Added: In hardcore mode, disable respawn and show hardcore death message
|
||||
Minecraft *pMC = Minecraft::GetInstance();
|
||||
bool isHardcore = false;
|
||||
if (pMC != nullptr && pMC->level != nullptr)
|
||||
{
|
||||
isHardcore = pMC->level->getLevelData()->isHardcore();
|
||||
}
|
||||
|
||||
if (isHardcore)
|
||||
{
|
||||
m_buttonRespawn.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;
|
||||
|
||||
if(pMC != nullptr && pMC->localgameModes[iPad] != nullptr )
|
||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||
if(pMinecraft != nullptr && pMinecraft->localgameModes[iPad] != nullptr )
|
||||
{
|
||||
TutorialMode *gameMode = static_cast<TutorialMode *>(pMC->localgameModes[iPad]);
|
||||
TutorialMode *gameMode = static_cast<TutorialMode *>(pMinecraft->localgameModes[iPad]);
|
||||
|
||||
// This just allows it to be shown
|
||||
gameMode->getTutorial()->showTutorialPopup(false);
|
||||
@@ -103,16 +84,8 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
|
||||
switch(static_cast<int>(controlId))
|
||||
{
|
||||
case eControl_Respawn:
|
||||
{
|
||||
// 4J Added: Safeguard - don't respawn in hardcore mode
|
||||
Minecraft *pMC = Minecraft::GetInstance();
|
||||
if (pMC != nullptr && pMC->level != nullptr && pMC->level->getLevelData()->isHardcore())
|
||||
{
|
||||
break;
|
||||
}
|
||||
m_bIgnoreInput = true;
|
||||
app.SetAction(m_iPad,eAppAction_Respawn);
|
||||
}
|
||||
m_bIgnoreInput = true;
|
||||
app.SetAction(m_iPad,eAppAction_Respawn);
|
||||
#ifdef _DURANGO
|
||||
//InputManager.SetEnabledGtcButtons(_360_GTC_MENU|_360_GTC_PAUSE|_360_GTC_VIEW);
|
||||
#endif
|
||||
@@ -136,16 +109,7 @@ void UIScene_DeathMenu::handlePress(F64 controlId, F64 childId)
|
||||
playTime = static_cast<int>(pMinecraft->localplayers[m_iPad]->getSessionTimer());
|
||||
}
|
||||
TelemetryManager->RecordLevelExit(m_iPad, eSen_LevelExitStatus_Failed);
|
||||
|
||||
// 4J Added: Hardcore mode — skip save dialog, exit without saving, delete world
|
||||
if (pMinecraft->level != nullptr && pMinecraft->level->getLevelData()->isHardcore() && g_NetworkManager.IsHost())
|
||||
{
|
||||
MinecraftServer::getInstance()->setSaveOnExit(false);
|
||||
MinecraftServer::getInstance()->setDeleteWorldOnExit(true);
|
||||
app.SetAction(m_iPad, eAppAction_ExitWorld);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#if defined (_XBOX_ONE) || defined(__ORBIS__)
|
||||
if(g_NetworkManager.IsHost() && StorageManager.GetSaveDisabled())
|
||||
{
|
||||
|
||||
@@ -229,19 +229,29 @@ void UIScene_Keyboard::tick()
|
||||
if (g_KBMInput.IsKeyPressed('V') && g_KBMInput.IsKeyDown(VK_CONTROL))
|
||||
{
|
||||
wstring pasted = Screen::getClipboard();
|
||||
for (size_t i = 0; i < pasted.length(); i++)
|
||||
wstring sanitized;
|
||||
sanitized.reserve(pasted.length());
|
||||
|
||||
for (wchar_t pc : pasted)
|
||||
{
|
||||
if (pc >= 0x20) // Keep printable characters
|
||||
{
|
||||
if (static_cast<int>(m_win64TextBuffer.length() + sanitized.length()) >= m_win64MaxChars)
|
||||
break;
|
||||
sanitized += pc;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sanitized.empty())
|
||||
{
|
||||
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++;
|
||||
m_win64TextBuffer.insert(m_iCursorPos, sanitized);
|
||||
m_iCursorPos += (int)sanitized.length();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_win64TextBuffer += pc;
|
||||
m_win64TextBuffer += sanitized;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,12 @@
|
||||
#define CHECKFORAVAILABLETEXTUREPACKS_TIMER_TIME 50
|
||||
#endif
|
||||
|
||||
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[5]=
|
||||
int UIScene_LoadMenu::m_iDifficultyTitleSettingA[4]=
|
||||
{
|
||||
IDS_DIFFICULTY_TITLE_PEACEFUL,
|
||||
IDS_DIFFICULTY_TITLE_EASY,
|
||||
IDS_DIFFICULTY_TITLE_NORMAL,
|
||||
IDS_DIFFICULTY_TITLE_HARD,
|
||||
IDS_GAMEMODE_HARDCORE
|
||||
IDS_DIFFICULTY_TITLE_HARD
|
||||
};
|
||||
|
||||
int UIScene_LoadMenu::LoadSaveDataThumbnailReturned(LPVOID lpParam,PBYTE pbThumbnail,DWORD dwThumbnailBytes)
|
||||
@@ -111,7 +110,6 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
|
||||
m_bThumbnailGetFailed = false;
|
||||
m_seed = 0;
|
||||
m_bIsCorrupt = false;
|
||||
m_bHardcore = false;
|
||||
|
||||
m_bMultiplayerAllowed = ProfileManager.IsSignedInLive( m_iPad ) && ProfileManager.AllowedToPlayMultiplayer(m_iPad);
|
||||
// 4J-PB - read the settings for the online flag. We'll only save this setting if the user changed it.
|
||||
@@ -255,34 +253,10 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
|
||||
{
|
||||
wchar_t wSaveName[128];
|
||||
ZeroMemory(wSaveName, sizeof(wSaveName));
|
||||
MultiByteToWideChar(CP_UTF8, 0, params->saveDetails->UTF8SaveName, -1, wSaveName, 127);
|
||||
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, 127);
|
||||
m_levelName = wstring(wSaveName);
|
||||
m_labelGameName.init(m_levelName);
|
||||
}
|
||||
if (params->saveDetails != nullptr)
|
||||
{
|
||||
// Set thumbnail name from save filename (needed for texture display in tick)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -572,14 +546,6 @@ void UIScene_LoadMenu::tick()
|
||||
{
|
||||
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();
|
||||
@@ -984,15 +950,10 @@ void UIScene_LoadMenu::handleSliderMove(F64 sliderId, F64 currentValue)
|
||||
switch(static_cast<int>(sliderId))
|
||||
{
|
||||
case eControl_Difficulty:
|
||||
if (m_bHardcore)
|
||||
{
|
||||
m_sliderDifficulty.handleSliderMove(4);
|
||||
break;
|
||||
}
|
||||
m_sliderDifficulty.handleSliderMove(value);
|
||||
|
||||
app.SetGameSettings(m_iPad,eGameSetting_Difficulty,value);
|
||||
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
|
||||
swprintf( (WCHAR *)TempString, 256, L"%ls: %ls", app.GetString( IDS_SLIDER_DIFFICULTY ),app.GetString(m_iDifficultyTitleSettingA[value]));
|
||||
m_sliderDifficulty.setLabel(TempString);
|
||||
break;
|
||||
}
|
||||
@@ -1206,7 +1167,7 @@ void UIScene_LoadMenu::LaunchGame(void)
|
||||
#if TO_BE_IMPLEMENTED
|
||||
if(eLoadStatus==C4JStorage::ELoadGame_DeviceRemoved)
|
||||
{
|
||||
// disable saving
|
||||
// disable saving
|
||||
StorageManager.SetSaveDisabled(true);
|
||||
StorageManager.SetSaveDeviceSelected(m_iPad,false);
|
||||
UINT uiIDA[1];
|
||||
@@ -1619,24 +1580,6 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
|
||||
|
||||
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
// 4J Added: Store save folder name for potential hardcore world deletion
|
||||
app.DebugPrintf("StartGameFromSave: pSaveDetails=%p, levelGen=%p, saveInfoIndex=%d\n", pSaveDetails, pClass->m_levelGen, pClass->m_iSaveGameInfoIndex);
|
||||
if (pSaveDetails != nullptr && pClass->m_levelGen == nullptr)
|
||||
{
|
||||
app.DebugPrintf("StartGameFromSave: UTF8SaveFilename='%s'\n", pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex].UTF8SaveFilename);
|
||||
wchar_t wFolder[MAX_SAVEFILENAME_LENGTH] = {};
|
||||
mbstowcs(wFolder, pSaveDetails->SaveInfoA[(int)pClass->m_iSaveGameInfoIndex].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
|
||||
app.SetCurrentSaveFolderName(wFolder);
|
||||
app.DebugPrintf("StartGameFromSave: stored folder name '%ls'\n", wFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("StartGameFromSave: no save details or is levelGen, clearing folder name\n");
|
||||
app.SetCurrentSaveFolderName(L"");
|
||||
}
|
||||
#endif
|
||||
|
||||
NetworkGameInitData *param = new NetworkGameInitData();
|
||||
param->seed = pClass->m_seed;
|
||||
param->saveData = nullptr;
|
||||
@@ -1669,7 +1612,6 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
|
||||
app.SetGameHostOption(eGameHostOption_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
|
||||
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
|
||||
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
|
||||
app.SetGameHostOption(eGameHostOption_Hardcore, pClass->m_bHardcore ? 1 : 0);
|
||||
|
||||
#ifdef _LARGE_WORLDS
|
||||
app.SetGameHostOption(eGameHostOption_WorldSize, pClass->m_MoreOptionsParams.worldSize+1 ); // 0 is GAME_HOST_OPTION_WORLDSIZE_UNKNOWN
|
||||
|
||||
@@ -15,7 +15,7 @@ private:
|
||||
eControl_OnlineGame,
|
||||
};
|
||||
|
||||
static int m_iDifficultyTitleSettingA[5];
|
||||
static int m_iDifficultyTitleSettingA[4];
|
||||
|
||||
UIControl m_controlMainPanel;
|
||||
UIControl_Label m_labelGameName, m_labelSeed, m_labelCreatedMode;
|
||||
@@ -71,7 +71,6 @@ private:
|
||||
wstring m_thumbnailName;
|
||||
|
||||
bool m_bRebuildTouchBoxes;
|
||||
bool m_bHardcore;
|
||||
public:
|
||||
UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLayer);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "..\..\..\Minecraft.World\NbtIo.h"
|
||||
#include "..\..\..\Minecraft.World\compression.h"
|
||||
|
||||
static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardcore = nullptr)
|
||||
static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
|
||||
{
|
||||
// Check for a worldname.txt sidecar written by the rename feature first
|
||||
size_t slashPos = filePath.rfind(L'\\');
|
||||
@@ -49,7 +49,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
|
||||
if (len > 0)
|
||||
{
|
||||
wchar_t wbuf[128] = {};
|
||||
MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, 127);
|
||||
mbstowcs(wbuf, buf, 127);
|
||||
return wstring(wbuf);
|
||||
}
|
||||
}
|
||||
@@ -124,11 +124,7 @@ static wstring ReadLevelNameFromSaveFile(const wstring& filePath, bool *outHardc
|
||||
{
|
||||
CompoundTag *dataTag = root->getCompound(L"Data");
|
||||
if (dataTag != nullptr)
|
||||
{
|
||||
result = dataTag->getString(L"LevelName");
|
||||
if (outHardcore)
|
||||
*outHardcore = dataTag->getBoolean(L"hardcore");
|
||||
}
|
||||
delete root;
|
||||
}
|
||||
}
|
||||
@@ -210,8 +206,6 @@ int UIScene_LoadOrJoinMenu::LoadSaveCallback(LPVOID lpParam,bool bRes)
|
||||
|
||||
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
|
||||
initialiseMovie();
|
||||
app.SetLiveLinkRequired( true );
|
||||
@@ -236,8 +230,8 @@ UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer
|
||||
m_controlJoinTimer.setVisible( true );
|
||||
|
||||
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||
m_spaceIndicatorSaves.init(L"",eControl_SpaceIndicator,0, MAXIMUM_SAVE_STORAGE);
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
||||
m_spaceIndicatorSaves.init(L"",eControl_SpaceIndicator,0, (4LL *1024LL * 1024LL * 1024LL) );
|
||||
#endif
|
||||
m_bUpdateSaveSize = false;
|
||||
|
||||
@@ -701,7 +695,7 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||
if(m_eSaveTransferState == eSaveTransfer_Idle)
|
||||
m_bSaveTransferRunning = false;
|
||||
#endif
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
||||
if(m_bUpdateSaveSize)
|
||||
{
|
||||
if((m_iDefaultButtonsC > 0) && (m_iSaveListIndex >= m_iDefaultButtonsC))
|
||||
@@ -722,7 +716,7 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||
if(m_pSaveDetails!=nullptr)
|
||||
{
|
||||
//CD - Fix - Adding define for ORBIS/XBOXONE
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
||||
m_spaceIndicatorSaves.reset();
|
||||
#endif
|
||||
|
||||
@@ -764,22 +758,6 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||
{
|
||||
#if defined(_XBOX_ONE)
|
||||
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__)
|
||||
m_spaceIndicatorSaves.addSave(m_pSaveDetails->SaveInfoA[i].blocksUsed * (32 * 1024) );
|
||||
#endif
|
||||
@@ -792,17 +770,17 @@ void UIScene_LoadOrJoinMenu::tick()
|
||||
#else
|
||||
#ifdef _WINDOWS64
|
||||
{
|
||||
bool saveHardcore = false;
|
||||
wstring levelName = ReadLevelNameFromSaveFile(filePath, &saveHardcore);
|
||||
m_saveDetails[i].isHardcore = saveHardcore;
|
||||
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");
|
||||
wstring levelName = ReadLevelNameFromSaveFile(filePath);
|
||||
if (!levelName.empty())
|
||||
{
|
||||
m_buttonListSaves.addItem(levelName, wstring(L""));
|
||||
{
|
||||
int n = WideCharToMultiByte(CP_UTF8, 0, levelName.c_str(), -1, m_saveDetails[i].UTF8SaveName, 127, nullptr, nullptr);
|
||||
if (n <= 0) m_saveDetails[i].UTF8SaveName[0] = '\0';
|
||||
m_saveDetails[i].UTF8SaveName[127] = '\0';
|
||||
}
|
||||
wcstombs(m_saveDetails[i].UTF8SaveName, levelName.c_str(), 127);
|
||||
m_saveDetails[i].UTF8SaveName[127] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1447,9 +1425,9 @@ int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,boo
|
||||
for (int k = 0; k < 127 && ui16Text[k]; k++)
|
||||
wNewName[k] = static_cast<wchar_t>(ui16Text[k]);
|
||||
|
||||
// Convert to narrow for storage and in-memory update (UTF-8 to preserve Unicode)
|
||||
char narrowName[256] = {};
|
||||
WideCharToMultiByte(CP_UTF8, 0, wNewName, -1, narrowName, 255, nullptr, nullptr);
|
||||
// Convert to narrow for storage and in-memory update
|
||||
char narrowName[128] = {};
|
||||
wcstombs(narrowName, wNewName, 127);
|
||||
|
||||
// Build the sidecar path: Windows64\GameHDD\{folder}\worldname.txt
|
||||
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH] = {};
|
||||
@@ -1465,7 +1443,7 @@ int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(LPVOID lpParam,boo
|
||||
|
||||
// Update the in-memory display name so the list reflects it immediately
|
||||
strncpy_s(pClass->m_saveDetails[listPos].UTF8SaveName, narrowName, 127);
|
||||
pClass->m_saveDetails[listPos].UTF8SaveName[127] = '\0'; // UTF8SaveName is still 128 bytes; narrowName fits as Arabic is <=2 bytes/char in UTF-8
|
||||
pClass->m_saveDetails[listPos].UTF8SaveName[127] = '\0';
|
||||
|
||||
// Reuse the existing callback to trigger the list repopulate
|
||||
UIScene_LoadOrJoinMenu::RenameSaveDataReturned(pClass, true);
|
||||
@@ -2533,7 +2511,7 @@ int UIScene_LoadOrJoinMenu::SaveOptionsDialogReturned(void *pParam,int iPad,C4JS
|
||||
{
|
||||
wchar_t wSaveName[128];
|
||||
ZeroMemory(wSaveName, 128 * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, -1, wSaveName, 127);
|
||||
mbstowcs_s(nullptr, wSaveName, 128, pClass->m_saveDetails[pClass->m_iSaveListIndex - pClass->m_iDefaultButtonsC].UTF8SaveName, _TRUNCATE);
|
||||
UIKeyboardInitData kbData;
|
||||
kbData.title = app.GetString(IDS_RENAME_WORLD_TITLE);
|
||||
kbData.defaultText = wSaveName;
|
||||
|
||||
@@ -20,7 +20,7 @@ private:
|
||||
{
|
||||
eControl_SavesList,
|
||||
eControl_GamesList,
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
||||
eControl_SpaceIndicator,
|
||||
#endif
|
||||
};
|
||||
@@ -52,7 +52,7 @@ protected:
|
||||
UIControl_SaveList m_buttonListGames;
|
||||
UIControl_Label m_labelSavesListTitle, m_labelJoinListTitle, m_labelNoGames;
|
||||
UIControl m_controlSavesTimer, m_controlJoinTimer;
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
||||
UIControl_SpaceIndicatorBar m_spaceIndicatorSaves;
|
||||
#endif
|
||||
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
UI_MAP_ELEMENT( m_controlSavesTimer, "SavesTimer")
|
||||
UI_MAP_ELEMENT( m_controlJoinTimer, "JoinTimer")
|
||||
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__) || defined(_WINDOWS64)
|
||||
#if defined(_XBOX_ONE) || defined(__ORBIS__)
|
||||
UI_MAP_ELEMENT( m_spaceIndicatorSaves, "SaveSizeBar")
|
||||
#endif
|
||||
UI_END_MAP_ELEMENTS_AND_NAMES()
|
||||
|
||||
@@ -247,14 +247,11 @@ typedef struct _SaveListDetails
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool isHardcore;
|
||||
|
||||
_SaveListDetails()
|
||||
{
|
||||
saveId = 0;
|
||||
pbThumbnailData = nullptr;
|
||||
dwThumbnailSize = 0;
|
||||
isHardcore = false;
|
||||
#ifdef _DURANGO
|
||||
ZeroMemory(UTF16SaveName,sizeof(wchar_t)*128);
|
||||
ZeroMemory(UTF16SaveFilename,sizeof(wchar_t)*MAX_SAVEFILENAME_LENGTH);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "..\..\..\Minecraft.World\File.h"
|
||||
#include "UITTFFont.h"
|
||||
|
||||
UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharacter, bool registerAsDefaultFonts)
|
||||
UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharacter)
|
||||
: m_strFontName(name)
|
||||
{
|
||||
app.DebugPrintf("UITTFFont opening %s\n",path.c_str());
|
||||
@@ -41,12 +41,9 @@ UITTFFont::UITTFFont(const string &name, const string &path, S32 fallbackCharact
|
||||
|
||||
IggyFontInstallTruetypeFallbackCodepointUTF8( m_strFontName.c_str(), -1, IGGY_FONTFLAG_none, fallbackCharacter );
|
||||
|
||||
if (registerAsDefaultFonts)
|
||||
{
|
||||
// 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 );
|
||||
}
|
||||
// 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;
|
||||
|
||||
public:
|
||||
UITTFFont(const string &name, const string &path, S32 fallbackCharacter, bool registerAsDefaultFonts = true);
|
||||
UITTFFont(const string &name, const string &path, S32 fallbackCharacter);
|
||||
~UITTFFont();
|
||||
|
||||
string getFontName();
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
#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.
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#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,7 +2,6 @@
|
||||
#include "XUI_Chat.h"
|
||||
#include "..\..\Minecraft.h"
|
||||
#include "..\..\Gui.h"
|
||||
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||
|
||||
HRESULT CScene_Chat::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
|
||||
{
|
||||
@@ -30,8 +29,7 @@ HRESULT CScene_Chat::OnTimer( XUIMessageTimer *pXUIMessageTimer, BOOL &bHandled)
|
||||
{
|
||||
m_Backgrounds[i].SetOpacity(opacity);
|
||||
m_Labels[i].SetOpacity(opacity);
|
||||
wstring shaped = shapeArabicText(pGui->getMessage(m_iPad, i));
|
||||
m_Labels[i].SetText( shaped.c_str() );
|
||||
m_Labels[i].SetText( pGui->getMessage(m_iPad,i).c_str() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "XUI_Ctrl_4JList.h"
|
||||
#include "..\..\..\Minecraft.World\ArabicShaping.h"
|
||||
|
||||
static bool TimeSortFn(const void *a, const void *b);
|
||||
|
||||
@@ -295,16 +294,8 @@ HRESULT CXuiCtrl4JList::OnGetSourceDataText(XUIMessageGetSourceText *pGetSourceT
|
||||
if( ( 0 == pGetSourceTextData->iData ) && ( ( pGetSourceTextData->bItemData ) ) )
|
||||
{
|
||||
EnterCriticalSection(&m_AccessListData);
|
||||
LPCWSTR rawText = GetData(pGetSourceTextData->iItem).pwszText;
|
||||
if (rawText)
|
||||
{
|
||||
m_shapedTextCache = shapeArabicText(rawText);
|
||||
pGetSourceTextData->szText = m_shapedTextCache.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
pGetSourceTextData->szText = rawText;
|
||||
}
|
||||
pGetSourceTextData->szText =
|
||||
GetData(pGetSourceTextData->iItem).pwszText;
|
||||
LeaveCriticalSection(&m_AccessListData);
|
||||
bHandled = TRUE;
|
||||
}
|
||||
|
||||
@@ -75,5 +75,4 @@ private:
|
||||
static bool IndexSortFn(const void *a, const void *b);
|
||||
|
||||
HXUIOBJ m_hSelectionChangedHandlerObj;
|
||||
std::wstring m_shapedTextCache; // temp buffer for Arabic-shaped text in OnGetSourceDataText
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "..\..\..\Minecraft.World\Entity.h"
|
||||
#include "..\..\..\Minecraft.Client\MultiplayerLocalPlayer.h"
|
||||
#include "..\..\..\Minecraft.World\Level.h"
|
||||
#include "..\..\..\Minecraft.World\net.minecraft.world.level.storage.h"
|
||||
#include "..\..\..\Minecraft.World\ChunkSource.h"
|
||||
#include "..\..\..\Minecraft.Client\ProgressRenderer.h"
|
||||
#include "..\..\..\Minecraft.Client\GameRenderer.h"
|
||||
@@ -19,7 +18,6 @@
|
||||
#include "..\..\..\Minecraft.World\Pos.h"
|
||||
#include "..\..\..\Minecraft.World\Dimension.h"
|
||||
#include "..\..\Minecraft.h"
|
||||
#include "..\..\MinecraftServer.h"
|
||||
#include "..\..\Options.h"
|
||||
#include "..\..\LocalPlayer.h"
|
||||
#include "..\..\..\Minecraft.World\compression.h"
|
||||
@@ -39,26 +37,9 @@ HRESULT CScene_Death::OnInit( XUIMessageInit* pInitData, BOOL& bHandled )
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
// 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
|
||||
ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT);
|
||||
|
||||
@@ -129,16 +110,7 @@ HRESULT CScene_Death::OnNotifyPressEx(HXUIOBJ hObjPressed, XUINotifyPress* pNoti
|
||||
playTime = static_cast<int>(pMinecraft->localplayers[pNotifyPressData->UserIndex]->getSessionTimer());
|
||||
}
|
||||
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())
|
||||
{
|
||||
uiIDA[0]=IDS_CONFIRM_CANCEL;
|
||||
@@ -200,12 +172,6 @@ HRESULT CScene_Death::OnNotifyPressEx(HXUIOBJ hObjPressed, XUINotifyPress* pNoti
|
||||
break;
|
||||
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;
|
||||
app.SetAction(pNotifyPressData->UserIndex,eAppAction_Respawn);
|
||||
}
|
||||
|
||||
@@ -186,8 +186,7 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
||||
if (pMinecraft->localplayers[m_iPad]->invulnerableTime < 10) blink = false;
|
||||
int iHealth = pMinecraft->localplayers[m_iPad]->getHealth();
|
||||
int iLastHealth = pMinecraft->localplayers[m_iPad]->lastHealth;
|
||||
bool bHasPoison = pMinecraft->localplayers[m_iPad]->hasEffect(MobEffect::poison);
|
||||
bool isHardcore = pMinecraft->level != nullptr && pMinecraft->level->getLevelData()->isHardcore();
|
||||
bool bHasPoison = pMinecraft->localplayers[m_iPad]->hasEffect(MobEffect::poison);
|
||||
for (int icon = 0; icon < Player::MAX_HEALTH / 2; icon++)
|
||||
{
|
||||
if(blink)
|
||||
@@ -197,15 +196,11 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
||||
// Full
|
||||
if(bHasPoison)
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"FullPoisonFlashHardcore" : L"FullPoisonFlash", nullptr,
|
||||
isHardcore ? L"FullPoisonFlashHardcore" : L"FullPoisonFlash");
|
||||
m_healthIcon[icon].PlayVisualRange(L"FullPoisonFlash",nullptr,L"FullPoisonFlash");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"FullFlashHardcore" : L"FullFlash", nullptr,
|
||||
isHardcore ? L"FullFlashHardcore" : L"FullFlash");
|
||||
m_healthIcon[icon].PlayVisualRange(L"FullFlash",nullptr,L"FullFlash");
|
||||
}
|
||||
}
|
||||
else if (icon * 2 + 1 == iLastHealth || icon * 2 + 1 == iHealth)
|
||||
@@ -213,23 +208,17 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
||||
// Half
|
||||
if(bHasPoison)
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"HalfPoisonFlashHardcore" : L"HalfPoisonFlash", nullptr,
|
||||
isHardcore ? L"HalfPoisonFlashHardcore" : L"HalfPoisonFlash");
|
||||
m_healthIcon[icon].PlayVisualRange(L"HalfPoisonFlash",nullptr,L"HalfPoisonFlash");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"HalfFlashHardcore" : L"HalfFlash", nullptr,
|
||||
isHardcore ? L"HalfFlashHardcore" : L"HalfFlash");
|
||||
m_healthIcon[icon].PlayVisualRange(L"HalfFlash",nullptr,L"HalfFlash");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Empty
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"NormalFlashHardcore" : L"NormalFlash", nullptr,
|
||||
isHardcore ? L"NormalFlashHardcore" : L"NormalFlash");
|
||||
m_healthIcon[icon].PlayVisualRange(L"NormalFlash",nullptr,L"NormalFlash");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -239,15 +228,11 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
||||
// Full
|
||||
if(bHasPoison)
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"FullPoisonHardcore" : L"FullPoison", nullptr,
|
||||
isHardcore ? L"FullPoisonHardcore" : L"FullPoison");
|
||||
m_healthIcon[icon].PlayVisualRange(L"FullPoison",nullptr,L"FullPoison");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"FullHardcore" : L"Full", nullptr,
|
||||
isHardcore ? L"FullHardcore" : L"Full");
|
||||
m_healthIcon[icon].PlayVisualRange(L"Full",nullptr,L"Full");
|
||||
}
|
||||
}
|
||||
else if (icon * 2 + 1 == iHealth)
|
||||
@@ -255,23 +240,17 @@ HRESULT CXuiSceneHud::OnCustomMessage_TickScene()
|
||||
// Half
|
||||
if(bHasPoison)
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"HalfPoisonHardcore" : L"HalfPoison", nullptr,
|
||||
isHardcore ? L"HalfPoisonHardcore" : L"HalfPoison");
|
||||
m_healthIcon[icon].PlayVisualRange(L"HalfPoison",nullptr,L"HalfPoison");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"HalfHardcore" : L"Half", nullptr,
|
||||
isHardcore ? L"HalfHardcore" : L"Half");
|
||||
m_healthIcon[icon].PlayVisualRange(L"Half",nullptr,L"Half");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Empty
|
||||
m_healthIcon[icon].PlayVisualRange(
|
||||
isHardcore ? L"NormalHardcore" : L"Normal", nullptr,
|
||||
isHardcore ? L"NormalHardcore" : L"Normal");
|
||||
m_healthIcon[icon].PlayVisualRange(L"Normal",nullptr,L"Normal");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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,7 +8,6 @@
|
||||
#include "..\Minecraft.World\net.minecraft.h"
|
||||
#include "..\Minecraft.World\StringHelpers.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)
|
||||
{
|
||||
@@ -17,7 +16,7 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
|
||||
charWidths = new int[charC];
|
||||
|
||||
// 4J - added initialisers
|
||||
memset(charWidths, 0, charC * sizeof(int));
|
||||
memset(charWidths, 0, charC);
|
||||
|
||||
enforceUnicodeSheet = false;
|
||||
bidirectional = false;
|
||||
@@ -27,19 +26,6 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
|
||||
m_underline = 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
|
||||
m_cols = cols;
|
||||
m_rows = rows;
|
||||
@@ -275,87 +261,7 @@ void Font::drawLiteral(const wstring& str, int x, int y, int color)
|
||||
yPos = static_cast<float>(y);
|
||||
wstring cleanStr = sanitize(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
renderCharacter(cleanStr.at(i));
|
||||
}
|
||||
|
||||
void Font::drawShadowWordWrap(const wstring &str, int x, int y, int w, int color, int h)
|
||||
@@ -439,7 +345,7 @@ void Font::draw(const wstring &str, bool dropShadow)
|
||||
}
|
||||
|
||||
// "noise" for crazy splash screen message
|
||||
if (noise && !isUnicodeGlyphChar(c))
|
||||
if (noise)
|
||||
{
|
||||
int newc;
|
||||
do
|
||||
@@ -449,18 +355,7 @@ void Font::draw(const wstring &str, bool dropShadow)
|
||||
c = newc;
|
||||
}
|
||||
|
||||
if (isUnicodeGlyphChar(c))
|
||||
{
|
||||
t->end();
|
||||
renderUnicodeCharacter(c);
|
||||
textures->bindTexture(m_textureLocation);
|
||||
lastBoundTexture = fontTexture;
|
||||
t->begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
addCharacterQuad(c);
|
||||
}
|
||||
addCharacterQuad(c);
|
||||
}
|
||||
|
||||
t->end();
|
||||
@@ -501,22 +396,11 @@ int Font::width(const wstring& str)
|
||||
++i;
|
||||
else
|
||||
{
|
||||
if (isUnicodeGlyphChar(167))
|
||||
len += (int)unicodeCharWidth(167);
|
||||
else
|
||||
len += charWidths[167];
|
||||
len += charWidths[167];
|
||||
if (i + 1 < cleanStr.length())
|
||||
{
|
||||
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)];
|
||||
}
|
||||
len += charWidths[static_cast<unsigned>(cleanStr[++i])];
|
||||
}
|
||||
}
|
||||
else if (isUnicodeGlyphChar(c))
|
||||
len += (int)unicodeCharWidth(c);
|
||||
else
|
||||
len += charWidths[c];
|
||||
}
|
||||
@@ -530,19 +414,13 @@ int Font::widthLiteral(const wstring& str)
|
||||
if (cleanStr == L"") 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)];
|
||||
}
|
||||
len += charWidths[static_cast<unsigned>(cleanStr.at(i))];
|
||||
return len;
|
||||
}
|
||||
|
||||
wstring Font::sanitize(const wstring& str)
|
||||
{
|
||||
wstring sb = shapeArabicText(str);
|
||||
wstring sb = str;
|
||||
|
||||
for (unsigned int i = 0; i < sb.length(); i++)
|
||||
{
|
||||
@@ -550,10 +428,6 @@ wstring Font::sanitize(const wstring& str)
|
||||
{
|
||||
sb[i] = MapCharacter(sb[i]);
|
||||
}
|
||||
else if (unicodeWidth[sb[i]] != 0)
|
||||
{
|
||||
// Leave as-is: raw codepoint for glyph page rendering
|
||||
}
|
||||
else
|
||||
{
|
||||
// If this character isn't supported, just show the first character (empty square box character)
|
||||
@@ -797,22 +671,33 @@ void Font::renderFakeCB(IntBuffer *ib)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void Font::loadUnicodePage(int page)
|
||||
{
|
||||
wchar_t fileName[40];
|
||||
swprintf(fileName, 40, L"/1_2_2/font/glyph_%02X.png", page);
|
||||
wchar_t fileName[25];
|
||||
//String fileName = String.format("/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);
|
||||
//try
|
||||
//{
|
||||
// image = ImageIO.read(Textures.class.getResourceAsStream(fileName.toString()));
|
||||
//}
|
||||
//catch (IOException e)
|
||||
//{
|
||||
// throw new RuntimeException(e);
|
||||
//}
|
||||
|
||||
unicodeTexID[page] = textures->getTexture(image);
|
||||
lastBoundTexture = unicodeTexID[page];
|
||||
delete image;
|
||||
}
|
||||
|
||||
void Font::renderUnicodeCharacter(wchar_t c)
|
||||
{
|
||||
if (unicodeWidth[c] == 0)
|
||||
{
|
||||
// System.out.println("no-width char " + c);
|
||||
return;
|
||||
}
|
||||
|
||||
int page = c / 256;
|
||||
|
||||
@@ -824,17 +709,19 @@ void Font::renderUnicodeCharacter(wchar_t c)
|
||||
lastBoundTexture = unicodeTexID[page];
|
||||
}
|
||||
|
||||
// first column with non-trans pixels
|
||||
int firstLeft = unicodeWidth[c] >> 4;
|
||||
// last column with non-trans pixels
|
||||
int firstRight = unicodeWidth[c] & 0xF;
|
||||
|
||||
float left = (float)firstLeft;
|
||||
float right = (float)(firstRight + 1);
|
||||
float left = firstLeft;
|
||||
float right = firstRight + 1;
|
||||
|
||||
float xOff = (c % 16) * 16 + left;
|
||||
float yOff = ((c & 0xFF) / 16) * 16;
|
||||
float xOff = c % 16 * 16 + left;
|
||||
float yOff = (c & 0xFF) / 16 * 16;
|
||||
float width = right - left - .02f;
|
||||
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
Tesselator *t = Tesselator::getInstance();
|
||||
t->begin(GL_TRIANGLE_STRIP);
|
||||
t->tex(xOff / 256.0F, yOff / 256.0F);
|
||||
t->vertex(xPos, yPos, 0.0f);
|
||||
@@ -848,17 +735,5 @@ void Font::renderUnicodeCharacter(wchar_t c)
|
||||
|
||||
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,10 +18,6 @@ private:
|
||||
|
||||
Textures *textures;
|
||||
|
||||
int unicodeTexID[256];
|
||||
unsigned char unicodeWidth[65536];
|
||||
int lastBoundTexture;
|
||||
|
||||
float xPos;
|
||||
float yPos;
|
||||
|
||||
@@ -74,18 +70,10 @@ private:
|
||||
void drawLiteral(const wstring& str, int x, int y, int color); // no § parsing
|
||||
int MapCharacter(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:
|
||||
int width(const wstring& str);
|
||||
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);
|
||||
void drawWordWrap(const wstring &string, int x, int y, int w, int col, int h); // 4J Added h param
|
||||
|
||||
|
||||
@@ -359,17 +359,14 @@ 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)
|
||||
{
|
||||
//m_fov=fov;
|
||||
mc->options->set(Options::Option::FOV, (fov - 70) / 40);
|
||||
m_fov=fov;
|
||||
}
|
||||
|
||||
float GameRenderer::GetFovVal()
|
||||
{
|
||||
return 70 + mc->options->fov * 40;//m_fov;
|
||||
return m_fov;
|
||||
}
|
||||
|
||||
void GameRenderer::tickFov()
|
||||
@@ -393,11 +390,9 @@ float GameRenderer::getFov(float a, bool applyEffects)
|
||||
shared_ptr<LocalPlayer> player = dynamic_pointer_cast<LocalPlayer>(mc->cameraTargetPlayer);
|
||||
int playerIdx = player ? player->GetXboxPad() : 0;
|
||||
float fov = m_fov;//70;
|
||||
if (fov < 1) fov = 1; // Crash fix
|
||||
|
||||
if (applyEffects)
|
||||
{
|
||||
fov += mc->options->fov * 40;
|
||||
//fov += mc->options->fov * 40;
|
||||
fov *= oFov[playerIdx] + (this->fov[playerIdx] - oFov[playerIdx]) * a;
|
||||
}
|
||||
if (player->getHealth() <= 0)
|
||||
|
||||
@@ -499,10 +499,11 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
||||
|
||||
int y0 = 0;
|
||||
|
||||
//if (minecraft->level->getLevelData()->isHardcore())
|
||||
//{
|
||||
// y0 = 5;
|
||||
//}
|
||||
// No hardcore on console
|
||||
/*if (minecraft->level.getLevelData().isHardcore())
|
||||
{
|
||||
y0 = 5;
|
||||
}*/
|
||||
|
||||
blit(xo, yo, 16 + bg * 9, 9 * y0, 9, 9);
|
||||
if (blink)
|
||||
@@ -853,11 +854,10 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
||||
// font.draw(str, x + 1, y, 0xffffff);
|
||||
// }
|
||||
|
||||
|
||||
lastTickA = a;
|
||||
// 4J Stu - This is now displayed in a xui scene
|
||||
#if 0
|
||||
// Jukebox CD message
|
||||
// Jukebox CD message
|
||||
if (overlayMessageTime > 0)
|
||||
{
|
||||
float t = overlayMessageTime - a;
|
||||
@@ -1065,7 +1065,7 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
|
||||
vector<wstring> lines;
|
||||
|
||||
// Only show version/branch for player 0 to avoid cluttering each splitscreen viewport
|
||||
if (iPad == 0 && ClientConstants::SHOW_VERSION_WATERMARK)
|
||||
if (iPad == 0)
|
||||
{
|
||||
lines.push_back(ClientConstants::VERSION_STRING);
|
||||
lines.push_back(ClientConstants::BRANCH_STRING);
|
||||
@@ -1386,9 +1386,6 @@ void Gui::clearMessages(int iPad)
|
||||
|
||||
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
|
||||
//int iScale=1;
|
||||
|
||||
@@ -1610,7 +1607,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 + 0.5f), static_cast<float>(0));
|
||||
}
|
||||
}
|
||||
|
||||
if( dataB != NULL )
|
||||
{
|
||||
|
||||
@@ -110,11 +110,6 @@ void GuiComponent::drawStringLiteral(Font *font, const wstring& str, int x, int
|
||||
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)
|
||||
{
|
||||
float us = 1 / 256.0f;
|
||||
|
||||
@@ -16,6 +16,5 @@ public:
|
||||
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 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);
|
||||
};
|
||||
|
||||
@@ -6894,22 +6894,6 @@ 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)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||
</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">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||
@@ -29639,22 +29623,6 @@ 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)'=='CONTENTPACKAGE_SYMBOLS|PSVita'">false</ExcludedFromBuild>
|
||||
</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">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Xbox 360'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|Xbox 360'">true</ExcludedFromBuild>
|
||||
|
||||
@@ -2953,9 +2953,6 @@
|
||||
<ClInclude Include="Common\UI\UIBitmapFont.h">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\UI\UIUnicodeBitmapFont.h">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\UI\UITTFFont.h">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClInclude>
|
||||
@@ -5202,9 +5199,6 @@
|
||||
<ClCompile Include="Common\UI\UIBitmapFont.cpp">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\UI\UIUnicodeBitmapFont.cpp">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\UI\UITTFFont.cpp">
|
||||
<Filter>Common\Source Files\UI</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
""
|
||||
{
|
||||
"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,11 +73,6 @@
|
||||
#include "Common\UI\UIFontData.h"
|
||||
#include "DLCTexturePack.h"
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "Windows64/stb_image_write.h"
|
||||
#endif
|
||||
|
||||
#ifdef __ORBIS__
|
||||
#include "Orbis\Network\PsPlusUpsellWrapper_Orbis.h"
|
||||
#endif
|
||||
@@ -1554,9 +1549,6 @@ void Minecraft::run_middle()
|
||||
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
|
||||
if(g_KBMInput.IsKBMActive() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SNEAK))
|
||||
{
|
||||
@@ -3745,80 +3737,6 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
||||
//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))
|
||||
{
|
||||
ui.NavigateToScene(iPad,eUIScene_InGameInfoMenu);
|
||||
|
||||
@@ -561,7 +561,6 @@ MinecraftServer::MinecraftServer()
|
||||
m_serverPausedEvent = new C4JThread::Event;
|
||||
|
||||
m_saveOnExit = false;
|
||||
m_deleteWorldOnExit = false;
|
||||
m_suspending = false;
|
||||
|
||||
m_ugcPlayersVersion = 0;
|
||||
@@ -888,15 +887,6 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
|
||||
// }
|
||||
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?
|
||||
levels = ServerLevelArray(3);
|
||||
|
||||
@@ -1007,9 +997,6 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
LevelGenerationOptions *mapOptions = app.getLevelGenerationOptions();
|
||||
@@ -1655,7 +1642,7 @@ bool MinecraftServer::isNetherEnabled()
|
||||
|
||||
bool MinecraftServer::isHardcore()
|
||||
{
|
||||
return app.GetGameHostOption(eGameHostOption_Hardcore) > 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int MinecraftServer::getOperatorUserPermissionLevel()
|
||||
|
||||
@@ -265,8 +265,6 @@ private:
|
||||
private:
|
||||
// 4J Added
|
||||
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;
|
||||
|
||||
public:
|
||||
@@ -280,9 +278,6 @@ public:
|
||||
void chunkPacketManagement_PostTick();
|
||||
|
||||
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();
|
||||
bool IsSuspending();
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
""
|
||||
{
|
||||
"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,7 +25,6 @@
|
||||
#include "..\Minecraft.World\StringHelpers.h"
|
||||
#include "..\Minecraft.World\Socket.h"
|
||||
#include "..\Minecraft.World\Achievements.h"
|
||||
#include "..\Minecraft.World\LevelData.h"
|
||||
#include "..\Minecraft.World\net.minecraft.h"
|
||||
#include "EntityTracker.h"
|
||||
#include "ServerConnection.h"
|
||||
@@ -143,14 +142,6 @@ void PlayerConnection::tick()
|
||||
{
|
||||
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)
|
||||
@@ -1118,12 +1109,22 @@ void PlayerConnection::handleClientCommand(shared_ptr<ClientCommandPacket> packe
|
||||
{
|
||||
player = server->getPlayers()->respawn(player, player->m_enteredEndExitPortal?0:player->dimension, true);
|
||||
}
|
||||
else if (player->level->getLevelData()->isHardcore())
|
||||
{
|
||||
// Hardcore mode — server rejects respawn. Ban and disconnect are already
|
||||
// handled in ServerPlayer::die() via banPlayerForHardcoreDeath().
|
||||
return;
|
||||
}
|
||||
//else if (player.getLevel().getLevelData().isHardcore())
|
||||
//{
|
||||
// if (server.isSingleplayer() && player.name.equals(server.getSingleplayerName()))
|
||||
// {
|
||||
// player.connection.disconnect("You have died. Game over, man, it's game over!");
|
||||
// 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
|
||||
{
|
||||
if (player->getHealth() > 0) return;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "ConsoleInputSource.h"
|
||||
#include "..\Minecraft.World\PacketListener.h"
|
||||
#include "..\Minecraft.World\JavaIntHash.h"
|
||||
#include <atomic>
|
||||
|
||||
class MinecraftServer;
|
||||
class Connection;
|
||||
@@ -131,8 +130,8 @@ public:
|
||||
|
||||
void setShowOnMaps(bool bVal);
|
||||
|
||||
void setWasKicked() { m_bWasKicked.store(true); }
|
||||
bool getWasKicked() { return m_bWasKicked.load(); }
|
||||
void setWasKicked() { m_bWasKicked = true; }
|
||||
bool getWasKicked() { return m_bWasKicked; }
|
||||
|
||||
// 4J Added
|
||||
bool hasClientTickedOnce() { return m_bHasClientTickedOnce; }
|
||||
@@ -141,5 +140,5 @@ private:
|
||||
bool m_bCloseOnTick;
|
||||
vector<wstring> m_texturesRequested;
|
||||
|
||||
std::atomic<bool> m_bWasKicked{false};
|
||||
bool m_bWasKicked;
|
||||
};
|
||||
@@ -39,10 +39,6 @@
|
||||
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
#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;
|
||||
#endif
|
||||
|
||||
@@ -71,7 +67,6 @@ PlayerList::PlayerList(MinecraftServer *server)
|
||||
int rawMax = server->settings->getInt(L"max-players", 8);
|
||||
maxPlayers = static_cast<unsigned int>(Mth::clamp(rawMax, 1, MINECRAFT_NET_MAX_PLAYERS));
|
||||
doWhiteList = false;
|
||||
InitializeCriticalSection(&m_banCS);
|
||||
InitializeCriticalSection(&m_kickPlayersCS);
|
||||
InitializeCriticalSection(&m_closePlayersCS);
|
||||
}
|
||||
@@ -85,7 +80,6 @@ PlayerList::~PlayerList()
|
||||
player->gameMode = nullptr;
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&m_banCS);
|
||||
DeleteCriticalSection(&m_kickPlayersCS);
|
||||
DeleteCriticalSection(&m_closePlayersCS);
|
||||
}
|
||||
@@ -277,8 +271,7 @@ bool PlayerList::placeNewPlayer(Connection *connection, shared_ptr<ServerPlayer>
|
||||
static_cast<BYTE>(playerIndex), level->useNewSeaLevel(),
|
||||
player->getAllPlayerGamePrivileges(),
|
||||
level->getLevelData()->getXZSize(),
|
||||
level->getLevelData()->getHellScale(),
|
||||
level->getLevelData()->isHardcore()));
|
||||
level->getLevelData()->getHellScale()));
|
||||
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<SetCarriedItemPacket>(player->inventory->selected));
|
||||
@@ -709,13 +702,6 @@ shared_ptr<ServerPlayer> PlayerList::respawn(shared_ptr<ServerPlayer> serverPlay
|
||||
// necessary)
|
||||
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 the player is still alive and respawning to the same dimension, they are just being added back from someone else viewing the Win screen
|
||||
@@ -753,7 +739,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->gameMode->getGameModeForPlayer(), level->difficulty, level->getLevelData()->getGenerator(),
|
||||
player->level->useNewSeaLevel(), player->entityId, level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale(), level->getLevelData()->isHardcore() ) );
|
||||
player->level->useNewSeaLevel(), player->entityId, level->getLevelData()->getXZSize(), level->getLevelData()->getHellScale() ) );
|
||||
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) );
|
||||
|
||||
@@ -870,7 +856,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->gameMode->getGameModeForPlayer(), newLevel->difficulty, newLevel->getLevelData()->getGenerator(),
|
||||
newLevel->useNewSeaLevel(), player->entityId, newLevel->getLevelData()->getXZSize(), newLevel->getLevelData()->getHellScale(), newLevel->getLevelData()->isHardcore()));
|
||||
newLevel->useNewSeaLevel(), player->entityId, newLevel->getLevelData()->getXZSize(), newLevel->getLevelData()->getHellScale()));
|
||||
|
||||
oldLevel->removeEntityImmediately(player);
|
||||
player->removed = false;
|
||||
@@ -1684,7 +1670,6 @@ bool PlayerList::isXuidBanned(PlayerUID xuid)
|
||||
|
||||
bool banned = false;
|
||||
|
||||
EnterCriticalSection(&m_banCS);
|
||||
for(PlayerUID it : m_bannedXuids)
|
||||
{
|
||||
if( ProfileManager.AreXUIDSEqual( xuid, it ) )
|
||||
@@ -1693,7 +1678,6 @@ bool PlayerList::isXuidBanned(PlayerUID xuid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m_banCS);
|
||||
|
||||
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
|
||||
if (!banned && g_Win64DedicatedServer)
|
||||
@@ -1705,107 +1689,6 @@ bool PlayerList::isXuidBanned(PlayerUID xuid)
|
||||
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
|
||||
void PlayerList::setViewDistance(int newViewDistance)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,6 @@ private:
|
||||
|
||||
// 4J Added
|
||||
vector<PlayerUID> m_bannedXuids;
|
||||
CRITICAL_SECTION m_banCS; // 4J Added - protects m_bannedXuids for concurrent access
|
||||
deque<BYTE> m_smallIdsToKick;
|
||||
CRITICAL_SECTION m_kickPlayersCS;
|
||||
deque<BYTE> m_smallIdsToClose;
|
||||
@@ -136,8 +135,6 @@ public:
|
||||
void closePlayerConnectionBySmallId(BYTE networkSmallId);
|
||||
void queueSmallIdForRecycle(BYTE smallId);
|
||||
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
|
||||
void setViewDistance(int newViewDistance);
|
||||
};
|
||||
|
||||
@@ -303,12 +303,6 @@ void SelectWorldScreen::WorldSelectionList::renderItem(int i, int x, int y, int
|
||||
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, id, x + 2, y + 12, 0x808080);
|
||||
parent->drawString(parent->font, info, x + 2, y + 12 + 10, 0x808080);
|
||||
|
||||
@@ -569,17 +569,6 @@ void ServerPlayer::die(DamageSource *source)
|
||||
{
|
||||
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))
|
||||
{
|
||||
inventory->dropAll();
|
||||
@@ -1620,9 +1609,9 @@ bool ServerPlayer::hasPermission(EGameCommand command)
|
||||
//
|
||||
// // 4J - Don't need
|
||||
// //if (server.isSingleplayer() && server.getSingleplayerName().equals(name))
|
||||
/// //{
|
||||
// //{
|
||||
// // server.setDifficulty(packet.getDifficulty());
|
||||
/// //}
|
||||
// //}
|
||||
//}
|
||||
|
||||
int ServerPlayer::getViewDistance()
|
||||
|
||||
@@ -34,8 +34,10 @@ public:
|
||||
static const int KEY_DEBUG_MENU = VK_F4;
|
||||
static const int KEY_THIRD_PERSON = VK_F5;
|
||||
static const int KEY_DEBUG_CONSOLE = VK_F6;
|
||||
static const int KEY_HOST_SETTINGS = VK_TAB;
|
||||
static const int KEY_HOST_SETTINGS = VK_F8;
|
||||
static const int KEY_FULLSCREEN = VK_F11;
|
||||
|
||||
// todo: implement and shi
|
||||
static const int KEY_SCREENSHOT = VK_F2;
|
||||
|
||||
void Init();
|
||||
|
||||
@@ -506,7 +506,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
case WM_PAINT:
|
||||
@@ -563,7 +563,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
else if (vk == VK_MENU)
|
||||
vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU;
|
||||
g_KBMInput.OnKeyDown(vk);
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
@@ -661,7 +661,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -673,23 +673,23 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
//
|
||||
ATOM MyRegisterClass(HINSTANCE hInstance)
|
||||
{
|
||||
WNDCLASSEXW wcex;
|
||||
WNDCLASSEX wcex;
|
||||
|
||||
wcex.cbSize = sizeof(WNDCLASSEXW);
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = WndProc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = hInstance;
|
||||
wcex.hIcon = LoadIconW(hInstance, L"Minecraft");
|
||||
wcex.hIcon = LoadIcon(hInstance, "Minecraft");
|
||||
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
|
||||
wcex.lpszMenuName = L"Minecraft";
|
||||
wcex.lpszClassName = L"MinecraftClass";
|
||||
wcex.lpszMenuName = "Minecraft";
|
||||
wcex.lpszClassName = "MinecraftClass";
|
||||
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_MINECRAFTWINDOWS));
|
||||
|
||||
return RegisterClassExW(&wcex);
|
||||
return RegisterClassEx(&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
|
||||
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
|
||||
|
||||
g_hWnd = CreateWindowW( L"MinecraftClass",
|
||||
L"Minecraft",
|
||||
g_hWnd = CreateWindow( "MinecraftClass",
|
||||
"Minecraft",
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
0,
|
||||
|
||||