41 Commits

Author SHA1 Message Date
mschiller890
4b6039d8a4 Added JoinByIPScreen.cpp to the source list 2026-03-11 20:16:35 +02:00
mschiller890
1e908423d5 Replaced std::stoi(port) with atoi(port.c_str()) call because of Android NDK 2026-03-11 20:15:15 +02:00
InviseDivine
4bd3821ff6 Update project/dedicated_server/CMakeLists.txt
change to yours
2026-03-11 19:55:38 +02:00
InviseDivine
28a49debcf Merge branch 'main' of https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1 2026-03-11 19:52:59 +02:00
InviseDivine
d2a5f4755c remove std stoi 2026-03-11 19:52:25 +02:00
mschiller890
7f3af5c98a Implemented openURL for android and updated init logic 2026-03-11 19:40:13 +02:00
mschiller890
d82d19be68 Updated the Discord link (and removed color tags cuz they were messing up the URL) 2026-03-11 19:38:53 +02:00
mschiller890
33590751c5 Added openURL(String) helper 2026-03-11 19:37:10 +02:00
mschiller890
a80d2ee847 Fix NPE in MainActivity.onDialogCompleted by guarding showSoftInput call with null focus check 2026-03-11 19:10:08 +02:00
InviseDivine
8875342557 Join by ip screen 2026-03-11 19:04:54 +02:00
InviseDivine
933ef9c988 Update README.md 2026-03-11 15:54:33 +02:00
mschiller890
09d28be195 Updated Android build version from 0.4.0 to 0.6.1-alpha-<build> 2026-03-11 12:49:04 +02:00
mschiller890
ffd9dda611 Upload files to "project/android" 2026-03-11 12:47:57 +02:00
mschiller890
6ed2d40edc Update build.ps1 2026-03-11 12:46:16 +02:00
mschiller890
ce6a987651 Game now asks for storage permission during runtime 2026-03-11 12:31:51 +02:00
mschiller890
23cdc15285 Bumped minSdk to 24 2026-03-11 12:27:36 +02:00
mschiller890
904bf68cd6 Bumped minSdk to 24 2026-03-11 12:27:11 +02:00
mschiller890
e529bd5d64 Fixed Done button not working and backspace on Android 2026-03-11 12:21:09 +02:00
mschiller890
099b560273 oopsie 2026-03-11 12:19:48 +02:00
mschiller890
2d70b68b73 Fixed Done button not working and backspace on Android 2026-03-11 11:03:06 +02:00
mschiller890
01f78eabc7 Upload files to "src" 2026-03-11 11:01:29 +02:00
Kolyah35
99164a781d whoops 2026-03-11 02:30:38 +03:00
Kolyah35
d25a04f154 REMOVE: license verification and BuyGame btns/screens 2026-03-11 00:39:27 +03:00
Kolyah35
3c71139a7c FIX: human readable world date 2026-03-10 23:58:20 +03:00
Kolyah35
9991ba312d FIX: improve textbox 2026-03-10 23:36:12 +03:00
Kolyah35
11d5551d02 Merge remote-tracking branch 'refs/remotes/origin/main' 2026-03-10 23:27:15 +03:00
Kolyah35
d0939875fc FIX: improve create world screen 2026-03-10 23:26:02 +03:00
InviseDivine
da1906f94b Fix: linux open links 2026-03-10 22:14:39 +02:00
InviseDivine
04f13ab4a7 Fix: gui, block destroy
Feat: speed up on left mouse button in credits
2026-03-10 22:06:28 +02:00
InviseDivine
2d17f9d152 Ported to textfield 2026-03-10 21:37:12 +02:00
Kolyah35
ae84705332 Merge pull request 'A lot of stuff.' (#1) from mschiller890/minecraft-pe-0.6.1:alotofstuff into main
Reviewed-on: https://192.168.0.2:3000/Kolyah35/minecraft-pe-0.6.1/pulls/1
2026-03-10 21:07:27 +02:00
mschiller890
12b30c245a Update README.md 2026-03-10 21:00:09 +02:00
mschiller890
7345f68aee Update README.md 2026-03-10 20:59:27 +02:00
mschiller890
311e97bd77 Update README.md 2026-03-10 20:40:41 +02:00
mschiller890
6d43273b18 Update README.md 2026-03-10 20:36:33 +02:00
Michal Schiller
2fc323639a Fixes and enhancements from my MCPE repository. (https://github.com/mschiller890/mcpe64) 2026-03-10 19:31:40 +01:00
Kolyah35
0c97ceb340 TextBox / removed BuyButton / impoved CreateWorldScreen 2026-03-10 02:51:32 +03:00
InviseDivine
65d25748db no sound define 2026-03-09 21:15:55 +02:00
InviseDivine
8a53d3432d Fix: Creative mode flying and cheats enabled 2026-03-09 20:40:07 +02:00
InviseDivine
5311b134ac Fix: Block destroy 2026-03-09 19:14:38 +02:00
InviseDivine
310ff754ee Update README.md 2026-03-09 16:14:47 +02:00
85 changed files with 3081 additions and 942 deletions

201
.gitignore vendored
View File

@@ -1,3 +1,202 @@
# Build output
build/ build/
linux-build/ out/
bin/
lib/
cmake-build-*/
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
Makefile
*.cmake
!cmake/CPM.cmake
# Compiled object files
*.o
*.obj
*.a
*.lib
*.so
*.dylib
*.dll
*.exe
*.out
# CMake generated
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_CPack_Packages/
*.cbp
# Visual Studio
*.sdf
*.suo
*.user
*.userosscache
*.sln.docstates
*.VC.db
*.VC.opendb
.vs/
ipch/
x64/
x86/
Debug/
Release/
RelWithDebInfo/
MinSizeRel/
# Xcode
*.xcworkspace
xcuserdata/
*.xccheckout
*.moved-aside
DerivedData/
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
# Android
*.apk
*.aab
*.ap_
local.properties
.gradle/
project/.gradle/
project/android/bin/
project/android/gen/
project/android/obj/
project/android_java/bin/
project/android_java/gen/
project/android_java/obj/
project/android/libs/*.so
# macOS
.DS_Store
.AppleDouble
.LSOverride
._*
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
# Linux
*~
.nfs*
# CLion / JetBrains
.idea/
*.iml
*.ipr
*.iws
# Eclipse CDT
.project
.cproject
.settings/
# Logs
*.log
# Ninja
.ninja_deps
.ninja_log
build.ninja
# VS Code
.vscode/
*.code-workspace
# Visual Studio additional
*.ncb
*.aps
*.pdb
*.ilk
*.exp
*.iobj
*.ipdb
*.tlog
*.lastbuildstate
*.pch
*.ipch
*.VC.db-shm
*.VC.db-wal
*.svclog
*.vcxproj.user
# CMake generated project files
ALL_BUILD.vcxproj
ALL_BUILD.vcxproj.filters
INSTALL.vcxproj
INSTALL.vcxproj.filters
PACKAGE.vcxproj
PACKAGE.vcxproj.filters
ZERO_CHECK.vcxproj
ZERO_CHECK.vcxproj.filters
MinecraftPE.vcxproj
MinecraftPE.vcxproj.filters
MinecraftPE.sln
CPackConfig.cmake
CPackSourceConfig.cmake
cpm-package-lock.cmake
MinecraftPE.dir/
_deps/
# Test / coverage
Testing/
CTestResults/
*.gcno
*.gcda
*.gcov
coverage/
lcov.info
# Precompiled headers
*.gch
# Compiler / linker intermediates
*.map
*.res
*.d
# Patch / diff leftovers
*.orig
*.rej
*.patch
# Backup / temp
*.bak
*.swp
*.swo
*.tmp
*~.nib
# Tags
tags
TAGS
.tags
ctags
# macOS extra
.Spotlight-V100
.Trashes
.fseventsd
Icon\r
# Windows extra
*.lnk
[Dd]esktop.ini
# User / local config
options.txt
local.cmake
games/
# Dependency cache
vcpkg_installed/
.cache/ .cache/
conan/

View File

@@ -5,11 +5,11 @@ include(cmake/CPM.cmake)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_POLICY_VERSION_MINIMUM 3.10)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "-Wno-c++11-narrowing -Wno-invalid-source-encoding -Wno-reserved-user-defined-literal") set(CMAKE_CXX_FLAGS "-Wno-c++11-narrowing -Wno-narrowing -Wno-invalid-source-encoding -Wno-reserved-user-defined-literal")
endif() endif()
find_package(Threads REQUIRED)
CPMAddPackage("gh:madler/zlib@1.3.2") CPMAddPackage("gh:madler/zlib@1.3.2")
CPMAddPackage( CPMAddPackage(
NAME "libpng" NAME "libpng"
@@ -44,8 +44,189 @@ CPMAddPackage(
"GLFW_BUILD_DOCS OFF" "GLFW_BUILD_DOCS OFF"
"BUILD_SHARED_LIBS ON" "BUILD_SHARED_LIBS ON"
) )
# TODO: Clear this paths with *
file(GLOB SERVER_SOURCES
"src/NinecraftApp.cpp"
"src/Performance.cpp"
"src/SharedConstants.cpp"
file(GLOB SOURCES "src/client/IConfigListener.cpp"
"src/client/Minecraft.cpp"
"src/client/OptionStrings.cpp"
"src/client/Options.cpp"
"src/client/OptionsFile.cpp"
"src/client/gamemode/CreativeMode.cpp"
"src/client/gamemode/GameMode.cpp"
"src/client/gamemode/SurvivalMode.cpp"
"src/client/player/LocalPlayer.cpp"
"src/client/player/RemotePlayer.cpp"
"src/client/player/input/KeyboardInput.cpp"
"src/locale/I18n.cpp"
"src/main.cpp"
"src/main_dedicated.cpp"
"src/nbt/Tag.cpp"
"src/network/ClientSideNetworkHandler.cpp"
"src/network/NetEventCallback.cpp"
"src/network/Packet.cpp"
"src/network/RakNetInstance.cpp"
"src/network/ServerSideNetworkHandler.cpp"
"src/network/command/CommandServer.cpp"
"src/platform/CThread.cpp"
"src/platform/time.cpp"
"src/platform/input/Controller.cpp"
"src/platform/input/Keyboard.cpp"
"src/platform/input/Mouse.cpp"
"src/platform/input/Multitouch.cpp"
"src/server/ArgumentsSettings.cpp"
"src/server/ServerLevel.cpp"
"src/server/ServerPlayer.cpp"
"src/util/DataIO.cpp"
"src/util/Mth.cpp"
"src/util/PerfTimer.cpp"
"src/util/StringUtils.cpp"
"src/world/Direction.cpp"
"src/world/entity/AgableMob.cpp"
"src/world/entity/Entity.cpp"
"src/world/entity/EntityFactory.cpp"
"src/world/entity/FlyingMob.cpp"
"src/world/entity/HangingEntity.cpp"
"src/world/entity/Mob.cpp"
"src/world/entity/MobCategory.cpp"
"src/world/entity/Motive.cpp"
"src/world/entity/Painting.cpp"
"src/world/entity/PathfinderMob.cpp"
"src/world/entity/SynchedEntityData.cpp"
"src/world/entity/ai/control/MoveControl.cpp"
"src/world/entity/animal/Animal.cpp"
"src/world/entity/animal/Chicken.cpp"
"src/world/entity/animal/Cow.cpp"
"src/world/entity/animal/Pig.cpp"
"src/world/entity/animal/Sheep.cpp"
"src/world/entity/animal/WaterAnimal.cpp"
"src/world/entity/item/FallingTile.cpp"
"src/world/entity/item/ItemEntity.cpp"
"src/world/entity/item/PrimedTnt.cpp"
"src/world/entity/item/TripodCamera.cpp"
"src/world/entity/monster/Creeper.cpp"
"src/world/entity/monster/Monster.cpp"
"src/world/entity/monster/PigZombie.cpp"
"src/world/entity/monster/Skeleton.cpp"
"src/world/entity/monster/Spider.cpp"
"src/world/entity/monster/Zombie.cpp"
"src/world/entity/player/Inventory.cpp"
"src/world/entity/player/Player.cpp"
"src/world/entity/projectile/Arrow.cpp"
"src/world/entity/projectile/Throwable.cpp"
"src/world/food/SimpleFoodData.cpp"
"src/world/inventory/BaseContainerMenu.cpp"
"src/world/inventory/ContainerMenu.cpp"
"src/world/inventory/FillingContainer.cpp"
"src/world/inventory/FurnaceMenu.cpp"
"src/world/item/ArmorItem.cpp"
"src/world/item/BedItem.cpp"
"src/world/item/DyePowderItem.cpp"
"src/world/item/HangingEntityItem.cpp"
"src/world/item/HatchetItem.cpp"
"src/world/item/HoeItem.cpp"
"src/world/item/Item.cpp"
"src/world/item/ItemInstance.cpp"
"src/world/item/PickaxeItem.cpp"
"src/world/item/ShovelItem.cpp"
"src/world/item/crafting/ArmorRecipes.cpp"
"src/world/item/crafting/FurnaceRecipes.cpp"
"src/world/item/crafting/OreRecipes.cpp"
"src/world/item/crafting/Recipe.cpp"
"src/world/item/crafting/Recipes.cpp"
"src/world/item/crafting/StructureRecipes.cpp"
"src/world/item/crafting/ToolRecipes.cpp"
"src/world/item/crafting/WeaponRecipes.cpp"
"src/world/level/Explosion.cpp"
"src/world/level/Level.cpp"
"src/world/level/LightLayer.cpp"
"src/world/level/LightUpdate.cpp"
"src/world/level/MobSpawner.cpp"
"src/world/level/Region.cpp"
"src/world/level/TickNextTickData.cpp"
"src/world/level/biome/Biome.cpp"
"src/world/level/biome/BiomeSource.cpp"
"src/world/level/chunk/LevelChunk.cpp"
"src/world/level/dimension/Dimension.cpp"
"src/world/level/levelgen/CanyonFeature.cpp"
"src/world/level/levelgen/DungeonFeature.cpp"
"src/world/level/levelgen/LargeCaveFeature.cpp"
"src/world/level/levelgen/LargeFeature.cpp"
"src/world/level/levelgen/RandomLevelSource.cpp"
"src/world/level/levelgen/feature/Feature.cpp"
"src/world/level/levelgen/synth/ImprovedNoise.cpp"
"src/world/level/levelgen/synth/PerlinNoise.cpp"
"src/world/level/levelgen/synth/Synth.cpp"
"src/world/level/material/Material.cpp"
"src/world/level/pathfinder/Path.cpp"
"src/world/level/storage/ExternalFileLevelStorage.cpp"
"src/world/level/storage/ExternalFileLevelStorageSource.cpp"
"src/world/level/storage/FolderMethods.cpp"
"src/world/level/storage/LevelData.cpp"
"src/world/level/storage/LevelStorageSource.cpp"
"src/world/level/storage/RegionFile.cpp"
"src/world/level/tile/BedTile.cpp"
"src/world/level/tile/ChestTile.cpp"
"src/world/level/tile/CropTile.cpp"
"src/world/level/tile/DoorTile.cpp"
"src/world/level/tile/EntityTile.cpp"
"src/world/level/tile/FurnaceTile.cpp"
"src/world/level/tile/GrassTile.cpp"
"src/world/level/tile/HeavyTile.cpp"
"src/world/level/tile/LightGemTile.cpp"
"src/world/level/tile/MelonTile.cpp"
"src/world/level/tile/Mushroom.cpp"
"src/world/level/tile/NetherReactor.cpp"
"src/world/level/tile/NetherReactorPattern.cpp"
"src/world/level/tile/StairTile.cpp"
"src/world/level/tile/StemTile.cpp"
"src/world/level/tile/StoneSlabTile.cpp"
"src/world/level/tile/TallGrass.cpp"
"src/world/level/tile/Tile.cpp"
"src/world/level/tile/TrapDoorTile.cpp"
"src/world/level/tile/entity/ChestTileEntity.cpp"
"src/world/level/tile/entity/FurnaceTileEntity.cpp"
"src/world/level/tile/entity/NetherReactorTileEntity.cpp"
"src/world/level/tile/entity/SignTileEntity.cpp"
"src/world/level/tile/entity/TileEntity.cpp"
"src/world/phys/HitResult.cpp"
)
file(GLOB CLIENT_SOURCES
"src/client/*.cpp" "src/client/*.cpp"
"src/client/gamemode/*.cpp" "src/client/gamemode/*.cpp"
@@ -129,18 +310,29 @@ endif()
if(PLATFORM STREQUAL "PLATFORM_WIN32") if(PLATFORM STREQUAL "PLATFORM_WIN32")
list(APPEND SOURCES "src/AppPlatform_win32.cpp") list(APPEND CLIENT_SOURCES "src/AppPlatform_win32.cpp")
endif() endif()
if(PLATFORM STREQUAL "PLATFORM_GLFW") if(PLATFORM STREQUAL "PLATFORM_GLFW")
list(APPEND SOURCES "src/AppPlatform_glfw.cpp") list(APPEND CLIENT_SOURCES "src/AppPlatform_glfw.cpp")
endif() endif()
# Explicitly list files added after the initial glob so they are always included
list(APPEND CLIENT_SOURCES
"src/client/gui/screens/ConsoleScreen.cpp"
"src/client/gui/screens/UsernameScreen.cpp"
"src/client/gui/screens/CreditsScreen.cpp"
)
add_executable(${PROJECT_NAME} add_executable(${PROJECT_NAME}
${SOURCES} ${CLIENT_SOURCES}
"glad/src/glad.c" "glad/src/glad.c"
) )
#add_executable("${PROJECT_NAME}-server"
# ${SERVER_SOURCES}
#)
if(WIN32) if(WIN32)
set(EXTRA_LIBS "ws2_32") set(EXTRA_LIBS "ws2_32")
target_compile_definitions(${PROJECT_NAME} PUBLIC "_CRT_SECURE_NO_WARNINGS") target_compile_definitions(${PROJECT_NAME} PUBLIC "_CRT_SECURE_NO_WARNINGS")
@@ -150,6 +342,7 @@ if(PLATFORM STREQUAL "PLATFORM_WIN32" OR PLATFORM STREQUAL "PLATFORM_GLFW")
target_compile_definitions(${PROJECT_NAME} PUBLIC "PLATFORM_DESKTOP") target_compile_definitions(${PROJECT_NAME} PUBLIC "PLATFORM_DESKTOP")
endif() endif()
target_include_directories(${PROJECT_NAME} PUBLIC target_include_directories(${PROJECT_NAME} PUBLIC
"${CMAKE_SOURCE_DIR}/glad/include/" "${CMAKE_SOURCE_DIR}/glad/include/"
"${CMAKE_SOURCE_DIR}/src" "${CMAKE_SOURCE_DIR}/src"
@@ -158,6 +351,16 @@ target_include_directories(${PROJECT_NAME} PUBLIC
"lib/include" "lib/include"
) )
# Server
#target_link_libraries("${PROJECT_NAME}-server" PRIVATE
# raknet ${CMAKE_THREAD_LIBS_INIT})
#target_compile_definitions("${PROJECT_NAME}-server" PUBLIC "STANDALONE_SERVER")
#target_include_directories("${PROJECT_NAME}-server" PUBLIC
# "${CMAKE_SOURCE_DIR}/src/"
#)
# Client
target_compile_definitions(${PROJECT_NAME} PUBLIC "OPENGL_ES" "NO_EGL" ${PLATFORM}) target_compile_definitions(${PROJECT_NAME} PUBLIC "OPENGL_ES" "NO_EGL" ${PLATFORM})
target_link_libraries(${PROJECT_NAME} zlib png_shared alsoft.common OpenAL::OpenAL glfw ${EXTRA_LIBS}) target_link_libraries(${PROJECT_NAME} zlib png_shared alsoft.common OpenAL::OpenAL glfw ${EXTRA_LIBS})

View File

@@ -1,21 +1,56 @@
# MinecraftPE # MinecraftPE
> [!Important]
> We have a discord server, where you can report bugs or send feedback https://discord.gg/c58YesBxve
This is leaked source code of Minecraft PE 0.6.1 with my own impovements :sunglasses: Source code for **Minecraft Pocket Edition 0.6.1 alpha** with various fixes and improvements.
First of all I made it build with CMake (w/o VS2012). Also I fixed some compile errors. And finally I ported it to GLFW to make it run on several platforms and remove binary dependencies. This project aims to preserve and improve this early version of Minecraft PE.
# TODO # TODO / Roadmap
- [x] Add platform GLFW - [x] Add platform GLFW
- [x] Compile for Linux - [x] Compile for Linux
- [ ] Compile for android aarch64 - [x] Compile for android aarch64
- [x] Touch control improvements
- [ ] Screen fixes
- [ ] Rewrite platform logic - [ ] Rewrite platform logic
- [x] Fix sound - [x] Fix sound
- [ ] Do a server connection gui - [ ] Do a server connection GUI
- [ ] Controller support
- [ ] Minecraft server hosting
- [x] Screen fixess
- [x] Fix fog
- [x] Add sprinting
- [x] Chat (semi working) and commands
- [x] Implementing options
- [x] Better F3
# Build # Build
## CMake ## CMake
``` ```
mkdir build && cd build mkdir build && cd build
cmake .. -B . cmake .. -B .
make -j4 make -j4
``` ```
## Visual Studio
1. Open the repository folder in **Visual Studio**.
2. Visual Studio will automatically detect the `CMakeLists.txt` file and generate the project configuration.
3. Set **MinecraftPE.exe** as the **target**.
4. Press **Run** (or F5) to build and launch the game.
## Android
Download [r14b Android NDK](http://dl.google.com/android/repository/android-ndk-r14b-windows-x86_64.zip) and run `build.ps1`:
```
# Full build (NDK + Java + APK + install)
.\build.ps1
# Skip NDK recompile (Java/assets changed only)
.\build.ps1 -NoJava
# Skip Java recompile (C++ changed only)
.\build.ps1 -NoCpp
# Only repackage + install (no recompile at all)
.\build.ps1 -NoBuild
```

302
build.ps1 Normal file
View File

@@ -0,0 +1,302 @@
# ============================================================
# MCPE 0.6.1 Android Build Script — from-scratch capable
# Works on a clean machine; creates all dirs, keystore and
# stub Java files automatically.
#
# Usage:
# .\build.ps1 # full build (NDK + Java + APK + install)
# .\build.ps1 -NoCpp # skip NDK rebuild (Java/assets changed)
# .\build.ps1 -NoJava # skip Java recompile (C++ changed only)
# .\build.ps1 -NoBuild # repackage + install only (no recompile)
# ============================================================
param(
[switch]$NoCpp,
[switch]$NoJava,
[switch]$NoBuild
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
# ── Paths ────────────────────────────────────────────────────
$repo = $PSScriptRoot
$apkbuild = "C:\apkbuild"
$ndk = "C:\android-ndk-r14b"
$sdkTools = "$env:LOCALAPPDATA\Android\Sdk\build-tools\35.0.0"
$androidJar = "$env:LOCALAPPDATA\Android\Sdk\platforms\android-36\android.jar"
$adb = "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe"
$keystore = "$apkbuild\debug.keystore"
$pkg = "com.mojang.minecraftpe"
# Auto-detect keytool from JAVA_HOME, then from common install locations
$keytool = if ($env:JAVA_HOME) { "$env:JAVA_HOME\bin\keytool.exe" } else {
$found = Get-ChildItem "C:\Program Files\Java","C:\Program Files\Eclipse Adoptium" `
-Filter keytool.exe -Recurse -ErrorAction SilentlyContinue |
Sort-Object FullName -Descending | Select-Object -First 1 -ExpandProperty FullName
if (-not $found) { throw "keytool not found. Set JAVA_HOME or install a JDK." }
$found
}
$jniDir = "$repo\project\android\jni"
$libSrc = "$repo\project\android\libs\arm64-v8a\libminecraftpe.so"
$libDst = "$apkbuild\lib\arm64-v8a\libminecraftpe.so"
$manifest = "$repo\project\android_java\AndroidManifest.xml"
$res = "$repo\project\android_java\res"
$javaSrc = "$repo\project\android_java\src"
$stubsDir = "$apkbuild\stubs"
$rJava = "$apkbuild\gen\R.java"
$classesDir = "$apkbuild\classes"
$dexOut = "$apkbuild\classes.dex"
$dataDir = "$repo\data"
$unsigned = "$apkbuild\minecraftpe-unsigned.apk"
$aligned = "$apkbuild\minecraftpe-aligned.apk"
$signed = "$apkbuild\minecraftpe-debug.apk"
Add-Type -Assembly "System.IO.Compression.FileSystem"
function Write-Step([string]$msg) { Write-Host "`n==> $msg" -ForegroundColor Cyan }
function Assert-ExitCode([string]$step) {
if ($LASTEXITCODE -ne 0) { Write-Host "FAILED: $step (exit $LASTEXITCODE)" -ForegroundColor Red; exit 1 }
}
function New-Dir([string]$path) { New-Item $path -ItemType Directory -Force | Out-Null }
function Write-Stub([string]$rel, [string]$content) {
$full = "$stubsDir\$rel"
New-Dir (Split-Path $full -Parent)
if (-not (Test-Path $full)) { [System.IO.File]::WriteAllText($full, $content); Write-Host " stub: $rel" }
}
# ── 0. Bootstrap ─────────────────────────────────────────────
Write-Step "Bootstrap"
New-Dir $apkbuild
New-Dir "$apkbuild\lib\arm64-v8a"
New-Dir "$apkbuild\gen"
New-Dir $stubsDir
if (-not (Test-Path $keystore)) {
Write-Host " generating debug.keystore..."
$eap = $ErrorActionPreference; $ErrorActionPreference = "Continue"
& $keytool -genkeypair `
-keystore $keystore -storepass android -keypass android `
-alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 `
-dname "CN=Android Debug,O=Android,C=US" 2>&1 | Out-Null
$ErrorActionPreference = $eap
Assert-ExitCode "keytool"
Write-Host " keystore created"
} else { Write-Host " keystore OK" }
Write-Stub "com\mojang\android\StringValue.java" "package com.mojang.android;`npublic interface StringValue { String getStringValue(); }`n"
Write-Stub "com\mojang\android\licensing\LicenseCodes.java" "package com.mojang.android.licensing;`npublic class LicenseCodes { public static final int LICENSE_OK = 0; }`n"
Write-Stub "com\mojang\android\EditTextAscii.java" @"
package com.mojang.android;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.widget.EditText;
public class EditTextAscii extends EditText implements TextWatcher {
public EditTextAscii(Context c) { super(c); addTextChangedListener(this); }
public EditTextAscii(Context c, AttributeSet a) { super(c,a); addTextChangedListener(this); }
public EditTextAscii(Context c, AttributeSet a, int d) { super(c,a,d); addTextChangedListener(this); }
@Override public void onTextChanged(CharSequence s,int st,int b,int co){}
public void beforeTextChanged(CharSequence s,int st,int co,int aft){}
public void afterTextChanged(Editable e){
String s=e.toString(),san=sanitize(s);
if(!s.equals(san))e.replace(0,e.length(),san);
}
static public String sanitize(String s){
StringBuilder sb=new StringBuilder();
for(int i=0;i<s.length();i++){char c=s.charAt(i);if(c<128)sb.append(c);}
return sb.toString();
}
}
"@
Write-Stub "com\mojang\android\preferences\SliderPreference.java" @"
package com.mojang.android.preferences;
import android.content.Context;
import android.content.res.Resources;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
public class SliderPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
private static final String NS="http://schemas.android.com/apk/res/android";
private Context _ctx; private TextView _tv; private SeekBar _sb;
private String _suf; private int _def,_max,_val,_min;
public SliderPreference(Context ctx,AttributeSet a){
super(ctx,a); _ctx=ctx;
_suf=gStr(a,NS,"text",""); _def=gInt(a,NS,"defaultValue",0);
_max=gInt(a,NS,"max",100); _min=gInt(a,null,"min",0);
setDefaultValue(_def);
}
@Override protected View onCreateDialogView(){
LinearLayout l=new LinearLayout(_ctx); l.setOrientation(LinearLayout.VERTICAL); l.setPadding(6,6,6,6);
_tv=new TextView(_ctx); _tv.setGravity(Gravity.CENTER_HORIZONTAL); _tv.setTextSize(32);
l.addView(_tv,new LinearLayout.LayoutParams(-1,-2));
_sb=new SeekBar(_ctx); _sb.setOnSeekBarChangeListener(this);
l.addView(_sb,new LinearLayout.LayoutParams(-1,-2));
if(shouldPersist())_val=getPersistedInt(_def);
_sb.setMax(_max); _sb.setProgress(_val); return l;
}
@Override protected void onSetInitialValue(boolean r,Object d){
super.onSetInitialValue(r,d);
_val=r?(shouldPersist()?getPersistedInt(_def):0):(Integer)d;
}
public void onProgressChanged(SeekBar s,int v,boolean f){
_val=v+_min; _tv.setText(_val+_suf);
if(shouldPersist())persistInt(_val); callChangeListener(Integer.valueOf(_val));
}
public void onStartTrackingTouch(SeekBar s){}
public void onStopTrackingTouch(SeekBar s){}
private int gInt(AttributeSet a,String ns,String n,int d){int id=a.getAttributeResourceValue(ns,n,0);return id!=0?getContext().getResources().getInteger(id):a.getAttributeIntValue(ns,n,d);}
private String gStr(AttributeSet a,String ns,String n,String d){int id=a.getAttributeResourceValue(ns,n,0);if(id!=0)return getContext().getResources().getString(id);String v=a.getAttributeValue(ns,n);return v!=null?v:d;}
}
"@
Write-Stub "com\mojang\minecraftpe\MainMenuOptionsActivity.java" @"
package com.mojang.minecraftpe;
import android.app.Activity;
public class MainMenuOptionsActivity extends Activity {
public static final String Internal_Game_DifficultyPeaceful="internal_game_difficulty_peaceful";
public static final String Game_DifficultyLevel="game_difficulty";
public static final String Controls_Sensitivity="controls_sensitivity";
}
"@
Write-Stub "com\mojang\minecraftpe\Minecraft_Market.java" @"
package com.mojang.minecraftpe;
import android.app.Activity; import android.content.Intent; import android.os.Bundle;
public class Minecraft_Market extends Activity {
@Override protected void onCreate(Bundle s){super.onCreate(s);startActivity(new Intent(this,MainActivity.class));finish();}
}
"@
Write-Stub "com\mojang\minecraftpe\Minecraft_Market_Demo.java" @"
package com.mojang.minecraftpe;
import android.content.Intent; import android.net.Uri;
public class Minecraft_Market_Demo extends MainActivity {
@Override public void buyGame(){startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse("market://details?id=com.mojang.minecraftpe")));}
@Override protected boolean isDemo(){return true;}
}
"@
Write-Stub "com\mojang\minecraftpe\GameModeButton.java" @"
package com.mojang.minecraftpe;
import com.mojang.android.StringValue;
import android.content.Context; import android.util.AttributeSet;
import android.view.View; import android.view.View.OnClickListener;
import android.widget.TextView; import android.widget.ToggleButton;
public class GameModeButton extends ToggleButton implements OnClickListener,StringValue {
static final int Creative=0,Survival=1;
private int _type=0; private boolean _attached=false;
public GameModeButton(Context c,AttributeSet a){super(c,a);setOnClickListener(this);}
public void onClick(View v){_update();}
@Override protected void onFinishInflate(){super.onFinishInflate();_update();}
@Override protected void onAttachedToWindow(){if(!_attached){_update();_attached=true;}}
private void _update(){_set(isChecked()?Survival:Creative);}
private void _set(int i){
_type=i<Creative?Creative:(i>Survival?Survival:i);
int id=_type==Survival?R.string.gamemode_survival_summary:R.string.gamemode_creative_summary;
String desc=getContext().getString(id);
View v=getRootView().findViewById(R.id.labelGameModeDesc);
if(desc!=null&&v instanceof TextView)((TextView)v).setText(desc);
}
public String getStringValue(){return new String[]{"creative","survival"}[_type];}
static public String getStringForType(int i){int c=i<Creative?Creative:(i>Survival?Survival:i);return new String[]{"creative","survival"}[c];}
}
"@
Write-Host " stubs OK"
# ── 1. NDK build ─────────────────────────────────────────────
if (-not $NoCpp -and -not $NoBuild) {
Write-Step "NDK build (arm64-v8a)"
# NDK r14b on Windows hits the 32K CreateProcess limit with long paths.
# Work around it by building through a short junction C:\m -> repo root.
$junctionBase = "C:\m"
if (-not (Test-Path $junctionBase)) {
& cmd.exe /c "mklink /J `"$junctionBase`" `"$repo`"" | Out-Null
}
Push-Location "$junctionBase\project\android\jni"
$env:NDK_MODULE_PATH = "$junctionBase\project\lib_projects"
# run ndk-build and capture everything; let user see full output for debugging
$ndkOutput = & "$ndk\ndk-build.cmd" NDK_PROJECT_PATH="$junctionBase\project\android" APP_BUILD_SCRIPT="$junctionBase\project\android\jni\Android.mk" 2>&1 | Tee-Object -Variable ndkOutput
# dump entire output for diagnosis
Write-Host "---- NDK BUILD OUTPUT BEGIN ----"
$ndkOutput | ForEach-Object { Write-Host $_ }
Write-Host "---- NDK BUILD OUTPUT END ----"
# optionally highlight errors/warnings afterwards
$ndkOutput | Where-Object { $_ -match "error:|warning:|libminecraftpe|In file included" }
Pop-Location
Assert-ExitCode "ndk-build"
Copy-Item $libSrc $libDst -Force
Write-Host " .so -> $libDst"
}
# ── 2. Java compile ──────────────────────────────────────────
if (-not $NoJava -and -not $NoBuild) {
Write-Step "Java compile"
New-Dir (Split-Path $rJava -Parent)
& "$sdkTools\aapt.exe" package -f -M $manifest -S $res -I $androidJar -J "$apkbuild\gen" -F "$apkbuild\_rgen.apk" 2>&1 | Out-Null
Assert-ExitCode "aapt R.java"
Remove-Item "$apkbuild\_rgen.apk" -ea SilentlyContinue
$srcs = @(
Get-ChildItem $javaSrc -Recurse -Filter "*.java" | Select-Object -Exp FullName
Get-ChildItem $stubsDir -Recurse -Filter "*.java" | Select-Object -Exp FullName
$rJava
)
Remove-Item $classesDir -Recurse -Force -ea SilentlyContinue
New-Dir $classesDir
$eap = $ErrorActionPreference; $ErrorActionPreference = "Continue"
$errors = & javac --release 8 -cp $androidJar -d $classesDir @srcs 2>&1 |
Where-Object { $_ -match "error:" }
$ErrorActionPreference = $eap
if ($errors) { Write-Host $errors -ForegroundColor Red; exit 1 }
Write-Host " javac OK"
$classFiles = Get-ChildItem $classesDir -Recurse -Filter "*.class" | Select-Object -Exp FullName
& "$sdkTools\d8.bat" --min-api 21 --output $apkbuild $classFiles
Assert-ExitCode "d8"
Write-Host " d8 -> $dexOut"
}
# ── 3. Package APK ───────────────────────────────────────────
Write-Step "Package APK"
Remove-Item $unsigned,$aligned,$signed -ea SilentlyContinue
& "$sdkTools\aapt.exe" package -f -M $manifest -S $res -I $androidJar -F $unsigned
Assert-ExitCode "aapt package"
$zip = [System.IO.Compression.ZipFile]::Open($unsigned, 'Update')
try {
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$dexOut,"classes.dex",[System.IO.Compression.CompressionLevel]::Fastest)|Out-Null
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$libDst,"lib/arm64-v8a/libminecraftpe.so",[System.IO.Compression.CompressionLevel]::NoCompression)|Out-Null
Get-ChildItem $dataDir -Recurse -File | ForEach-Object {
$rel=$_.FullName.Substring("$dataDir\".Length).Replace('\','/')
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$_.FullName,"assets/$rel",[System.IO.Compression.CompressionLevel]::NoCompression)|Out-Null
}
} finally { $zip.Dispose() }
Write-Host " APK assembled"
& "$sdkTools\zipalign.exe" -p 4 $unsigned $aligned; Assert-ExitCode "zipalign"
& "$sdkTools\apksigner.bat" sign --ks $keystore --ks-pass pass:android --key-pass pass:android --out $signed $aligned; Assert-ExitCode "apksigner"
Write-Host " signed -> $signed"
# ── 4. Install ───────────────────────────────────────────────
Write-Step "Install"
& $adb shell am force-stop $pkg
& $adb uninstall $pkg 2>$null
& $adb install --no-incremental $signed
Assert-ExitCode "adb install"
Write-Host "`nDone." -ForegroundColor Green

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -144,6 +144,12 @@ options.fov.max=Quake Pro
options.gamma=Brightness options.gamma=Brightness
options.gamma.min=Moody options.gamma.min=Moody
options.gamma.max=Bright options.gamma.max=Bright
options.group.mojang=Login
options.group.game=Game
options.group.controls=Controls
options.group.graphics=Graphics
options.thirdperson=Third Person
options.servervisible=Server Visible
options.sensitivity=Sensitivity options.sensitivity=Sensitivity
options.sensitivity.min=*yawn* options.sensitivity.min=*yawn*
options.sensitivity.max=HYPERSPEED!!! options.sensitivity.max=HYPERSPEED!!!
@@ -156,6 +162,8 @@ options.viewBobbing=View Bobbing
options.ao=Smooth Lighting options.ao=Smooth Lighting
options.anaglyph=3D Anaglyph options.anaglyph=3D Anaglyph
options.framerateLimit=Performance options.framerateLimit=Performance
options.limitFramerate=Limit Framerate
options.vsync=VSync
options.difficulty=Difficulty options.difficulty=Difficulty
options.difficulty.peaceful=Peaceful options.difficulty.peaceful=Peaceful
options.difficulty.easy=Easy options.difficulty.easy=Easy
@@ -170,6 +178,7 @@ options.guiScale.auto=Auto
options.guiScale.small=Small options.guiScale.small=Small
options.guiScale.normal=Normal options.guiScale.normal=Normal
options.guiScale.large=Large options.guiScale.large=Large
options.guiScale.larger=Larger
options.advancedOpengl=Advanced OpenGL options.advancedOpengl=Advanced OpenGL
options.renderClouds=Clouds options.renderClouds=Clouds
options.farWarning1=A 64 bit Java installation is recommended options.farWarning1=A 64 bit Java installation is recommended

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mojang.minecraftpe" package="com.mojang.minecraftpe"
android:versionCode="6006" android:versionCode="6010"
android:versionName="0.6.0" android:versionName="0.6.1-alpha-0.0.3"
android:installLocation="preferExternal"> android:installLocation="preferExternal">
<!-- This is the platform API where NativeActivity was introduced. --> <!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="9" <uses-sdk android:minSdkVersion="24"
android:targetSdkVersion="9" /> android:targetSdkVersion="24" />
<!-- uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/ --> <!-- uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/ -->

View File

@@ -170,6 +170,7 @@ options.guiScale.auto=Auto
options.guiScale.small=Small options.guiScale.small=Small
options.guiScale.normal=Normal options.guiScale.normal=Normal
options.guiScale.large=Large options.guiScale.large=Large
options.guiScale.larger=Larger
options.advancedOpengl=Advanced OpenGL options.advancedOpengl=Advanced OpenGL
options.renderClouds=Clouds options.renderClouds=Clouds
options.farWarning1=A 64 bit Java installation is recommended options.farWarning1=A 64 bit Java installation is recommended

View File

@@ -4,7 +4,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := minecraftpe LOCAL_MODULE := minecraftpe
LOCAL_SRC_FILES := ../../../src/main.cpp \ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/main_android.cpp \ ../../../src/main_android_java.cpp \
../../../src/platform/audio/SoundSystemSL.cpp \ ../../../src/platform/audio/SoundSystemSL.cpp \
../../../src/platform/input/Controller.cpp \ ../../../src/platform/input/Controller.cpp \
../../../src/platform/input/Keyboard.cpp \ ../../../src/platform/input/Keyboard.cpp \
@@ -40,6 +40,7 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/gui/components/ScrolledSelectionList.cpp \ ../../../src/client/gui/components/ScrolledSelectionList.cpp \
../../../src/client/gui/components/ScrollingPane.cpp \ ../../../src/client/gui/components/ScrollingPane.cpp \
../../../src/client/gui/components/Slider.cpp \ ../../../src/client/gui/components/Slider.cpp \
../../../src/client/gui/components/TextBox.cpp \
../../../src/client/gui/components/SmallButton.cpp \ ../../../src/client/gui/components/SmallButton.cpp \
../../../src/client/gui/Font.cpp \ ../../../src/client/gui/Font.cpp \
../../../src/client/gui/Gui.cpp \ ../../../src/client/gui/Gui.cpp \
@@ -48,6 +49,10 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/gui/screens/ScreenChooser.cpp \ ../../../src/client/gui/screens/ScreenChooser.cpp \
../../../src/client/gui/screens/ArmorScreen.cpp \ ../../../src/client/gui/screens/ArmorScreen.cpp \
../../../src/client/gui/screens/ChatScreen.cpp \ ../../../src/client/gui/screens/ChatScreen.cpp \
../../../src/client/gui/screens/ChooseLevelScreen.cpp \
../../../src/client/gui/screens/SimpleChooseLevelScreen.cpp \
../../../src/client/gui/screens/ConsoleScreen.cpp \
../../../src/client/gui/screens/UsernameScreen.cpp \
../../../src/client/gui/screens/ConfirmScreen.cpp \ ../../../src/client/gui/screens/ConfirmScreen.cpp \
../../../src/client/gui/screens/ChestScreen.cpp \ ../../../src/client/gui/screens/ChestScreen.cpp \
../../../src/client/gui/screens/DeathScreen.cpp \ ../../../src/client/gui/screens/DeathScreen.cpp \
@@ -56,12 +61,14 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/client/gui/screens/IngameBlockSelectionScreen.cpp \ ../../../src/client/gui/screens/IngameBlockSelectionScreen.cpp \
../../../src/client/gui/screens/JoinGameScreen.cpp \ ../../../src/client/gui/screens/JoinGameScreen.cpp \
../../../src/client/gui/screens/OptionsScreen.cpp \ ../../../src/client/gui/screens/OptionsScreen.cpp \
../../../src/client/gui/screens/PauseScreen.cpp \ ../../../src/client/gui/screens/CreditsScreen.cpp \
../../../src/client/gui/screens/PauseScreen.cpp \
../../../src/client/gui/screens/ProgressScreen.cpp \ ../../../src/client/gui/screens/ProgressScreen.cpp \
../../../src/client/gui/screens/RenameMPLevelScreen.cpp \ ../../../src/client/gui/screens/RenameMPLevelScreen.cpp \
../../../src/client/gui/screens/SelectWorldScreen.cpp \ ../../../src/client/gui/screens/SelectWorldScreen.cpp \
../../../src/client/gui/screens/StartMenuScreen.cpp \ ../../../src/client/gui/screens/StartMenuScreen.cpp \
../../../src/client/gui/screens/TextEditScreen.cpp \ ../../../src/client/gui/screens/TextEditScreen.cpp \
../../../src/client/gui/screens/JoinByIPScreen.cpp \
../../../src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.cpp \ ../../../src/client/gui/screens/touch/TouchIngameBlockSelectionScreen.cpp \
../../../src/client/gui/screens/touch/TouchJoinGameScreen.cpp \ ../../../src/client/gui/screens/touch/TouchJoinGameScreen.cpp \
../../../src/client/gui/screens/touch/TouchSelectWorldScreen.cpp \ ../../../src/client/gui/screens/touch/TouchSelectWorldScreen.cpp \
@@ -245,7 +252,9 @@ LOCAL_SRC_FILES := ../../../src/main.cpp \
../../../src/world/level/tile/entity/FurnaceTileEntity.cpp \ ../../../src/world/level/tile/entity/FurnaceTileEntity.cpp \
../../../src/world/phys/HitResult.cpp ../../../src/world/phys/HitResult.cpp
LOCAL_CFLAGS := -Wno-psabi $(LOCAL_CFLAGS) LOCAL_CFLAGS := -DPLATFORM_ANDROID -DPRE_ANDROID23 -Wno-narrowing $(LOCAL_CFLAGS)
LOCAL_CPPFLAGS := -std=c++11
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../src
#LOCAL_CFLAGS := -DANDROID_PUBLISH -DDEMO_MODE $(LOCAL_CFLAGS) #LOCAL_CFLAGS := -DANDROID_PUBLISH -DDEMO_MODE $(LOCAL_CFLAGS)
#LOCAL_CFLAGS := -DANDROID_PUBLISH $(LOCAL_CFLAGS) #LOCAL_CFLAGS := -DANDROID_PUBLISH $(LOCAL_CFLAGS)

View File

@@ -1,5 +1,5 @@
APP_PLATFORM := android-9 APP_PLATFORM := android-21
APP_STL := stlport_static APP_STL := gnustl_static
APP_OPTIM := release APP_OPTIM := release
APP_ABI := armeabi-v7a APP_ABI := arm64-v8a
#APP_ABI := armeabi-v7a x86 #APP_ABI := armeabi-v7a x86

View File

@@ -468,17 +468,16 @@ public class MainActivity extends NativeActivity {
_userInputStatus = 1; _userInputStatus = 1;
InputMethodManager inputManager = (InputMethodManager)getSystemService("input_method"); InputMethodManager inputManager = (InputMethodManager)getSystemService("input_method");
boolean result = inputManager.showSoftInput(this.getCurrentFocus(), InputMethodManager.SHOW_IMPLICIT); View focused = this.getCurrentFocus();
if (focused != null) {
boolean result = inputManager.showSoftInput(focused, InputMethodManager.SHOW_IMPLICIT);
} else {
// fallback: try to show using decor view token
View decor = getWindow().getDecorView();
if (decor != null) {
inputManager.showSoftInput(decor, InputMethodManager.SHOW_IMPLICIT);
} }
protected void onStart() {
//System.out.println("onStart");
super.onStart();
} }
protected void onResume() {
//System.out.println("onResume");
super.onResume();
} }
protected void onPause() { protected void onPause() {

View File

@@ -1,44 +1,74 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mojang.minecraftpe" package="com.mojang.minecraftpe"
android:versionCode="4000" android:versionCode="6010"
android:versionName="0.4.0" android:versionName="0.6.1-alpha-0.0.3">
>
<!-- android:installLocation="preferExternal" -->
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="7"/> <uses-sdk
android:minSdkVersion="24"
android:targetSdkVersion="28"/>
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/> <uses-feature
android:name="android.hardware.touchscreen.multitouch"
android:required="true"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.VIBRATE"/>
<application android:icon="@drawable/icon" <application
android:icon="@drawable/icon"
android:label="@string/app_name" android:label="@string/app_name"
> android:hardwareAccelerated="true"
android:extractNativeLibs="true"
android:requestLegacyExternalStorage="true">
<activity android:name="com.mojang.minecraftpe.Minecraft_Market" <activity
android:name="com.mojang.minecraftpe.Minecraft_Market"
android:label="@string/app_name_short" android:label="@string/app_name_short"
android:configChanges="orientation|keyboardHidden" android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
android:screenOrientation="landscape" android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:exported="true">
<meta-data android:name="android.app.lib_name" <meta-data
android:value="minecraftpe" /> android:name="android.app.lib_name"
android:value="minecraftpe"/>
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.mojang.minecraftpe.MainMenuOptionsActivity"></activity>
<meta-data android:name="xperiaplayoptimized_content" android:resource="@string/xperiaplayoptimized_content" /> <activity
<meta-data android:name="game_display_name" android:resource="@string/app_name" /> android:name="com.mojang.minecraftpe.MainActivity"
<meta-data android:name="game_icon" android:resource="@drawable/iconx" /> android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
android:screenOrientation="landscape"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:exported="false"/>
<activity
android:name="com.mojang.minecraftpe.MainMenuOptionsActivity"
android:exported="false"/>
<meta-data
android:name="xperiaplayoptimized_content"
android:resource="@string/xperiaplayoptimized_content"/>
<meta-data
android:name="game_display_name"
android:resource="@string/app_name"/>
<meta-data
android:name="game_icon"
android:resource="@drawable/iconx"/>
<uses-library
android:name="xperiaplaycertified"
android:required="false"/>
<uses-library android:name="xperiaplaycertified" android:required="false"/>
</application> </application>
</manifest> </manifest>

View File

@@ -31,6 +31,8 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.content.pm.PackageManager;
import android.os.Build;
import android.graphics.Bitmap.CompressFormat; import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.media.AudioManager; import android.media.AudioManager;
@@ -40,7 +42,6 @@ import android.os.Vibrator;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.view.Display;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
@@ -55,9 +56,12 @@ import com.mojang.minecraftpe.sound.SoundPlayer;
public class MainActivity extends Activity { public class MainActivity extends Activity {
/** Called when the activity is first created. */ /** Called when the activity is first created. */
private static final int PERMISSION_REQUEST_CODE = 123;
private GLView _glView; private GLView _glView;
public float invScale = 1.0f;// / 1.5f; public float invScale = 1.0f;// / 1.5f;
private int _screenWidth = 0;
private int _screenHeight = 0;
Vector<MotionEvent> _touchEvents = new Vector<MotionEvent>(); Vector<MotionEvent> _touchEvents = new Vector<MotionEvent>();
Vector<KeyEvent> _keyEvents = new Vector<KeyEvent>(); Vector<KeyEvent> _keyEvents = new Vector<KeyEvent>();
@@ -68,7 +72,12 @@ public class MainActivity extends Activity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
nativeRegisterThis(); nativeRegisterThis();
nativeOnCreate(); // Cache screen dimensions once to avoid re-entrant getDisplayMetrics() callbacks
android.util.DisplayMetrics _dm = getResources().getDisplayMetrics();
_screenWidth = Math.max(_dm.widthPixels, _dm.heightPixels);
_screenHeight = Math.min(_dm.widthPixels, _dm.heightPixels);
nativeOnCreate(_screenWidth, _screenHeight);
_glView = new GLView(getApplication(), this); _glView = new GLView(getApplication(), this);
//_glView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); //_glView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
@@ -102,19 +111,69 @@ public class MainActivity extends Activity {
setContentView(_glView); setContentView(_glView);
_soundPlayer = new SoundPlayer(this, AudioManager.STREAM_MUSIC); _soundPlayer = new SoundPlayer(this, AudioManager.STREAM_MUSIC);
// request dangerous permissions at runtime if necessary
checkAndRequestPermissions();
}
private void checkAndRequestPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean needRequest = false;
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
needRequest = true;
}
if (checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
needRequest = true;
}
if (needRequest) {
requestPermissions(new String[] {
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.READ_EXTERNAL_STORAGE
}, PERMISSION_REQUEST_CODE);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_CODE) {
boolean granted = true;
for (int r : grantResults) {
if (r != PackageManager.PERMISSION_GRANTED) {
granted = false;
break;
}
}
if (!granted) {
// user denied; you might want to warn or close the app
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
// method required by native code to detect touchscreen support
public boolean supportsTouchscreen() {
return true; // all devices using this build are touch-capable
} }
public boolean isTouchscreen() { return true; }
static public boolean isXperiaPlay() { return false; } static public boolean isXperiaPlay() { return false; }
static private boolean _isPowerVr = false; static private boolean _isPowerVr = false;
public void setIsPowerVR(boolean status) { MainActivity._isPowerVr = status; } public void setIsPowerVR(boolean status) { MainActivity._isPowerVr = status; }
static public boolean isPowerVR() { return _isPowerVr; } static public boolean isPowerVR() { return _isPowerVr; }
@SuppressWarnings("deprecation")
public void vibrate(int milliSeconds) { public void vibrate(int milliSeconds) {
Vibrator v = (Vibrator)this.getSystemService(VIBRATOR_SERVICE); Vibrator v = (Vibrator) getSystemService(VIBRATOR_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= 26) {
v.vibrate(android.os.VibrationEffect.createOneShot(milliSeconds,
android.os.VibrationEffect.DEFAULT_AMPLITUDE));
} else {
v.vibrate(milliSeconds); v.vibrate(milliSeconds);
} }
}
private void createAlertDialog(boolean hasOkButton, boolean hasCancelButton, boolean preventBackKey) { private void createAlertDialog(boolean hasOkButton, boolean hasCancelButton, boolean preventBackKey) {
AlertDialog.Builder builder = new AlertDialog.Builder(this); AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -144,9 +203,16 @@ public class MainActivity extends Activity {
@Override @Override
public void onWindowFocusChanged(boolean hasFocus) { public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
//System.out.println("Focus has changed. Has Focus? " + hasFocus);
super.onWindowFocusChanged(hasFocus); super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
} }
@Override @Override
@@ -184,9 +250,12 @@ public class MainActivity extends Activity {
return; return;
} }
if (event.getAction() == KeyEvent.ACTION_DOWN) if (event.getAction() == KeyEvent.ACTION_DOWN) {
nativeOnKeyDown(keyCode); nativeOnKeyDown(keyCode);
else if (event.getAction() == KeyEvent.ACTION_UP) int unicodeChar = event.getUnicodeChar(event.getMetaState());
if (unicodeChar > 0)
nativeTextChar(unicodeChar);
} else if (event.getAction() == KeyEvent.ACTION_UP)
nativeOnKeyUp(keyCode); nativeOnKeyUp(keyCode);
} }
@@ -347,22 +416,15 @@ public class MainActivity extends Activity {
} }
public int getScreenWidth() { public int getScreenWidth() {
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); return _screenWidth;
int out = Math.max(display.getWidth(), display.getHeight());
//System.out.println("getwidth: " + out);
return out;
} }
public int getScreenHeight() { public int getScreenHeight() {
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); return _screenHeight;
int out = Math.min(display.getWidth(), display.getHeight());
//System.out.println("getheight: " + out);
return out;
} }
public float getPixelsPerMillimeter() { public float getPixelsPerMillimeter() {
DisplayMetrics metrics = new DisplayMetrics(); android.util.DisplayMetrics metrics = getResources().getDisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
return (metrics.xdpi + metrics.ydpi) * 0.5f / 25.4f; return (metrics.xdpi + metrics.ydpi) * 0.5f / 25.4f;
} }
@@ -465,8 +527,8 @@ public class MainActivity extends Activity {
MainActivity.this.mDialog.show(); MainActivity.this.mDialog.show();
MainActivity.this.mDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); MainActivity.this.mDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
MainActivity.this.mDialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); MainActivity.this.mDialog.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
//MainActivity.this.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); //MainActivity.this.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
} }
}); });
} }
@@ -516,6 +578,20 @@ public class MainActivity extends Activity {
public void buyGame() {} public void buyGame() {}
public int getKeyFromKeyCode(int keyCode, int metaState, int deviceId) {
android.view.KeyCharacterMap kcm = android.view.KeyCharacterMap.load(deviceId);
return kcm.get(keyCode, metaState);
}
public void openURL(String url) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, android.net.Uri.parse(url));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
public String getPlatformStringVar(int id) { public String getPlatformStringVar(int id) {
if (id == 0) return android.os.Build.MODEL; if (id == 0) return android.os.Build.MODEL;
return null; return null;
@@ -604,10 +680,11 @@ public class MainActivity extends Activity {
// //
native void nativeRegisterThis(); native void nativeRegisterThis();
native void nativeUnregisterThis(); native void nativeUnregisterThis();
native static void nativeOnCreate(); native static void nativeOnCreate(int screenWidth, int screenHeight);
native static void nativeOnDestroy(); native static void nativeOnDestroy();
native static void nativeOnKeyDown(int key); native static void nativeOnKeyDown(int key);
native static void nativeOnKeyUp(int key); native static void nativeOnKeyUp(int key);
native static void nativeTextChar(int unicodeChar);
native static boolean nativeHandleBack(boolean isDown); native static boolean nativeHandleBack(boolean isDown);
native static void nativeMouseDown(int pointerId, int buttonId, float x, float y); native static void nativeMouseDown(int pointerId, int buttonId, float x, float y);
native static void nativeMouseUp(int pointerId, int buttonId, float x, float y); native static void nativeMouseUp(int pointerId, int buttonId, float x, float y);

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.7) cmake_minimum_required(VERSION 3.5.0)
find_package (Threads) find_package (Threads)
include_directories("${PROJECT_SOURCE_DIR}/../lib_projects/raknet/jni/RaknetSources") include_directories("${PROJECT_SOURCE_DIR}/../lib_projects/raknet/jni/RaknetSources")
add_subdirectory("${PROJECT_SOURCE_DIR}/../lib_projects/raknet/jni" "${CMAKE_CURRENT_BINARY_DIR}/raknet") add_subdirectory("${PROJECT_SOURCE_DIR}/../lib_projects/raknet/jni" "${CMAKE_CURRENT_BINARY_DIR}/raknet")
@@ -151,6 +151,9 @@ set(CompileFiles ../../src/main.cpp
../../src/world/level/tile/entity/TileEntity.cpp ../../src/world/level/tile/entity/TileEntity.cpp
../../src/world/level/tile/entity/FurnaceTileEntity.cpp ../../src/world/level/tile/entity/FurnaceTileEntity.cpp
../../src/world/phys/HitResult.cpp) ../../src/world/phys/HitResult.cpp)
message(${CMAKE_LIBRARY_ARCHITECTURE})
add_executable(mcpe_server ${CompileFiles}) add_executable(mcpe_server ${CompileFiles})
target_link_libraries(mcpe_server raknet ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(mcpe_server raknet ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(mcpe_server PUBLIC
"minecraft-pe-0.6.1/src/"
)

View File

@@ -5,7 +5,7 @@
#include <stdio.h> // RAKNET_DEBUG_PRINTF #include <stdio.h> // RAKNET_DEBUG_PRINTF
#include "RakAssert.h" #include "RakAssert.h"
#if defined(ANDROID) #if defined(ANDROID)
#include <asm/io.h> // <asm/io.h> not needed and unavailable on arm64
#elif defined(_WIN32) || defined(__CYGWIN__) #elif defined(_WIN32) || defined(__CYGWIN__)
#include <io.h> #include <io.h>

View File

@@ -124,7 +124,7 @@ static const unsigned int MAX_OFFLINE_DATA_LENGTH=400; // I set this because I l
#pragma warning(disable:4309) // 'initializing' : truncation of constant value #pragma warning(disable:4309) // 'initializing' : truncation of constant value
#endif #endif
// Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false // Make sure highest bit is 0, so isValid in DatagramHeaderFormat is false
static const char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78}; static const unsigned char OFFLINE_MESSAGE_DATA_ID[16]={0x00,0xFF,0xFF,0x00,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD,0xFD,0xFD,0x12,0x34,0x56,0x78};
struct PacketFollowedByData struct PacketFollowedByData
{ {

View File

@@ -96,9 +96,6 @@ public:
virtual std::string getDateString(int s) { return ""; } virtual std::string getDateString(int s) { return ""; }
//virtual void createUserInputScreen(const char* types) {} //virtual void createUserInputScreen(const char* types) {}
virtual int checkLicense() { return 0; }
virtual bool hasBuyButtonWhenInvalidLicense() { return false; }
virtual void uploadPlatformDependentData(int id, void* data) {} virtual void uploadPlatformDependentData(int id, void* data) {}
virtual BinaryBlob readAssetFile(const std::string& filename) { return BinaryBlob(); } virtual BinaryBlob readAssetFile(const std::string& filename) { return BinaryBlob(); }
virtual void _tick() {} virtual void _tick() {}
@@ -117,7 +114,7 @@ public:
virtual bool isSuperFast() = 0; virtual bool isSuperFast() = 0;
#endif #endif
virtual void buyGame() {} virtual void openURL(const std::string& url) {}
virtual void finish() {} virtual void finish() {}

View File

@@ -68,9 +68,6 @@ public:
_methodGetDateString(0), _methodGetDateString(0),
_methodCheckLicense(0),
_methodHasBuyButton(0),
_methodBuyGame(0),
_methodVibrate(0), _methodVibrate(0),
_methodSupportsTouchscreen(0), _methodSupportsTouchscreen(0),
_methodSetIsPowerVR(0), _methodSetIsPowerVR(0),
@@ -104,6 +101,7 @@ public:
int getScreenWidth() { return _screenWidth; } int getScreenWidth() { return _screenWidth; }
int getScreenHeight() { return _screenHeight; } int getScreenHeight() { return _screenHeight; }
void setScreenDimensions(int w, int h) { _screenWidth = w; _screenHeight = h; }
// Note, this has to be called from the main thread (e.g. do it from JNI_onLoad) // Note, this has to be called from the main thread (e.g. do it from JNI_onLoad)
// Somewhere between calling this, and calling the AppPlatform methods, // Somewhere between calling this, and calling the AppPlatform methods,
@@ -146,10 +144,6 @@ public:
_methodGetDateString = env->GetMethodID( _activityClass, "getDateString", "(I)Ljava/lang/String;"); _methodGetDateString = env->GetMethodID( _activityClass, "getDateString", "(I)Ljava/lang/String;");
_methodCheckLicense = env->GetMethodID( _activityClass, "checkLicense", "()I");
_methodHasBuyButton = env->GetMethodID( _activityClass, "hasBuyButtonWhenInvalidLicense", "()Z");
_methodBuyGame = env->GetMethodID( _activityClass, "buyGame", "()V");
_methodVibrate = env->GetMethodID( _activityClass, "vibrate", "(I)V"); _methodVibrate = env->GetMethodID( _activityClass, "vibrate", "(I)V");
_methodSupportsTouchscreen = env->GetMethodID( _activityClass, "supportsTouchscreen", "()Z"); _methodSupportsTouchscreen = env->GetMethodID( _activityClass, "supportsTouchscreen", "()Z");
_methodSetIsPowerVR = env->GetMethodID( _activityClass, "setIsPowerVR", "(Z)V"); _methodSetIsPowerVR = env->GetMethodID( _activityClass, "setIsPowerVR", "(Z)V");
@@ -157,6 +151,8 @@ public:
_methodGetPixelsPerMillimeter = env->GetMethodID( _activityClass, "getPixelsPerMillimeter", "()F"); _methodGetPixelsPerMillimeter = env->GetMethodID( _activityClass, "getPixelsPerMillimeter", "()F");
_methodGetPlatformStringVar = env->GetMethodID( _activityClass, "getPlatformStringVar", "(I)Ljava/lang/String;"); _methodGetPlatformStringVar = env->GetMethodID( _activityClass, "getPlatformStringVar", "(I)Ljava/lang/String;");
// custom helper to launch external URLs
_methodOpenURL = env->GetMethodID(_activityClass, "openURL", "(Ljava/lang/String;)V");
_classWindow = (jclass)env->NewGlobalRef(env->FindClass("android/view/Window")); _classWindow = (jclass)env->NewGlobalRef(env->FindClass("android/view/Window"));
_classContext = (jclass)env->NewGlobalRef(env->FindClass("android/content/Context")); _classContext = (jclass)env->NewGlobalRef(env->FindClass("android/content/Context"));
@@ -192,14 +188,20 @@ public:
// be rewritten later on anyway // be rewritten later on anyway
int initConsts() { int initConsts() {
LOGI("initConsts: start\n");
JVMAttacher ta(_vm); JVMAttacher ta(_vm);
JNIEnv* env = ta.getEnv(); JNIEnv* env = ta.getEnv();
LOGI("initConsts: getting method IDs\n");
jmethodID fWidth = env->GetMethodID( _activityClass, "getScreenWidth", "()I"); jmethodID fWidth = env->GetMethodID( _activityClass, "getScreenWidth", "()I");
LOGI("initConsts: got fWidth=%p\n", fWidth);
jmethodID fHeight = env->GetMethodID( _activityClass, "getScreenHeight", "()I"); jmethodID fHeight = env->GetMethodID( _activityClass, "getScreenHeight", "()I");
LOGI("initConsts: got fHeight=%p, calling getScreenWidth\n", fHeight);
_screenWidth = env->CallIntMethod(instance, fWidth); _screenWidth = env->CallIntMethod(instance, fWidth);
LOGI("initConsts: screenWidth=%d, calling getScreenHeight\n", _screenWidth);
_screenHeight = env->CallIntMethod(instance, fHeight); _screenHeight = env->CallIntMethod(instance, fHeight);
LOGI("initConsts: screenHeight=%d, done\n", _screenHeight);
} }
void tick() { void tick() {
@@ -376,8 +378,9 @@ public:
JVMAttacher ta(_vm); JVMAttacher ta(_vm);
JNIEnv* env = ta.getEnv(); JNIEnv* env = ta.getEnv();
std::string path = textureFolder ? "images/" + filename : filename;
jintArray arr = (jintArray)env->CallObjectMethod( jintArray arr = (jintArray)env->CallObjectMethod(
instance, _getImageData, env->NewStringUTF(filename.c_str())); instance, _getImageData, env->NewStringUTF(path.c_str()));
if (!arr) if (!arr)
return TextureData(); return TextureData();
@@ -464,37 +467,15 @@ public:
env->ReleaseStringUTFChars(stringVar, str); env->ReleaseStringUTFChars(stringVar, str);
return out; return out;
} }
// Opens a webpage using an Android intent. Called from native code.
int checkLicense() { virtual void openURL(const std::string& url) {
if (!_isInited) return -2; if (!_isInited || !_methodOpenURL) return;
if (!_methodCheckLicense) return -2;
JVMAttacher ta(_vm); JVMAttacher ta(_vm);
JNIEnv* env = ta.getEnv(); JNIEnv* env = ta.getEnv();
jstring jurl = env->NewStringUTF(url.c_str());
return env->CallIntMethod(instance, _methodCheckLicense); env->CallVoidMethod(instance, _methodOpenURL, jurl);
env->DeleteLocalRef(jurl);
} }
bool hasBuyButtonWhenInvalidLicense() {
if (!_isInited) return false;
if (!_methodHasBuyButton) return false;
JVMAttacher ta(_vm);
JNIEnv* env = ta.getEnv();
return JNI_TRUE == env->CallBooleanMethod(instance, _methodHasBuyButton);
}
void buyGame() {
if (!_isInited) return;
if (!_methodBuyGame) return;
JVMAttacher ta(_vm);
JNIEnv* env = ta.getEnv();
env->CallVoidMethod(instance, _methodBuyGame);
}
virtual void finish() { virtual void finish() {
if (!_isInited) return; if (!_isInited) return;
if (!_methodFinish) return; if (!_methodFinish) return;
@@ -636,10 +617,6 @@ private:
jmethodID _methodGetDateString; jmethodID _methodGetDateString;
jmethodID _methodCheckLicense;
jmethodID _methodHasBuyButton;
jmethodID _methodBuyGame;
jmethodID _getScreenWidth; jmethodID _getScreenWidth;
jmethodID _getScreenHeight; jmethodID _getScreenHeight;
jmethodID _methodGetPixelsPerMillimeter; jmethodID _methodGetPixelsPerMillimeter;
@@ -649,6 +626,7 @@ private:
jmethodID _methodIsNetworkEnabled; jmethodID _methodIsNetworkEnabled;
jmethodID _methodGetPlatformStringVar; jmethodID _methodGetPlatformStringVar;
jmethodID _methodOpenURL; // new JNI method for launching browser
jclass _classWindow; jclass _classWindow;
jclass _classContext; jclass _classContext;

View File

@@ -1,5 +1,74 @@
#include "AppPlatform_glfw.h" #include "AppPlatform_glfw.h"
#ifdef WIN32
#include <Windows.h>
#endif
// Loader that tries GLFW first, then falls back to opengl32.dll for any
// function that glfwGetProcAddress can't resolve.
void* winGLLoader(const char* name) {
void* p = (void*)glfwGetProcAddress(name);
#ifdef WIN32
if (!p) {
static HMODULE opengl32 = LoadLibraryA("opengl32.dll");
if (opengl32) p = (void*)GetProcAddress(opengl32, name);
}
#endif
return p;
}
// -----------------------------------------------------------------------
// Compatibility wrappers for OpenGL ES functions absent from desktop GL.
// The desktop equivalents use double parameters and are not declared in
// the GLES1 GLAD header, so look them up at runtime via winGLLoader.
// -----------------------------------------------------------------------
static void APIENTRY compat_glDepthRangef(GLfloat n, GLfloat f) {
typedef void(APIENTRY *fn_t)(double, double);
static fn_t fn = (fn_t)winGLLoader("glDepthRange");
if (fn) fn((double)n, (double)f);
}
static void APIENTRY compat_glClearDepthf(GLfloat d) {
typedef void(APIENTRY *fn_t)(double);
static fn_t fn = (fn_t)winGLLoader("glClearDepth");
if (fn) fn((double)d);
}
static void APIENTRY compat_glOrthof(GLfloat l, GLfloat r, GLfloat b,
GLfloat t, GLfloat n, GLfloat f) {
typedef void(APIENTRY *fn_t)(double,double,double,double,double,double);
static fn_t fn = (fn_t)winGLLoader("glOrtho");
if (fn) fn(l, r, b, t, n, f);
}
static void APIENTRY compat_glFrustumf(GLfloat l, GLfloat r, GLfloat b,
GLfloat t, GLfloat n, GLfloat f) {
typedef void(APIENTRY *fn_t)(double,double,double,double,double,double);
static fn_t fn = (fn_t)winGLLoader("glFrustum");
if (fn) fn(l, r, b, t, n, f);
}
// glFogx / glFogxv are OpenGL ES fixed-point variants that don't exist in
// desktop opengl32.dll. Wrap them via the float equivalents. For fog-mode
// enum params the GLfixed value IS the enum integer, so the cast is exact.
static void APIENTRY compat_glFogx(GLenum pname, GLfixed param) {
glFogf(pname, (GLfloat)param);
}
static void APIENTRY compat_glFogxv(GLenum pname, const GLfixed* params) {
// Only GL_FOG_COLOR uses an array; convert each element.
GLfloat fp[4] = {
(GLfloat)params[0], (GLfloat)params[1],
(GLfloat)params[2], (GLfloat)params[3]
};
glFogfv(pname, fp);
}
void glPatchDesktopCompat() {
if (!glad_glDepthRangef) glad_glDepthRangef = compat_glDepthRangef;
if (!glad_glClearDepthf) glad_glClearDepthf = compat_glClearDepthf;
if (!glad_glOrthof) glad_glOrthof = compat_glOrthof;
if (!glad_glFrustumf) glad_glFrustumf = compat_glFrustumf;
if (!glad_glFogx) glad_glFogx = compat_glFogx;
if (!glad_glFogxv) glad_glFogxv = compat_glFogxv;
}
float AppPlatform_glfw::getPixelsPerMillimeter() { float AppPlatform_glfw::getPixelsPerMillimeter() {
GLFWmonitor* monitor = glfwGetPrimaryMonitor(); GLFWmonitor* monitor = glfwGetPrimaryMonitor();

View File

@@ -10,6 +10,12 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <ctime>
#ifdef _WIN32
#include <windows.h>
#include <shellapi.h>
#endif
static void png_funcReadFile(png_structp pngPtr, png_bytep data, png_size_t length) { static void png_funcReadFile(png_structp pngPtr, png_bytep data, png_size_t length) {
((std::istream*)png_get_io_ptr(pngPtr))->read((char*)data, length); ((std::istream*)png_get_io_ptr(pngPtr))->read((char*)data, length);
@@ -102,17 +108,12 @@ public:
} }
std::string getDateString(int s) { std::string getDateString(int s) {
std::stringstream ss; time_t tm = s;
ss << s << " s (UTC)";
return ss.str();
}
virtual int checkLicense() { char mbstr[100];
static int _z = 0;//20; std::strftime(mbstr, sizeof(mbstr), "%F %T", std::localtime(&tm));
_z--;
if (_z < 0) return 0; return std::string(mbstr);
//if (_z < 0) return 107;
return -2;
} }
virtual int getScreenWidth() { return 854; }; virtual int getScreenWidth() { return 854; };
@@ -121,9 +122,20 @@ public:
virtual float getPixelsPerMillimeter(); virtual float getPixelsPerMillimeter();
virtual bool supportsTouchscreen() { return true; } virtual bool supportsTouchscreen() { return true; }
virtual bool hasBuyButtonWhenInvalidLicense() { return false; }
virtual void openURL(const std::string& url) {
#ifdef _WIN32
ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
#elif __linux__
std::string command = "xdg-open " + url;
system(command.c_str());
#endif
}
private: private:
}; };
void* winGLLoader(const char* name);
void glPatchDesktopCompat();
#endif /*APPPLATFORM_GLFW_H__*/ #endif /*APPPLATFORM_GLFW_H__*/

View File

@@ -41,17 +41,6 @@ public:
std::string getDateString(int s); std::string getDateString(int s);
virtual int checkLicense() {
return 0;
static int _z = 20;
_z--;
if (_z < 0) return 0;
//if (_z < 0) return 107;
return -2;
}
virtual void buyGame();
virtual int getScreenWidth(); virtual int getScreenWidth();
virtual int getScreenHeight(); virtual int getScreenHeight();
virtual float getPixelsPerMillimeter(); virtual float getPixelsPerMillimeter();

View File

@@ -175,10 +175,6 @@ BinaryBlob AppPlatform_iOS::readAssetFile(const std::string& filename_) {
return BinaryBlob(bytes, numBytes); return BinaryBlob(bytes, numBytes);
} }
void AppPlatform_iOS::buyGame() {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=479516143&mt=8"]];
}
std::string AppPlatform_iOS::getDateString(int s) { std::string AppPlatform_iOS::getDateString(int s) {
NSDate* date = [NSDate dateWithTimeIntervalSince1970:s]; NSDate* date = [NSDate dateWithTimeIntervalSince1970:s];

View File

@@ -14,4 +14,3 @@ float AppPlatform_win32::getPixelsPerMillimeter() {
} }
bool AppPlatform_win32::supportsTouchscreen() { return true; } bool AppPlatform_win32::supportsTouchscreen() { return true; }
bool AppPlatform_win32::hasBuyButtonWhenInvalidLicense() { return true; }

View File

@@ -9,6 +9,8 @@
#include <cmath> #include <cmath>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <windows.h>
#include <shellapi.h>
static void png_funcReadFile(png_structp pngPtr, png_bytep data, png_size_t length) { static void png_funcReadFile(png_structp pngPtr, png_bytep data, png_size_t length) {
((std::istream*)png_get_io_ptr(pngPtr))->read((char*)data, length); ((std::istream*)png_get_io_ptr(pngPtr))->read((char*)data, length);
@@ -101,17 +103,12 @@ public:
} }
std::string getDateString(int s) { std::string getDateString(int s) {
std::stringstream ss; time_t tm = s;
ss << s << " s (UTC)";
return ss.str();
}
virtual int checkLicense() { char mbstr[100];
static int _z = 0;//20; std::strftime(mbstr, sizeof(mbstr), "%F %T", std::localtime(&tm));
_z--;
if (_z < 0) return 0; return std::string(mbstr);
//if (_z < 0) return 107;
return -2;
} }
virtual int getScreenWidth(); virtual int getScreenWidth();
@@ -120,7 +117,10 @@ public:
virtual float getPixelsPerMillimeter(); virtual float getPixelsPerMillimeter();
virtual bool supportsTouchscreen(); virtual bool supportsTouchscreen();
virtual bool hasBuyButtonWhenInvalidLicense();
virtual void openURL(const std::string& url) {
ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
private: private:
}; };

View File

@@ -18,6 +18,7 @@
//#include "world/level/storage/FolderMethods.h" //#include "world/level/storage/FolderMethods.h"
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
#include "client/gui/screens/StartMenuScreen.h" #include "client/gui/screens/StartMenuScreen.h"
#include "client/gui/screens/UsernameScreen.h"
#endif #endif
#include "client/player/LocalPlayer.h" #include "client/player/LocalPlayer.h"
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
@@ -110,6 +111,9 @@ void NinecraftApp::init()
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
LOGI("This: %p\n", this); LOGI("This: %p\n", this);
screenChooser.setScreen(SCREEN_STARTMENU); screenChooser.setScreen(SCREEN_STARTMENU);
if (options.username.empty()) {
setScreen(new UsernameScreen());
}
#else #else
user->name = "Server"; user->name = "Server";
hostMultiplayer(); hostMultiplayer();

View File

@@ -4,7 +4,13 @@ namespace Common {
std::string getGameVersionString(const std::string& versionSuffix /* = "" */) std::string getGameVersionString(const std::string& versionSuffix /* = "" */)
{ {
return std::string("v0.6.1") + versionSuffix + " alpha"; std::string result = std::string("v0.6.1") + versionSuffix;
// append 64-bit port marker only on Android 64bit targets
#if defined(ANDROID) && (defined(__aarch64__) || defined(__x86_64__))
result += " (64-bit port)";
#endif
result += " alpha";
return result;
} }
}; };

View File

@@ -1,5 +1,7 @@
#include "Minecraft.h" #include "Minecraft.h"
#include "client/player/input/IBuildInput.h" #include "client/player/input/IBuildInput.h"
#include <string>
#include <cstdlib>
#if defined(APPLE_DEMO_PROMOTION) #if defined(APPLE_DEMO_PROMOTION)
#define NO_NETWORK #define NO_NETWORK
@@ -31,6 +33,7 @@
#include "gui/Screen.h" #include "gui/Screen.h"
#include "gui/Font.h" #include "gui/Font.h"
#include "gui/screens/RenameMPLevelScreen.h" #include "gui/screens/RenameMPLevelScreen.h"
#include "gui/screens/ConsoleScreen.h"
#include "sound/SoundEngine.h" #include "sound/SoundEngine.h"
#endif #endif
#include "../platform/CThread.h" #include "../platform/CThread.h"
@@ -54,7 +57,6 @@
#include "player/input/XperiaPlayInput.h" #include "player/input/XperiaPlayInput.h"
#endif #endif
#include "player/input/MouseTurnInput.h" #include "player/input/MouseTurnInput.h"
#include "../world/entity/MobFactory.h" #include "../world/entity/MobFactory.h"
#include "../world/level/MobSpawner.h" #include "../world/level/MobSpawner.h"
@@ -490,15 +492,14 @@ void Minecraft::update() {
checkGlError("Update finished"); checkGlError("Update finished");
if (options.renderDebug) { if (options.renderDebug) {
#ifndef PLATFORM_DESKTOP
if (!PerfTimer::enabled) { if (!PerfTimer::enabled) {
PerfTimer::reset(); PerfTimer::reset();
PerfTimer::enabled = true; PerfTimer::enabled = true;
} }
//TIMER_PUSH("debugfps");
_perfRenderer->renderFpsMeter(1); _perfRenderer->renderFpsMeter(1);
checkGlError("render debug"); checkGlError("render debug");
//TIMER_POP(); #endif
} else { } else {
PerfTimer::enabled = false; PerfTimer::enabled = false;
} }
@@ -725,6 +726,9 @@ void Minecraft::tickInput() {
if (key == Keyboard::KEY_E) { if (key == Keyboard::KEY_E) {
screenChooser.setScreen(SCREEN_BLOCKSELECTION); screenChooser.setScreen(SCREEN_BLOCKSELECTION);
} }
if (!screen && key == Keyboard::KEY_T && level) {
setScreen(new ConsoleScreen());
}
if (!screen && key == Keyboard::KEY_O || key == 250) { if (!screen && key == Keyboard::KEY_O || key == 250) {
releaseMouse(); releaseMouse();
} }
@@ -737,10 +741,6 @@ void Minecraft::tickInput() {
printf("%d\t%f\n", i, noise.grad2(i, 3, 8)); printf("%d\t%f\n", i, noise.grad2(i, 3, 8));
*/ */
} }
// Change distance
if (key == Keyboard::KEY_F)
options.viewDistance = (options.viewDistance + 1) % 4;
#endif #endif
#if defined(WIN32) #if defined(WIN32)
if (key == Keyboard::KEY_F) { if (key == Keyboard::KEY_F) {
@@ -748,20 +748,6 @@ void Minecraft::tickInput() {
player->noPhysics = options.isFlying; player->noPhysics = options.isFlying;
} }
// if (key == Keyboard::KEY_T) {
// options.thirdPersonView = !options.thirdPersonView;
// /*
// ImprovedNoise noise;
// for (int i = 0; i < 16; ++i)
// printf("%d\t%f\n", i, noise.grad2(i, 3, 8));
// */
// }
if (key == Keyboard::KEY_O) {
useAmbientOcclusion = !useAmbientOcclusion;
options.ambientOcclusion = useAmbientOcclusion;
levelRenderer->allChanged();
}
if (key == Keyboard::KEY_L) if (key == Keyboard::KEY_L)
options.viewDistance = (options.viewDistance + 1) % 4; options.viewDistance = (options.viewDistance + 1) % 4;
@@ -879,7 +865,18 @@ void Minecraft::tickInput() {
static bool prevMouseDownLeft = false; static bool prevMouseDownLeft = false;
// Destroy and attack is on same button if (Mouse::getButtonState(MouseAction::ACTION_LEFT) == 0) {
gameMode->stopDestroyBlock();
}
if (useTouchscreen()) {
// Touch: gesture recognizer classifies the action type (turn/destroy/build)
BuildActionIntention bai;
if (inputHolder && inputHolder->getBuildInput()->tickBuild(player, &bai)) {
handleBuildAction(&bai);
}
} else {
// Desktop: left mouse = destroy/attack
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) { if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
auto baiFlags = BuildActionIntention::BAI_REMOVE | BuildActionIntention::BAI_ATTACK; auto baiFlags = BuildActionIntention::BAI_REMOVE | BuildActionIntention::BAI_ATTACK;
@@ -891,11 +888,12 @@ void Minecraft::tickInput() {
prevMouseDownLeft = Mouse::isButtonDown(MouseAction::ACTION_LEFT); prevMouseDownLeft = Mouse::isButtonDown(MouseAction::ACTION_LEFT);
static int buildHoldTicks = 0;
// Build and use/interact is on same button // Build and use/interact is on same button
// USPESHNO spizheno // USPESHNO spizheno
static int buildHoldTicks = 0;
if (Mouse::isButtonDown(MouseAction::ACTION_RIGHT)) { if (Mouse::isButtonDown(MouseAction::ACTION_RIGHT)) {
BuildActionIntention bai(BuildActionIntention::BAI_BUILD | BuildActionIntention::BAI_INTERACT);
handleBuildAction(&bai);
if (buildHoldTicks >= 5) buildHoldTicks = 0; if (buildHoldTicks >= 5) buildHoldTicks = 0;
if (++buildHoldTicks == 1) { if (++buildHoldTicks == 1) {
@@ -905,6 +903,7 @@ void Minecraft::tickInput() {
} else { } else {
buildHoldTicks = 0; buildHoldTicks = 0;
} }
}
lastTickTime = getTimeMs(); lastTickTime = getTimeMs();
@@ -1150,6 +1149,18 @@ void Minecraft::setSize(int w, int h) {
width = w; width = w;
height = h; height = h;
// determine gui scale, optionally overriding auto
if (options.guiScale != 0) {
// manual selection: 1->small, 2->normal, 3->large, 4->larger
switch (options.guiScale) {
case 1: Gui::GuiScale = 2.0f; break;
case 2: Gui::GuiScale = 3.0f; break;
case 3: Gui::GuiScale = 4.0f; break;
case 4: Gui::GuiScale = 5.0f; break; // bigger than large
default: Gui::GuiScale = 1.0f; break; // auto
}
} else {
// auto compute from resolution
if (width >= 1000) { if (width >= 1000) {
#ifdef __APPLE__ #ifdef __APPLE__
Gui::GuiScale = (width > 2000)? 8.0f : 4.0f; Gui::GuiScale = (width > 2000)? 8.0f : 4.0f;
@@ -1168,6 +1179,7 @@ void Minecraft::setSize(int w, int h) {
Gui::GuiScale = 2.0f; Gui::GuiScale = 2.0f;
else else
Gui::GuiScale = 1.0f; Gui::GuiScale = 1.0f;
}
Gui::InvGuiScale = 1.0f / Gui::GuiScale; Gui::InvGuiScale = 1.0f / Gui::GuiScale;
int screenWidth = (int)(width * Gui::InvGuiScale); int screenWidth = (int)(width * Gui::InvGuiScale);
@@ -1220,7 +1232,12 @@ void Minecraft::_reloadInput() {
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
delete inputHolder; delete inputHolder;
if (useTouchscreen() && !PLATFORM_DESKTOP) { #ifdef PLATFORM_DESKTOP
const bool useTouchHolder = false;
#else
const bool useTouchHolder = useTouchscreen();
#endif
if (useTouchHolder) {
inputHolder = new TouchInputHolder(this, &options); inputHolder = new TouchInputHolder(this, &options);
} else { } else {
#if defined(ANDROID) || defined(__APPLE__) #if defined(ANDROID) || defined(__APPLE__)
@@ -1272,6 +1289,31 @@ bool Minecraft::joinMultiplayer( const PingedCompatibleServer& server )
return false; return false;
} }
bool Minecraft::joinMultiplayerFromString( const std::string& server )
{
std::string ip = "";
std::string port = "19132";
size_t pos = server.find(":");
if (pos != std::string::npos) {
ip = server.substr(0, pos);
port = server.substr(pos + 1);
} else {
ip = server;
}
printf("%s \n", port.c_str());
if (isLookingForMultiplayer && netCallback) {
isLookingForMultiplayer = false;
printf("test");
int portNum = atoi(port.c_str());
return raknetInstance->connect(ip.c_str(), portNum);
}
return false;
}
void Minecraft::hostMultiplayer(int port) { void Minecraft::hostMultiplayer(int port) {
// Tear down last instance // Tear down last instance
raknetInstance->disconnect(); raknetInstance->disconnect();
@@ -1439,11 +1481,11 @@ LevelStorageSource* Minecraft::getLevelSource()
return storageSource; return storageSource;
} }
int Minecraft::getLicenseId() { // int Minecraft::getLicenseId() {
if (!LicenseCodes::isReady(_licenseId)) // if (!LicenseCodes::isReady(_licenseId))
_licenseId = platform()->checkLicense(); // _licenseId = platform()->checkLicense();
return _licenseId; // return _licenseId;
} // }
void Minecraft::audioEngineOn() { void Minecraft::audioEngineOn() {
#ifndef STANDALONE_SERVER #ifndef STANDALONE_SERVER
@@ -1530,5 +1572,8 @@ void Minecraft::optionUpdated( const Options::Option* option, float value ) {
} }
void Minecraft::optionUpdated( const Options::Option* option, int value ) { void Minecraft::optionUpdated( const Options::Option* option, int value ) {
if(option == &Options::Option::GUI_SCALE) {
// reapply screen scaling using current window size
setSize(width, height);
}
} }

View File

@@ -80,6 +80,7 @@ public:
void locateMultiplayer(); void locateMultiplayer();
void cancelLocateMultiplayer(); void cancelLocateMultiplayer();
bool joinMultiplayer(const PingedCompatibleServer& server); bool joinMultiplayer(const PingedCompatibleServer& server);
bool joinMultiplayerFromString(const std::string& server);
void hostMultiplayer(int port=19132); void hostMultiplayer(int port=19132);
Player* respawnPlayer(int playerId); Player* respawnPlayer(int playerId);
void respawnPlayer(); void respawnPlayer();
@@ -109,7 +110,6 @@ public:
void onGraphicsReset(); void onGraphicsReset();
bool isLevelGenerated(); bool isLevelGenerated();
int getLicenseId();
void audioEngineOn(); void audioEngineOn();
void audioEngineOff(); void audioEngineOff();

View File

@@ -5,6 +5,8 @@ const char* OptionStrings::Multiplayer_ServerVisible = "mp_server_visible_defa
const char* OptionStrings::Graphics_Fancy = "gfx_fancygraphics"; const char* OptionStrings::Graphics_Fancy = "gfx_fancygraphics";
const char* OptionStrings::Graphics_LowQuality = "gfx_lowquality"; const char* OptionStrings::Graphics_LowQuality = "gfx_lowquality";
const char* OptionStrings::Graphics_Vsync = "gfx_vsync";
const char* OptionStrings::Graphics_GUIScale = "gfx_guiscale";
const char* OptionStrings::Controls_Sensitivity = "ctrl_sensitivity"; const char* OptionStrings::Controls_Sensitivity = "ctrl_sensitivity";
const char* OptionStrings::Controls_InvertMouse = "ctrl_invertmouse"; const char* OptionStrings::Controls_InvertMouse = "ctrl_invertmouse";

View File

@@ -8,7 +8,8 @@ public:
static const char* Graphics_Fancy; static const char* Graphics_Fancy;
static const char* Graphics_LowQuality; static const char* Graphics_LowQuality;
static const char* Graphics_GUIScale;
static const char* Graphics_Vsync;
static const char* Controls_Sensitivity; static const char* Controls_Sensitivity;
static const char* Controls_InvertMouse; static const char* Controls_InvertMouse;
static const char* Controls_UseTouchScreen; static const char* Controls_UseTouchScreen;

View File

@@ -34,6 +34,7 @@ void Options::initDefaultValues() {
bobView = true; bobView = true;
anaglyph3d = false; anaglyph3d = false;
limitFramerate = false; limitFramerate = false;
vsync = true;
fancyGraphics = true;//false; fancyGraphics = true;//false;
ambientOcclusion = false; ambientOcclusion = false;
if(minecraft->supportNonTouchScreen()) if(minecraft->supportNonTouchScreen())
@@ -44,7 +45,7 @@ void Options::initDefaultValues() {
//useMouseForDigging = true; //useMouseForDigging = true;
//skin = "Default"; //skin = "Default";
username = "Steve"; username = "";
serverVisible = true; serverVisible = true;
keyUp = KeyMapping("key.forward", Keyboard::KEY_W); keyUp = KeyMapping("key.forward", Keyboard::KEY_W);
@@ -144,7 +145,8 @@ const Options::Option
Options::Option::USE_TOUCHSCREEN (16, "options.usetouchscreen", false, true), Options::Option::USE_TOUCHSCREEN (16, "options.usetouchscreen", false, true),
Options::Option::USE_TOUCH_JOYPAD (17, "options.usetouchpad", false, true), Options::Option::USE_TOUCH_JOYPAD (17, "options.usetouchpad", false, true),
Options::Option::DESTROY_VIBRATION (18, "options.destroyvibration", false, true), Options::Option::DESTROY_VIBRATION (18, "options.destroyvibration", false, true),
Options::Option::PIXELS_PER_MILLIMETER(19, "options.pixelspermilimeter", true, false); Options::Option::PIXELS_PER_MILLIMETER(19, "options.pixelspermilimeter", true, false),
Options::Option::VSYNC (20, "options.vsync", false, true);
/* private */ /* private */
const float Options::SOUND_MIN_VALUE = 0.0f; const float Options::SOUND_MIN_VALUE = 0.0f;
@@ -181,7 +183,8 @@ const char* Options::GUI_SCALE[] = {
"options.guiScale.auto", "options.guiScale.auto",
"options.guiScale.small", "options.guiScale.small",
"options.guiScale.normal", "options.guiScale.normal",
"options.guiScale.large" "options.guiScale.large",
"options.guiScale.larger"
}; };
void Options::update() void Options::update()
@@ -235,6 +238,13 @@ void Options::update()
fancyGraphics = false; fancyGraphics = false;
} }
} }
// Graphics extras
if (key == OptionStrings::Graphics_Vsync)
readBool(value, vsync);
if (key == OptionStrings::Graphics_GUIScale) {
int v;
if (readInt(value, v)) guiScale = v % 5;
}
// Game // Game
if (key == OptionStrings::Game_DifficultyLevel) { if (key == OptionStrings::Game_DifficultyLevel) {
readInt(value, difficulty); readInt(value, difficulty);
@@ -294,6 +304,8 @@ void Options::load()
void Options::save() void Options::save()
{ {
StringVector stringVec; StringVector stringVec;
// Login
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_Username, username);
// Game // Game
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_ServerVisible, serverVisible); addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_ServerVisible, serverVisible);
addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty); addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty);
@@ -305,6 +317,8 @@ void Options::save()
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchScreen, useTouchScreen); addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchScreen, useTouchScreen);
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchJoypad, isJoyTouchArea); addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchJoypad, isJoyTouchArea);
addOptionToSaveOutput(stringVec, OptionStrings::Controls_FeedbackVibration, destroyVibration); addOptionToSaveOutput(stringVec, OptionStrings::Controls_FeedbackVibration, destroyVibration);
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Vsync, vsync);
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_GUIScale, guiScale);
// //
// static const Option MUSIC; // static const Option MUSIC;
// static const Option SOUND; // static const Option SOUND;
@@ -348,6 +362,7 @@ void Options::save()
// System.out.println("Failed to save options"); // System.out.println("Failed to save options");
// e.printStackTrace(); // e.printStackTrace();
//} //}
optionsFile.save(stringVec);
} }
void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name, bool boolValue) { void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name, bool boolValue) {
std::stringstream ss; std::stringstream ss;
@@ -364,6 +379,9 @@ void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name
ss << name << ":" << intValue; ss << name << ":" << intValue;
stringVector.push_back(ss.str()); stringVector.push_back(ss.str());
} }
void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name, const std::string& strValue) {
stringVector.push_back(name + ":" + strValue);
}
std::string Options::getMessage( const Option* item ) std::string Options::getMessage( const Option* item )
{ {

View File

@@ -48,6 +48,7 @@ public:
static const Option DESTROY_VIBRATION; static const Option DESTROY_VIBRATION;
static const Option PIXELS_PER_MILLIMETER; static const Option PIXELS_PER_MILLIMETER;
static const Option VSYNC;
/* /*
static Option* getItem(int id) { static Option* getItem(int id) {
@@ -113,6 +114,7 @@ public:
bool bobView; bool bobView;
bool anaglyph3d; bool anaglyph3d;
bool limitFramerate; bool limitFramerate;
bool vsync;
bool fancyGraphics; bool fancyGraphics;
bool ambientOcclusion; bool ambientOcclusion;
bool useMouseForDigging; bool useMouseForDigging;
@@ -206,19 +208,21 @@ public:
} else if (item == &Option::PIXELS_PER_MILLIMETER) { } else if (item == &Option::PIXELS_PER_MILLIMETER) {
pixelsPerMillimeter = value; pixelsPerMillimeter = value;
} }
notifyOptionUpdate(item, value); notifyOptionUpdate(item, value); save(); }
}
void set(const Option* item, int value) { void set(const Option* item, int value) {
if(item == &Option::DIFFICULTY) { if(item == &Option::DIFFICULTY) {
difficulty = value; difficulty = value;
} else if(item == &Option::GUI_SCALE) {
guiScale = value % 5;
} }
notifyOptionUpdate(item, value); notifyOptionUpdate(item, value);
save();
} }
void toggle(const Option* option, int dir) { void toggle(const Option* option, int dir) {
if (option == &Option::INVERT_MOUSE) invertYMouse = !invertYMouse; if (option == &Option::INVERT_MOUSE) invertYMouse = !invertYMouse;
if (option == &Option::RENDER_DISTANCE) viewDistance = (viewDistance + dir) & 3; if (option == &Option::RENDER_DISTANCE) viewDistance = (viewDistance + dir) & 3;
if (option == &Option::GUI_SCALE) guiScale = (guiScale + dir) & 3; if (option == &Option::GUI_SCALE) guiScale = (guiScale + dir) % 5;
if (option == &Option::VIEW_BOBBING) bobView = !bobView; if (option == &Option::VIEW_BOBBING) bobView = !bobView;
if (option == &Option::THIRD_PERSON) thirdPersonView = !thirdPersonView; if (option == &Option::THIRD_PERSON) thirdPersonView = !thirdPersonView;
if (option == &Option::HIDE_GUI) hideGui = !hideGui; if (option == &Option::HIDE_GUI) hideGui = !hideGui;
@@ -232,6 +236,7 @@ public:
//minecraft->textures.reloadAll(); //minecraft->textures.reloadAll();
} }
if (option == &Option::LIMIT_FRAMERATE) limitFramerate = !limitFramerate; if (option == &Option::LIMIT_FRAMERATE) limitFramerate = !limitFramerate;
if (option == &Option::VSYNC) vsync = !vsync;
if (option == &Option::DIFFICULTY) difficulty = (difficulty + dir) & 3; if (option == &Option::DIFFICULTY) difficulty = (difficulty + dir) & 3;
if (option == &Option::GRAPHICS) { if (option == &Option::GRAPHICS) {
fancyGraphics = !fancyGraphics; fancyGraphics = !fancyGraphics;
@@ -247,6 +252,7 @@ public:
int getIntValue(const Option* item) { int getIntValue(const Option* item) {
if(item == &Option::DIFFICULTY) return difficulty; if(item == &Option::DIFFICULTY) return difficulty;
if(item == &Option::GUI_SCALE) return guiScale;
return 0; return 0;
} }
@@ -267,6 +273,8 @@ public:
return anaglyph3d; return anaglyph3d;
if (item == &Option::LIMIT_FRAMERATE) if (item == &Option::LIMIT_FRAMERATE)
return limitFramerate; return limitFramerate;
if (item == &Option::VSYNC)
return vsync;
if (item == &Option::AMBIENT_OCCLUSION) if (item == &Option::AMBIENT_OCCLUSION)
return ambientOcclusion; return ambientOcclusion;
if (item == &Option::THIRD_PERSON) if (item == &Option::THIRD_PERSON)
@@ -312,6 +320,7 @@ public:
void addOptionToSaveOutput(StringVector& stringVector, std::string name, bool boolValue); void addOptionToSaveOutput(StringVector& stringVector, std::string name, bool boolValue);
void addOptionToSaveOutput(StringVector& stringVector, std::string name, float floatValue); void addOptionToSaveOutput(StringVector& stringVector, std::string name, float floatValue);
void addOptionToSaveOutput(StringVector& stringVector, std::string name, int intValue); void addOptionToSaveOutput(StringVector& stringVector, std::string name, int intValue);
void addOptionToSaveOutput(StringVector& stringVector, std::string name, const std::string& strValue);
void notifyOptionUpdate(const Option* option, bool value); void notifyOptionUpdate(const Option* option, bool value);
void notifyOptionUpdate(const Option* option, float value); void notifyOptionUpdate(const Option* option, float value);
void notifyOptionUpdate(const Option* option, int value); void notifyOptionUpdate(const Option* option, int value);

View File

@@ -1,6 +1,7 @@
#include "OptionsFile.h" #include "OptionsFile.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <platform/log.h>
OptionsFile::OptionsFile() { OptionsFile::OptionsFile() {
#ifdef __APPLE__ #ifdef __APPLE__
@@ -19,19 +20,32 @@ void OptionsFile::save(const StringVector& settings) {
fprintf(pFile, "%s\n", it->c_str()); fprintf(pFile, "%s\n", it->c_str());
} }
fclose(pFile); fclose(pFile);
} else {
LOGI("OptionsFile::save failed to open '%s' for writing: %s", settingsPath.c_str(), strerror(errno));
} }
} }
StringVector OptionsFile::getOptionStrings() { StringVector OptionsFile::getOptionStrings() {
StringVector returnVector; StringVector returnVector;
FILE* pFile = fopen(settingsPath.c_str(), "w"); FILE* pFile = fopen(settingsPath.c_str(), "r");
if(pFile != NULL) { if(pFile != NULL) {
char lineBuff[128]; char lineBuff[128];
while(fgets(lineBuff, sizeof lineBuff, pFile)) { while(fgets(lineBuff, sizeof lineBuff, pFile)) {
if(strlen(lineBuff) > 2) // Strip trailing newline
returnVector.push_back(std::string(lineBuff)); size_t len = strlen(lineBuff);
while(len > 0 && (lineBuff[len-1] == '\n' || lineBuff[len-1] == '\r'))
lineBuff[--len] = '\0';
if(len < 3) continue;
// Split "key:value" into two separate entries to match update() pairing
char* colon = strchr(lineBuff, ':');
if(colon) {
returnVector.push_back(std::string(lineBuff, colon - lineBuff));
returnVector.push_back(std::string(colon + 1));
}
} }
fclose(pFile); fclose(pFile);
} else {
LOGI("OptionsFile::getOptionStrings failed to open '%s' for reading: %s", settingsPath.c_str(), strerror(errno));
} }
return returnVector; return returnVector;
} }

View File

@@ -21,6 +21,8 @@
#include "../../platform/input/Mouse.h" #include "../../platform/input/Mouse.h"
#include "../../world/level/Level.h" #include "../../world/level/Level.h"
#include "../../world/PosTranslator.h" #include "../../world/PosTranslator.h"
#include "../../platform/time.h"
#include <cmath>
float Gui::InvGuiScale = 1.0f / 3.0f; float Gui::InvGuiScale = 1.0f / 3.0f;
float Gui::GuiScale = 1.0f / Gui::InvGuiScale; float Gui::GuiScale = 1.0f / Gui::InvGuiScale;
@@ -116,6 +118,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
#endif #endif
#if defined(RPI) #if defined(RPI)
renderDebugInfo(); renderDebugInfo();
#elif defined(PLATFORM_DESKTOP)
if (minecraft->options.renderDebug)
renderDebugInfo();
#endif #endif
glDisable(GL_BLEND); glDisable(GL_BLEND);
@@ -632,17 +637,87 @@ void Gui::onLevelGenerated() {
} }
void Gui::renderDebugInfo() { void Gui::renderDebugInfo() {
static char buf[256]; // FPS counter (updates once per second)
float xx = minecraft->player->x; static float fps = 0.0f;
float yy = minecraft->player->y - minecraft->player->heightOffset; static float fpsLastTime = 0.0f;
float zz = minecraft->player->z; static int fpsFrames = 0;
posTranslator.to(xx, yy, zz); float now = getTimeS();
sprintf(buf, "pos: %3.1f, %3.1f, %3.1f\n", xx, yy, zz); fpsFrames++;
if (now - fpsLastTime >= 1.0f) {
fps = fpsFrames / (now - fpsLastTime);
fpsFrames = 0;
fpsLastTime = now;
}
LocalPlayer* p = minecraft->player;
Level* lvl = minecraft->level;
// Position
float px = p->x, py = p->y - p->heightOffset, pz = p->z;
posTranslator.to(px, py, pz);
int bx = (int)floorf(px), by = (int)floorf(py), bz = (int)floorf(pz);
int cx = bx >> 4, cz = bz >> 4;
// Facing direction
float yMod = fmodf(p->yRot, 360.0f);
if (yMod < 0) yMod += 360.0f;
const char* facing;
const char* axis;
if (yMod < 45 || yMod >= 315) { facing = "South"; axis = "+Z"; }
else if (yMod < 135) { facing = "West"; axis = "-X"; }
else if (yMod < 225) { facing = "North"; axis = "-Z"; }
else { facing = "East"; axis = "+X"; }
// Biome
const char* biomeName = "unknown";
if (lvl) {
Biome* biome = lvl->getBiome(bx, bz);
if (biome) biomeName = biome->name.c_str();
}
// Time
long worldTime = lvl ? lvl->getTime() : 0;
long dayTime = worldTime % Level::TICKS_PER_DAY;
long day = worldTime / Level::TICKS_PER_DAY;
long seed = lvl ? lvl->getSeed() : 0;
// Build lines (NULL entry = blank gap)
static char ln[8][96];
sprintf(ln[0], "Minecraft PE 0.6.1 alpha (mcpe64)");
sprintf(ln[1], "%.1f fps", fps);
ln[2][0] = '\0'; // blank separator
sprintf(ln[3], "XYZ: %.3f / %.3f / %.3f", px, py, pz);
sprintf(ln[4], "Block: %d %d %d Chunk: %d %d", bx, by, bz, cx, cz);
sprintf(ln[5], "Facing: %s (%s) (%.1f / %.1f)", facing, axis, p->yRot, p->xRot);
sprintf(ln[6], "Biome: %s", biomeName);
sprintf(ln[7], "Day %ld Time: %ld Seed: %ld", day, dayTime, seed);
const int N = 8;
const float LH = (float)Font::DefaultLineHeight; // 10 font-pixels
const float MGN = 2.0f; // left/top margin in font-pixels
const float PAD = 2.0f; // horizontal padding for background
Font* font = minecraft->font;
// 1) Draw semi-transparent background boxes behind each line
for (int i = 0; i < N; i++) {
if (ln[i][0] == '\0') continue;
float w = (float)font->width(ln[i]);
float x0 = MGN - PAD;
float y0 = MGN + i * LH - 1.0f;
float x1 = MGN + w + PAD;
float y1 = MGN + (i + 1) * LH - 1.0f;
fill(x0, y0, x1, y1, 0x90000000);
}
// 2) Draw text (no extra scale — font coords are in GUI units, same as fill)
Tesselator& t = Tesselator::instance; Tesselator& t = Tesselator::instance;
t.beginOverride(); t.beginOverride();
t.scale2d(InvGuiScale, InvGuiScale); for (int i = 0; i < N; i++) {
minecraft->font->draw(buf, 2, 2, 0xffffff); if (ln[i][0] == '\0') continue;
t.resetScale(); float y = MGN + i * LH;
int col = (i == 0) ? 0xffFFFF55 : 0xffffffff; // title yellow, rest white
font->draw(ln[i], MGN, y, col);
}
t.endOverrideAndDraw(); t.endOverrideAndDraw();
} }
@@ -676,6 +751,70 @@ void Gui::renderOnSelectItemNameText( const int screenWidth, Font* font, int ySl
} }
} }
// helper structure used by drawColoredString
struct ColorSegment {
std::string text;
uint32_t color;
};
// parse [tag] and [/tag] markers; tags may contain a color name (gold, green, etc.)
static void parseColorTags(const std::string& in, std::vector<ColorSegment>& out) {
uint32_t curColor = 0xffffff;
size_t pos = 0;
while (pos < in.size()) {
size_t open = in.find('[', pos);
if (open == std::string::npos) {
out.push_back({in.substr(pos), curColor});
break;
}
if (open > pos) {
out.push_back({in.substr(pos, open - pos), curColor});
}
size_t close = in.find(']', open);
if (close == std::string::npos) {
out.push_back({in.substr(open), curColor});
break;
}
std::string tag = in.substr(open + 1, close - open - 1);
if (!tag.empty() && tag[0] == '/') {
curColor = 0xffffff;
} else {
std::string lower;
lower.resize(tag.size());
std::transform(tag.begin(), tag.end(), lower.begin(), ::tolower);
if (lower.find("gold") != std::string::npos) curColor = 0xffd700;
else if (lower.find("green") != std::string::npos) curColor = 0x00ff00;
else if (lower.find("yellow") != std::string::npos) curColor = 0xffff00;
else if (lower.find("red") != std::string::npos) curColor = 0xff0000;
else if (lower.find("blue") != std::string::npos) curColor = 0x0000ff;
}
pos = close + 1;
}
}
void Gui::drawColoredString(Font* font, const std::string& text, float x, float y, int alpha) {
std::vector<ColorSegment> segs;
parseColorTags(text, segs);
float cx = x;
for (auto &s : segs) {
int color = s.color + (alpha << 24);
font->drawShadow(s.text, cx, y, color);
cx += font->width(s.text);
}
}
float Gui::getColoredWidth(Font* font, const std::string& text) {
std::vector<ColorSegment> segs;
parseColorTags(text, segs);
float w = 0;
for (auto &s : segs) {
w += font->width(s.text);
}
return w;
}
void Gui::renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font ) { void Gui::renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font ) {
// if (minecraft.screen instanceof ChatScreen) { // if (minecraft.screen instanceof ChatScreen) {
// max = 20; // max = 20;
@@ -709,7 +848,14 @@ void Gui::renderChatMessages( const int screenHeight, unsigned int max, bool isC
this->fill(x, y - 1, x + MAX_MESSAGE_WIDTH, y + 8, (alpha / 2) << 24); this->fill(x, y - 1, x + MAX_MESSAGE_WIDTH, y + 8, (alpha / 2) << 24);
glEnable(GL_BLEND); glEnable(GL_BLEND);
font->drawShadow(msg, x, y, 0xffffff + (alpha << 24)); // special-case join/leave announcements
int baseColor = 0xffffff;
if (msg.find(" joined the game") != std::string::npos ||
msg.find(" left the game") != std::string::npos) {
baseColor = 0xffff00; // yellow
}
// replace previous logic; allow full colour tags now
Gui::drawColoredString(font, msg, x, y, alpha);
} }
} }
} }

View File

@@ -47,6 +47,12 @@ public:
void renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font ); void renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font );
// draw a string containing simple [color]...[/color] tags; color names are matched
// case-insensitively and default to white. alpha is applied to each segment.
// draw tagged string (ignores simple [color]…[/color] tags)
static void drawColoredString(Font* font, const std::string& text, float x, float y, int alpha);
static float getColoredWidth(Font* font, const std::string& text);
void renderOnSelectItemNameText( const int screenWidth, Font* font, int ySlot ); void renderOnSelectItemNameText( const int screenWidth, Font* font, int ySlot );
void renderSleepAnimation( const int screenWidth, const int screenHeight ); void renderSleepAnimation( const int screenWidth, const int screenHeight );

View File

@@ -25,6 +25,12 @@ void Screen::render( int xm, int ym, float a )
Button* button = buttons[i]; Button* button = buttons[i];
button->render(minecraft, xm, ym); button->render(minecraft, xm, ym);
} }
// render any text boxes after buttons
for (unsigned int i = 0; i < textBoxes.size(); i++) {
TextBox* textbox = textBoxes[i];
textbox->render(minecraft, xm, ym);
}
} }
void Screen::init( Minecraft* minecraft, int width, int height ) void Screen::init( Minecraft* minecraft, int width, int height )
@@ -157,6 +163,12 @@ void Screen::keyPressed( int eventKey )
minecraft->setScreen(NULL); minecraft->setScreen(NULL);
//minecraft->grabMouse(); //minecraft->grabMouse();
} }
// pass key events to any text boxes first
for (auto& textbox : textBoxes) {
textbox->handleKey(eventKey);
}
if (minecraft->useTouchscreen()) if (minecraft->useTouchscreen())
return; return;
@@ -210,6 +222,11 @@ void Screen::mouseClicked( int x, int y, int buttonNum )
} }
} }
} }
// let textboxes see the click regardless
for (auto& textbox : textBoxes) {
textbox->mouseClicked(minecraft, x, y, buttonNum);
}
} }
void Screen::mouseReleased( int x, int y, int buttonNum ) void Screen::mouseReleased( int x, int y, int buttonNum )

View File

@@ -10,7 +10,7 @@ OptionsGroup::OptionsGroup( std::string labelID ) {
void OptionsGroup::setupPositions() { void OptionsGroup::setupPositions() {
// First we write the header and then we add the items // First we write the header and then we add the items
int curY = y + 10; int curY = y + 18;
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) { for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->width = width - 5; (*it)->width = width - 5;
@@ -23,7 +23,9 @@ void OptionsGroup::setupPositions() {
} }
void OptionsGroup::render( Minecraft* minecraft, int xm, int ym ) { void OptionsGroup::render( Minecraft* minecraft, int xm, int ym ) {
minecraft->font->draw(label, (float)x + 2, (float)y, 0xffffffff, false); float padX = 10.0f;
float padY = 5.0f;
minecraft->font->draw(label, (float)x + padX, (float)y + padY, 0xffffffff, false);
super::render(minecraft, xm, ym); super::render(minecraft, xm, ym);
} }
@@ -45,6 +47,7 @@ void OptionsGroup::createToggle( const Options::Option* option, Minecraft* minec
def.height = 20 * 0.7f; def.height = 20 * 0.7f;
OptionButton* element = new OptionButton(option); OptionButton* element = new OptionButton(option);
element->setImageDef(def, true); element->setImageDef(def, true);
element->updateImage(&minecraft->options);
std::string itemLabel = I18n::get(option->getCaptionId()); std::string itemLabel = I18n::get(option->getCaptionId());
OptionsItem* item = new OptionsItem(itemLabel, element); OptionsItem* item = new OptionsItem(itemLabel, element);
addChild(item); addChild(item);
@@ -58,11 +61,38 @@ void OptionsGroup::createProgressSlider( const Options::Option* option, Minecraf
minecraft->options.getProgrssMax(option)); minecraft->options.getProgrssMax(option));
element->width = 100; element->width = 100;
element->height = 20; element->height = 20;
OptionsItem* item = new OptionsItem(label, element); std::string itemLabel = I18n::get(option->getCaptionId());
OptionsItem* item = new OptionsItem(itemLabel, element);
addChild(item); addChild(item);
setupPositions(); setupPositions();
} }
void OptionsGroup::createStepSlider( const Options::Option* option, Minecraft* minecraft ) { void OptionsGroup::createStepSlider( const Options::Option* option, Minecraft* minecraft ) {
// integer-valued option; use step slider
std::vector<int> steps;
// render distance was removed; fall through to other cases
if(option == &Options::Option::DIFFICULTY) {
steps.push_back(0);
steps.push_back(1);
steps.push_back(2);
steps.push_back(3);
} else if(option == &Options::Option::GUI_SCALE) {
// slider order: small,normal,large,larger,auto
steps.push_back(1);
steps.push_back(2);
steps.push_back(3);
steps.push_back(4);
steps.push_back(0);
} else {
// fallback: use single value; duplicate so numSteps>1 and avoid divide-by-zero
steps.push_back(0);
steps.push_back(0);
}
Slider* element = new Slider(minecraft, option, steps);
element->width = 100;
element->height = 20;
std::string itemLabel = I18n::get(option->getCaptionId());
OptionsItem* item = new OptionsItem(itemLabel, element);
addChild(item);
setupPositions();
} }

View File

@@ -25,13 +25,17 @@ Slider::Slider(Minecraft* minecraft, const Options::Option* option, const std::v
assert(stepVec.size() > 1); assert(stepVec.size() > 1);
numSteps = sliderSteps.size(); numSteps = sliderSteps.size();
if(option != NULL) { if(option != NULL) {
curStepValue; // initialize slider position based on the current option value
int curStep;
curStepValue = minecraft->options.getIntValue(option); curStepValue = minecraft->options.getIntValue(option);
std::vector<int>::iterator currentItem = std::find(sliderSteps.begin(), sliderSteps.end(), curStepValue); auto currentItem = std::find(sliderSteps.begin(), sliderSteps.end(), curStepValue);
if(currentItem != sliderSteps.end()) { if(currentItem != sliderSteps.end()) {
curStep = currentItem - sliderSteps.begin(); curStep = static_cast<int>(currentItem - sliderSteps.begin());
} else {
// fallback to first step
curStep = 0;
curStepValue = sliderSteps[0];
} }
percentage = float(curStep) / float(numSteps - 1);
} }
} }
@@ -46,12 +50,17 @@ void Slider::render( Minecraft* minecraft, int xm, int ym ) {
//fill(x, y + 8, x + (int)(width * percentage), y + height, 0xffff00ff); //fill(x, y + 8, x + (int)(width * percentage), y + height, 0xffff00ff);
fill(xSliderStart, ySliderStart, xSliderEnd, ySliderEnd, 0xff606060); fill(xSliderStart, ySliderStart, xSliderEnd, ySliderEnd, 0xff606060);
if(sliderType == SliderStep) { if(sliderType == SliderStep) {
// numSteps should be >=2; protect against bad input (zero division)
if(numSteps <= 1) {
// nothing to render
} else {
int stepDistance = barWidth / (numSteps -1); int stepDistance = barWidth / (numSteps -1);
for(int a = 0; a <= numSteps - 1; ++a) { for(int a = 0; a <= numSteps - 1; ++a) {
int renderSliderStepPosX = xSliderStart + a * stepDistance + 1; int renderSliderStepPosX = xSliderStart + a * stepDistance + 1;
fill(renderSliderStepPosX - 1, ySliderStart - 2, renderSliderStepPosX + 1, ySliderEnd + 2, 0xff606060); fill(renderSliderStepPosX - 1, ySliderStart - 2, renderSliderStepPosX + 1, ySliderEnd + 2, 0xff606060);
} }
} }
}
minecraft->textures->loadAndBindTexture("gui/touchgui.png"); minecraft->textures->loadAndBindTexture("gui/touchgui.png");
blit(xSliderStart + (int)(percentage * barWidth) - handleSizeX / 2, y, 226, 126, handleSizeX, handleSizeY, handleSizeX, handleSizeY); blit(xSliderStart + (int)(percentage * barWidth) - handleSizeX / 2, y, 226, 126, handleSizeX, handleSizeY, handleSizeX, handleSizeY);
} }

View File

@@ -1,37 +1,102 @@
#include "TextBox.h" #include "TextBox.h"
#include "../Gui.h"
#include "../../Minecraft.h" #include "../../Minecraft.h"
#include "../../../AppPlatform.h" #include "../../../AppPlatform.h"
TextBox::TextBox( int id, const std::string& msg ) #include "../../../platform/input/Mouse.h"
: id(0), w(0), h(0), x(0), y(0), text(msg), focused(false) {
// delegate constructors
TextBox::TextBox(int id, const std::string& msg)
: TextBox(id, 0, 0, msg)
{
} }
TextBox::TextBox( int id, int x, int y, const std::string& msg ) TextBox::TextBox(int id, int x, int y, const std::string& msg)
: id(id), w(0), h(0), x(x), y(y), text(msg), focused(false) { : TextBox(id, x, y, 24, Font::DefaultLineHeight + 4, msg)
{
} }
TextBox::TextBox( int id, int x, int y, int w, int h, const std::string& msg ) TextBox::TextBox(int id, int x, int y, int w, int h, const std::string& msg)
: id(id), w(w), h(h), x(x), y(y), text(msg) { : GuiElement(true, true, x, y, w, h),
id(id), hint(msg), focused(false), blink(false), blinkTicks(0)
{
} }
void TextBox::setFocus(Minecraft* minecraft) { void TextBox::setFocus(Minecraft* minecraft) {
if(!focused) { if (!focused) {
minecraft->platform()->showKeyboard(); minecraft->platform()->showKeyboard();
focused = true; focused = true;
blinkTicks = 0;
blink = false;
} }
} }
bool TextBox::loseFocus(Minecraft* minecraft) { bool TextBox::loseFocus(Minecraft* minecraft) {
if(focused) { if (focused) {
minecraft->platform()->showKeyboard(); minecraft->platform()->hideKeyboard();
focused = false; focused = false;
return true; return true;
} }
return false; return false;
} }
void TextBox::render( Minecraft* minecraft, int xm, int ym ) { void TextBox::mouseClicked(Minecraft* minecraft, int x, int y, int buttonNum) {
if (buttonNum == MouseAction::ACTION_LEFT) {
if (pointInside(x, y)) {
setFocus(minecraft);
} else {
loseFocus(minecraft);
}
}
}
void TextBox::handleChar(char c) {
if (focused && c >= 32 && c < 127 && (int)text.size() < 256) {
text.push_back(c);
}
}
void TextBox::handleKey(int key) {
if (focused && key == Keyboard::KEY_BACKSPACE && !text.empty()) {
text.pop_back();
}
}
void TextBox::tick(Minecraft* minecraft) {
blinkTicks++;
if (blinkTicks >= 5) {
blink = !blink;
blinkTicks = 0;
}
}
void TextBox::render(Minecraft* minecraft, int xm, int ym) {
// textbox like in beta 1.7.3
// change appearance when focused so the user can tell it's active
// active background darker gray with a subtle border
uint32_t bgColor = focused ? 0xffa0a0a0 : 0xffa0a0a0;
uint32_t borderColor = focused ? 0xff000000 : 0xff000000;
fill(x, y, x + width, y + height, bgColor);
fill(x + 1, y + 1, x + width - 1, y + height - 1, borderColor);
glEnable2(GL_SCISSOR_TEST);
glScissor(
Gui::GuiScale * (x + 2),
minecraft->height - Gui::GuiScale * (y + height - 2),
Gui::GuiScale * (width - 2),
Gui::GuiScale * (height - 2)
);
int _y = y + (height - Font::DefaultLineHeight) / 2;
if (text.empty() && !focused) {
drawString(minecraft->font, hint, x + 2, _y, 0xff5e5e5e);
}
if (focused && blink) text.push_back('_');
drawString(minecraft->font, text, x + 2, _y, 0xffffffff);
if (focused && blink) text.pop_back();
glDisable2(GL_SCISSOR_TEST);
} }

View File

@@ -4,31 +4,41 @@
//package net.minecraft.client.gui; //package net.minecraft.client.gui;
#include <string> #include <string>
#include "../GuiComponent.h" #include "GuiElement.h"
#include "../../Options.h" #include "../../Options.h"
#include "../../../platform/input/Mouse.h"
#include "../../../platform/input/Keyboard.h"
class Font; class Font;
class Minecraft; class Minecraft;
class TextBox: public GuiComponent class TextBox: public GuiElement
{ {
public: public:
TextBox(int id, const std::string& msg); TextBox(int id, const std::string& msg);
TextBox(int id, int x, int y, const std::string& msg); TextBox(int id, int x, int y, const std::string& msg);
TextBox(int id, int x, int y, int w, int h, const std::string& msg); TextBox(int id, int x, int y, int w, int h, const std::string& msg);
virtual void mouseClicked(Minecraft* minecraft, int x, int y, int buttonNum);
virtual void setFocus(Minecraft* minecraft); virtual void setFocus(Minecraft* minecraft);
virtual bool loseFocus(Minecraft* minecraft); virtual bool loseFocus(Minecraft* minecraft);
virtual void render(Minecraft* minecraft, int xm, int ym); virtual void render(Minecraft* minecraft, int xm, int ym);
public: virtual void handleKey(int key);
int w, h; virtual void handleChar(char c);
int x, y; virtual void tick(Minecraft* minecraft);
public:
std::string hint;
std::string text; std::string text;
int id; int id;
int blinkTicks;
bool focused; bool focused;
bool blink;
}; };
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__TextBox_H__*/ #endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__TextBox_H__*/

View File

@@ -1,26 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__BuyGameScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__BuyGameScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
class BuyGameScreen: public Screen
{
public:
BuyGameScreen() {}
virtual ~BuyGameScreen() {}
void init();
void render(int xm, int ym, float a);
void buttonClicked(Button* button) {
//if (button->id == bQuit.id)
}
private:
//Button bQuit;
//Button bBuyGame;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__BuyGameScreen_H__*/

View File

@@ -0,0 +1,223 @@
#include "ConsoleScreen.h"
#include "../Gui.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
#include "../../../platform/input/Keyboard.h"
#include "../../../world/level/Level.h"
#include "../../../network/RakNetInstance.h"
#include "../../../network/ServerSideNetworkHandler.h"
#include "../../../network/packet/ChatPacket.h"
#include "../../../platform/log.h"
#include <sstream>
#include <cstdlib>
#include <cctype>
ConsoleScreen::ConsoleScreen()
: _input(""),
_cursorBlink(0)
{
}
void ConsoleScreen::init()
{
}
void ConsoleScreen::tick()
{
_cursorBlink++;
}
bool ConsoleScreen::handleBackEvent(bool /*isDown*/)
{
minecraft->setScreen(NULL);
return true;
}
void ConsoleScreen::keyPressed(int eventKey)
{
if (eventKey == Keyboard::KEY_ESCAPE) {
minecraft->setScreen(NULL);
} else if (eventKey == Keyboard::KEY_RETURN) {
execute();
} else if (eventKey == Keyboard::KEY_BACKSPACE) {
if (!_input.empty())
_input.erase(_input.size() - 1, 1);
} else {
super::keyPressed(eventKey);
}
}
void ConsoleScreen::keyboardNewChar(char inputChar)
{
if (inputChar >= 32 && inputChar < 127)
_input += inputChar;
}
// ---------------------------------------------------------------------------
// execute: run _input as a command, print result, close screen
// ---------------------------------------------------------------------------
void ConsoleScreen::execute()
{
if (_input.empty()) {
minecraft->setScreen(NULL);
return;
}
if (_input[0] == '/') {
// Command
std::string result = processCommand(_input);
if (!result.empty())
minecraft->gui.addMessage(result);
} else {
// Chat message: <name> message
std::string msg = std::string("<") + minecraft->player->name + "> " + _input;
if (minecraft->netCallback && minecraft->raknetInstance->isServer()) {
// Hosting a LAN game: displayGameMessage shows locally + broadcasts MessagePacket to clients
static_cast<ServerSideNetworkHandler*>(minecraft->netCallback)->displayGameMessage(msg);
} else if (minecraft->netCallback) {
// Connected client: send ChatPacket to server; server echoes it back as MessagePacket
ChatPacket chatPkt(msg);
minecraft->raknetInstance->send(chatPkt);
} else {
// Singleplayer: show locally only
minecraft->gui.addMessage(msg);
}
}
minecraft->setScreen(NULL);
}
// ---------------------------------------------------------------------------
// processCommand
// ---------------------------------------------------------------------------
static std::string trim(const std::string& s) {
size_t a = s.find_first_not_of(" \t");
if (a == std::string::npos) return "";
size_t b = s.find_last_not_of(" \t");
return s.substr(a, b - a + 1);
}
std::string ConsoleScreen::processCommand(const std::string& raw)
{
// strip leading '/'
std::string line = raw;
if (!line.empty() && line[0] == '/') line = line.substr(1);
line = trim(line);
// tokenise
std::vector<std::string> args;
{
std::istringstream ss(line);
std::string tok;
while (ss >> tok) args.push_back(tok);
}
if (args.empty()) return "";
Level* level = minecraft->level;
if (!level) return "No level loaded.";
// -----------------------------------------------------------------------
// /time ...
// -----------------------------------------------------------------------
if (args[0] == "time") {
if (args.size() < 2)
return "Usage: /time <add|set|query> ...";
const std::string& sub = args[1];
// -- time add <value> -----------------------------------------------
if (sub == "add") {
if (args.size() < 3) return "Usage: /time add <value>";
long delta = std::atol(args[2].c_str());
long newTime = level->getTime() + delta;
level->setTime(newTime);
std::ostringstream out;
out << "Set the time to " << (newTime % Level::TICKS_PER_DAY);
return out.str();
}
// -- time set <value|day|night|noon|midnight> -----------------------
if (sub == "set") {
if (args.size() < 3) return "Usage: /time set <value|day|night|noon|midnight>";
const std::string& val = args[2];
long t = -1;
if (val == "day") t = 1000;
else if (val == "noon") t = 6000;
else if (val == "night") t = 13000;
else if (val == "midnight") t = 18000;
else {
// numeric — accept positive integers only
bool numeric = true;
for (char c : val)
if (!std::isdigit((unsigned char)c)) { numeric = false; break; }
if (!numeric) return std::string("Unknown value: ") + val;
t = std::atol(val.c_str());
}
// Preserve the total day count so only the time-of-day changes
long dayCount = level->getTime() / Level::TICKS_PER_DAY;
long newTime = dayCount * Level::TICKS_PER_DAY + (t % Level::TICKS_PER_DAY);
level->setTime(newTime);
std::ostringstream out;
out << "Set the time to " << t;
return out.str();
}
// -- time query <daytime|gametime|day> ------------------------------
if (sub == "query") {
if (args.size() < 3) return "Usage: /time query <daytime|gametime|day>";
const std::string& what = args[2];
long total = level->getTime();
long daytime = total % Level::TICKS_PER_DAY;
long day = total / Level::TICKS_PER_DAY;
std::ostringstream out;
if (what == "daytime") { out << "The time of day is " << daytime; }
else if (what == "gametime") { out << "The game time is " << total; }
else if (what == "day") { out << "The day is " << day; }
else return std::string("Unknown query: ") + what;
return out.str();
}
return "Unknown sub-command. Usage: /time <add|set|query> ...";
}
return std::string("Unknown command: /") + args[0];
}
// ---------------------------------------------------------------------------
// render
// ---------------------------------------------------------------------------
void ConsoleScreen::render(int /*xm*/, int /*ym*/, float /*a*/)
{
// Dim the game world slightly
fillGradient(0, 0, width, height, 0x00000000, 0x40000000);
const int boxH = 12;
const int boxY = height - boxH - 2;
const int boxX0 = 2;
const int boxX1 = width - 2;
// Input box background
fill(boxX0, boxY, boxX1, boxY + boxH, 0xc0000000);
// Border
fill(boxX0, boxY, boxX1, boxY + 1, 0xff808080);
fill(boxX0, boxY + boxH - 1, boxX1, boxY + boxH, 0xff808080);
fill(boxX0, boxY, boxX0 + 1, boxY + boxH, 0xff808080);
fill(boxX1 - 1, boxY, boxX1, boxY + boxH, 0xff808080);
// Input text + blinking cursor
std::string displayed = _input;
if ((_cursorBlink / 10) % 2 == 0)
displayed += '_';
// Placeholder hint when empty
if (_input.empty() && (_cursorBlink / 10) % 2 != 0)
font->drawShadow("Type a message or /command", (float)(boxX0 + 2), (float)(boxY + 2), 0xff606060);
else
font->drawShadow(displayed, (float)(boxX0 + 2), (float)(boxY + 2), 0xffffffff);
}

View File

@@ -0,0 +1,34 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ConsoleScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ConsoleScreen_H__
#include "../Screen.h"
#include <string>
class ConsoleScreen: public Screen
{
typedef Screen super;
public:
ConsoleScreen();
virtual ~ConsoleScreen() {}
void init();
void render(int xm, int ym, float a);
void tick();
virtual bool renderGameBehind() { return true; }
virtual bool isInGameScreen() { return true; }
virtual bool isPauseScreen() { return false; }
virtual void keyPressed(int eventKey);
virtual void keyboardNewChar(char inputChar);
virtual bool handleBackEvent(bool isDown);
private:
void execute();
std::string processCommand(const std::string& cmd);
std::string _input;
int _cursorBlink; // tick counter for cursor blink
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ConsoleScreen_H__*/

View File

@@ -0,0 +1,127 @@
#include "CreditsScreen.h"
#include "StartMenuScreen.h"
#include "OptionsScreen.h"
#include "../../Minecraft.h"
#include "../components/Button.h"
#include "../components/ImageButton.h"
#include "platform/input/Mouse.h"
CreditsScreen::CreditsScreen()
: bHeader(NULL), btnBack(NULL)
{}
CreditsScreen::~CreditsScreen() {
if (bHeader) delete bHeader;
if (btnBack) delete btnBack;
}
void CreditsScreen::init() {
bHeader = new Touch::THeader(0, "Credits");
btnBack = new ImageButton(1, "");
{
ImageDef def;
def.name = "gui/touchgui.png";
def.width = 34;
def.height = 26;
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
btnBack->setImageDef(def, true);
}
buttons.push_back(bHeader);
buttons.push_back(btnBack);
// prepare text lines
_lines.clear();
_lines.push_back("Minecraft: Pocket Edition");
_lines.push_back("Original game by Mojang");
_lines.push_back("");
_lines.push_back("Programmers:");
_lines.push_back("mschiller890");
_lines.push_back("InviseDivine");
_lines.push_back("Kolyah35");
_lines.push_back("");
// avoid color tags around the URL so it isn't mangled by the parser please
_lines.push_back("Join our Discord server: https://discord.gg/c58YesBxve");
_scrollSpeed = 0.5f;
_scrollY = height; // start below screen
}
void CreditsScreen::setupPositions() {
int buttonHeight = btnBack->height;
btnBack->x = width - btnBack->width;
btnBack->y = 0;
if (bHeader) {
bHeader->x = 0;
bHeader->y = 0;
bHeader->width = width - btnBack->width;
bHeader->height = btnBack->height;
}
// reset scroll starting position when screen size changes
_scrollY = height;
}
void CreditsScreen::tick() {
// move text upward
_scrollY -= _scrollSpeed;
// if text has scrolled off the top, restart
float totalHeight = _lines.size() * (minecraft->font->lineHeight + 8);
if (_scrollY + totalHeight < 0) {
_scrollY = height;
}
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
_scrollSpeed = 1.5f;
} else {
_scrollSpeed = 0.5f;
}
}
void CreditsScreen::render(int xm, int ym, float a) {
renderBackground();
int w = width;
Font* font = minecraft->font;
float y = _scrollY;
const float lineHeight = font->lineHeight + 8;
for (size_t i = 0; i < _lines.size(); ++i) {
const std::string& line = _lines[i];
// use color-tag-aware drawing, centre by total width
float lineWidth = Gui::getColoredWidth(font, line);
Gui::drawColoredString(font, line, w/2 - lineWidth/2, (int)y, 255);
// underline hyperlink lines manually
if (line.find("http") != std::string::npos || line.find("discord.gg") != std::string::npos) {
float x0 = w/2 - lineWidth/2;
float y0 = y + font->lineHeight - 1;
this->fill(x0, y0, x0 + lineWidth, y0 + 1, 0xffffffff);
}
y += lineHeight;
}
super::render(xm, ym, a);
}
void CreditsScreen::buttonClicked(Button* button) {
if (button->id == 1) {
minecraft->setScreen(new OptionsScreen());
}
}
void CreditsScreen::mouseClicked(int x, int y, int buttonNum) {
// map click to a line in the scrolling text
const float lineHeight = minecraft->font->lineHeight + 8;
for (size_t i = 0; i < _lines.size(); ++i) {
float lineY = _scrollY + i * lineHeight;
if (y >= lineY && y < lineY + lineHeight) {
const std::string& line = _lines[i];
size_t start = line.find("http");
if (start == std::string::npos)
start = line.find("discord.gg");
if (start != std::string::npos) {
// extract until space
size_t end = line.find(' ', start);
std::string url = line.substr(start, (end == std::string::npos) ? std::string::npos : end - start);
minecraft->platform()->openURL(url);
return;
}
}
}
super::mouseClicked(x, y, buttonNum);
}

View File

@@ -0,0 +1,32 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__CreditsScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__CreditsScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
class ImageButton;
#include <vector>
#include <string>
class CreditsScreen: public Screen {
public:
typedef Screen super;
CreditsScreen();
virtual ~CreditsScreen();
void init();
void setupPositions();
virtual void tick();
void render(int xm, int ym, float a);
void buttonClicked(Button* button);
virtual void mouseClicked(int x, int y, int buttonNum);
private:
Touch::THeader* bHeader;
ImageButton* btnBack;
std::vector<std::string> _lines;
float _scrollY;
float _scrollSpeed;
};
#endif /* NET_MINECRAFT_CLIENT_GUI_SCREENS__CreditsScreen_H__ */

View File

@@ -1,107 +0,0 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__InvalidLicenseScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__InvalidLicenseScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
#include "../../../LicenseCodes.h"
class InvalidLicenseScreen: public Screen
{
public:
InvalidLicenseScreen(int id, bool hasBuyButton)
: _id(id),
_hasBuyButton(hasBuyButton),
_baseY(0),
bOk(0),
bBuy(0)
{
}
virtual ~InvalidLicenseScreen() {
delete bOk;
delete bBuy;
}
void init() {
if (minecraft->useTouchscreen()) {
bOk = new Touch::TButton(1, "Ok");
bBuy = new Touch::TButton(2, "Buy");
} else {
bOk = new Button(1, "Ok");
bBuy = new Button(2, "Buy");
}
if (_hasBuyButton)
bOk->msg = "Quit";
if (!LicenseCodes::isOk(_id)) {
char buf[20] = {0};
sprintf(buf, "%d", _id);
desc1 = "License verification failed (error ";
desc1 += buf;
desc1 += ")";
desc2 = "Try again later.";
hint = "You need to be connected to the internet\n";
hint += "once while you start the game.";
}
buttons.push_back(bOk);
tabButtons.push_back(bOk);
if (_hasBuyButton) {
buttons.push_back(bBuy);
tabButtons.push_back(bBuy);
}
}
void setupPositions() {
_baseY = height/5 + 6;
//if (_hasBuyButton)
_baseY -= 24;
bOk->width = bBuy->width = 200;
bOk->x = bBuy->x = (width - bOk->width) / 2;
bBuy->y = _baseY + 84;
bOk->y = bBuy->y + bBuy->height + 4;
if (!_hasBuyButton)
bOk->y -= 24;
}
void tick() {}
//void keyPressed(int eventKey) {}
void render(int xm, int ym, float a) {
renderDirtBackground(0);
drawCenteredString(minecraft->font, desc1, width/2, _baseY, 0xffffff);
drawCenteredString(minecraft->font, desc2, width/2, _baseY + 24, 0xffffff);
drawCenteredString(minecraft->font, hint, width/2, _baseY + 60, 0xffffff);
Screen::render(xm, ym, a);
}
void buttonClicked(Button* button) {
if (button->id == bOk->id) {
minecraft->quit();
}
if (button->id == bBuy->id) {
minecraft->platform()->buyGame();
}
};
private:
int _id;
std::string desc1;
std::string desc2;
std::string hint;
Button* bOk;
Button* bBuy;
bool _hasBuyButton;
int _baseY;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__InvalidLicenseScreen_H__*/

View File

@@ -0,0 +1,140 @@
#include "JoinByIPScreen.h"
#include "JoinGameScreen.h"
#include "StartMenuScreen.h"
#include "ProgressScreen.h"
#include "../Font.h"
#include "../../../network/RakNetInstance.h"
#include "client/gui/components/TextBox.h"
#include "network/ClientSideNetworkHandler.h"
JoinByIPScreen::JoinByIPScreen() :
tIP(0, "Server IP"),
bHeader(1, "Join on server"),
bJoin( 2, "Join Game"),
bBack( 3, "")
{
bJoin.active = false;
//gamesList->yInertia = 0.5f;
}
JoinByIPScreen::~JoinByIPScreen()
{
}
void JoinByIPScreen::buttonClicked(Button* button)
{
if (button->id == bJoin.id)
{
minecraft->isLookingForMultiplayer = true;
minecraft->netCallback = new ClientSideNetworkHandler(minecraft, minecraft->raknetInstance);
minecraft->joinMultiplayerFromString(tIP.text);
{
bJoin.active = false;
bBack.active = false;
minecraft->setScreen(new ProgressScreen());
}
}
if (button->id == bBack.id)
{
minecraft->cancelLocateMultiplayer();
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
}
bool JoinByIPScreen::handleBackEvent(bool isDown)
{
if (!isDown)
{
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
return true;
}
void JoinByIPScreen::tick()
{
bJoin.active = !tIP.text.empty();
}
void JoinByIPScreen::init()
{
ImageDef def;
def.name = "gui/touchgui.png";
def.width = 34;
def.height = 26;
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
bBack.setImageDef(def, true);
buttons.push_back(&bJoin);
buttons.push_back(&bBack);
buttons.push_back(&bHeader);
textBoxes.push_back(&tIP);
#ifdef ANDROID
tabButtons.push_back(&bJoin);
tabButtons.push_back(&bBack);
tabButtons.push_back(&bHeader);
#endif
}
void JoinByIPScreen::setupPositions() {
int tIpDiff = 40;
bJoin.y = height * 2 / 3;
bBack.y = 0;
bHeader.y = 0;
// Center buttons
//bJoin.x = width / 2 - 4 - bJoin.w;
bBack.x = width - bBack.width;//width / 2 + 4;
bJoin.x = (width - bJoin.width) / 2;
bHeader.x = 0;
bHeader.width = width - bBack.width;
tIP.width = bJoin.width + tIpDiff;
tIP.height = 16;
tIP.x = bJoin.x - tIpDiff / 2;
tIP.y = ((height - bJoin.height) / 2) - tIP.height - 4;
}
void JoinByIPScreen::mouseClicked(int x, int y, int buttonNum) {
int lvlTop = tIP.y - (Font::DefaultLineHeight + 4);
int lvlBottom = tIP.y + tIP.height;
int lvlLeft = tIP.x;
int lvlRight = tIP.x + tIP.width;
bool clickedIP = x >= lvlLeft && x < lvlRight && y >= lvlTop && y < lvlBottom;
if (clickedIP) {
tIP.setFocus(minecraft);
} else {
tIP.loseFocus(minecraft);
}
Screen::mouseClicked(x, y, buttonNum);
}
void JoinByIPScreen::render( int xm, int ym, float a )
{
renderBackground();
Screen::render(xm, ym, a);
}
void JoinByIPScreen::keyPressed(int eventKey)
{
if (eventKey == Keyboard::KEY_ESCAPE) {
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
return;
}
// let base class handle navigation and text box keys
Screen::keyPressed(eventKey);
}
void JoinByIPScreen::keyboardNewChar(char inputChar)
{
// forward character input to focused textbox(s)
for (auto* tb : textBoxes) tb->handleChar(inputChar);
}

View File

@@ -0,0 +1,30 @@
#include "../Screen.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
#include "client/gui/components/ImageButton.h"
#include "client/gui/components/TextBox.h"
class JoinByIPScreen: public Screen
{
public:
JoinByIPScreen();
virtual ~JoinByIPScreen();
void init();
void setupPositions();
virtual void tick();
void render(int xm, int ym, float a);
virtual void keyPressed(int eventKey);
virtual void keyboardNewChar(char inputChar);
void buttonClicked(Button* button);
virtual void mouseClicked(int x, int y, int buttonNum);
virtual bool handleBackEvent(bool isDown);
private:
TextBox tIP;
Touch::THeader bHeader;
Touch::TButton bJoin;
ImageButton bBack;
};

View File

@@ -1,46 +1,69 @@
#include "OptionsScreen.h" #include "OptionsScreen.h"
#include "StartMenuScreen.h" #include "StartMenuScreen.h"
#include "UsernameScreen.h"
#include "DialogDefinitions.h" #include "DialogDefinitions.h"
#include "../../Minecraft.h" #include "../../Minecraft.h"
#include "../../../AppPlatform.h" #include "../../../AppPlatform.h"
#include "CreditsScreen.h"
#include "../components/OptionsPane.h" #include "../components/OptionsPane.h"
#include "../components/ImageButton.h" #include "../components/ImageButton.h"
#include "../components/OptionsGroup.h" #include "../components/OptionsGroup.h"
OptionsScreen::OptionsScreen() OptionsScreen::OptionsScreen()
: btnClose(NULL), : btnClose(NULL),
bHeader(NULL), bHeader(NULL),
btnChangeUsername(NULL),
btnCredits(NULL),
selectedCategory(0) { selectedCategory(0) {
} }
OptionsScreen::~OptionsScreen() { OptionsScreen::~OptionsScreen() {
if(btnClose != NULL) {
if (btnClose != NULL) {
delete btnClose; delete btnClose;
btnClose = NULL; btnClose = NULL;
} }
if(bHeader != NULL) {
delete bHeader, if (bHeader != NULL) {
delete bHeader;
bHeader = NULL; bHeader = NULL;
} }
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
if(*it != NULL) { if (btnChangeUsername != NULL) {
delete *it; delete btnChangeUsername;
btnChangeUsername = NULL;
}
if (btnCredits != NULL) {
delete btnCredits;
btnCredits = NULL;
}
for (std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
if (*it != NULL) {
delete* it;
*it = NULL; *it = NULL;
} }
} }
for(std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
if(*it != NULL) { for (std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
delete *it; if (*it != NULL) {
delete* it;
*it = NULL; *it = NULL;
} }
} }
categoryButtons.clear(); categoryButtons.clear();
} }
void OptionsScreen::init() { void OptionsScreen::init() {
bHeader = new Touch::THeader(0, "Options"); bHeader = new Touch::THeader(0, "Options");
btnClose = new ImageButton(1, ""); btnClose = new ImageButton(1, "");
ImageDef def; ImageDef def;
def.name = "gui/touchgui.png"; def.name = "gui/touchgui.png";
def.width = 34; def.width = 34;
@@ -53,129 +76,199 @@ void OptionsScreen::init() {
categoryButtons.push_back(new Touch::TButton(3, "Game")); categoryButtons.push_back(new Touch::TButton(3, "Game"));
categoryButtons.push_back(new Touch::TButton(4, "Controls")); categoryButtons.push_back(new Touch::TButton(4, "Controls"));
categoryButtons.push_back(new Touch::TButton(5, "Graphics")); categoryButtons.push_back(new Touch::TButton(5, "Graphics"));
btnChangeUsername = new Touch::TButton(10, "Username");
btnCredits = new Touch::TButton(11, "Credits");
buttons.push_back(bHeader); buttons.push_back(bHeader);
buttons.push_back(btnClose); buttons.push_back(btnClose);
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) { buttons.push_back(btnChangeUsername);
buttons.push_back(btnCredits);
for (std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
buttons.push_back(*it); buttons.push_back(*it);
tabButtons.push_back(*it); tabButtons.push_back(*it);
} }
generateOptionScreens();
generateOptionScreens();
// start with first category selected
selectCategory(0);
} }
void OptionsScreen::setupPositions() { void OptionsScreen::setupPositions() {
int buttonHeight = btnClose->height; int buttonHeight = btnClose->height;
btnClose->x = width - btnClose->width; btnClose->x = width - btnClose->width;
btnClose->y = 0; btnClose->y = 0;
int offsetNum = 1; int offsetNum = 1;
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
for (std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
(*it)->x = 0; (*it)->x = 0;
(*it)->y = offsetNum * buttonHeight; (*it)->y = offsetNum * buttonHeight;
(*it)->selected = false; (*it)->selected = false;
offsetNum++; offsetNum++;
} }
bHeader->x = 0; bHeader->x = 0;
bHeader->y = 0; bHeader->y = 0;
bHeader->width = width - btnClose->width; bHeader->width = width - btnClose->width;
bHeader->height = btnClose->height; bHeader->height = btnClose->height;
for(std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
if(categoryButtons.size() > 0 && categoryButtons[0] != NULL) { // Username button (bottom-left)
if (btnChangeUsername != NULL) {
btnChangeUsername->width = categoryButtons.empty() ? 80 : categoryButtons[0]->width;
btnChangeUsername->height = btnClose->height;
btnChangeUsername->x = 0;
btnChangeUsername->y = height - btnChangeUsername->height;
}
// Credits button (bottom-right)
if (btnCredits != NULL) {
btnCredits->width = btnChangeUsername->width;
btnCredits->height = btnChangeUsername->height;
btnCredits->x = width - btnCredits->width;
btnCredits->y = height - btnCredits->height;
}
for (std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
if (categoryButtons.size() > 0 && categoryButtons[0] != NULL) {
(*it)->x = categoryButtons[0]->width; (*it)->x = categoryButtons[0]->width;
(*it)->y = bHeader->height; (*it)->y = bHeader->height;
(*it)->width = width - categoryButtons[0]->width; (*it)->width = width - categoryButtons[0]->width;
(*it)->setupPositions(); (*it)->setupPositions();
} }
} }
selectCategory(0);
// don't override user selection on resize
} }
void OptionsScreen::render( int xm, int ym, float a ) {
void OptionsScreen::render(int xm, int ym, float a) {
renderBackground(); renderBackground();
super::render(xm, ym, a); super::render(xm, ym, a);
int xmm = xm * width / minecraft->width; int xmm = xm * width / minecraft->width;
int ymm = ym * height / minecraft->height - 1; int ymm = ym * height / minecraft->height - 1;
if(currentOptionPane != NULL)
if (currentOptionPane != NULL)
currentOptionPane->render(minecraft, xmm, ymm); currentOptionPane->render(minecraft, xmm, ymm);
} }
void OptionsScreen::removed() void OptionsScreen::removed() {
{
} }
void OptionsScreen::buttonClicked( Button* button ) {
if(button == btnClose) { void OptionsScreen::buttonClicked(Button* button) {
minecraft->reloadOptions();
if (button == btnClose) {
minecraft->options.save();
minecraft->screenChooser.setScreen(SCREEN_STARTMENU); minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
} else if(button->id > 1 && button->id < 7) {
// This is a category button }
else if (button == btnChangeUsername) {
minecraft->options.save();
minecraft->setScreen(new UsernameScreen());
}
else if (button->id > 1 && button->id < 7) {
int categoryButton = button->id - categoryButtons[0]->id; int categoryButton = button->id - categoryButtons[0]->id;
selectCategory(categoryButton); selectCategory(categoryButton);
}
else if (button == btnCredits) {
minecraft->setScreen(new CreditsScreen());
} }
} }
void OptionsScreen::selectCategory( int index ) { void OptionsScreen::selectCategory(int index) {
int currentIndex = 0; int currentIndex = 0;
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
if(index == currentIndex) { for (std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
if (index == currentIndex)
(*it)->selected = true; (*it)->selected = true;
} else { else
(*it)->selected = false; (*it)->selected = false;
}
currentIndex++; currentIndex++;
} }
if(index < (int)optionPanes.size())
if (index < (int)optionPanes.size())
currentOptionPane = optionPanes[index]; currentOptionPane = optionPanes[index];
} }
void OptionsScreen::generateOptionScreens() { void OptionsScreen::generateOptionScreens() {
optionPanes.push_back(new OptionsPane()); optionPanes.push_back(new OptionsPane());
optionPanes.push_back(new OptionsPane()); optionPanes.push_back(new OptionsPane());
optionPanes.push_back(new OptionsPane()); optionPanes.push_back(new OptionsPane());
optionPanes.push_back(new OptionsPane()); optionPanes.push_back(new OptionsPane());
// Mojang Pane
// Login Pane
optionPanes[0]->createOptionsGroup("options.group.mojang") optionPanes[0]->createOptionsGroup("options.group.mojang")
//.addOptionItem(&Options::Option::THIRD_PERSON, minecraft);
.addOptionItem(&Options::Option::SENSITIVITY, minecraft); .addOptionItem(&Options::Option::SENSITIVITY, minecraft);
// int mojangGroup = optionPanes[0]->createOptionsGroup("Mojang");
// static const int arr[] = {5,4,3,15}; // Game Pane
// std::vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) ); optionPanes[1]->createOptionsGroup("options.group.game")
// optionPanes[0]->createStepSlider(minecraft, mojangGroup, "This works?", &Options::Option::DIFFICULTY, vec); .addOptionItem(&Options::Option::DIFFICULTY, minecraft)
// .addOptionItem(&Options::Option::SERVER_VISIBLE, minecraft)
// // Game Pane .addOptionItem(&Options::Option::THIRD_PERSON, minecraft)
// int gameGroup = optionPanes[1]->createOptionsGroup("Game"); .addOptionItem(&Options::Option::GUI_SCALE, minecraft);
// optionPanes[1]->createToggle(gameGroup, "Third person camera", &Options::Option::THIRD_PERSON);
// optionPanes[1]->createToggle(gameGroup, "Server visible", &Options::Option::SERVER_VISIBLE); // Controls Pane
// optionPanes[2]->createOptionsGroup("options.group.controls")
// // Input Pane .addOptionItem(&Options::Option::INVERT_MOUSE, minecraft);
// int controlsGroup = optionPanes[2]->createOptionsGroup("Controls");
// optionPanes[2]->createToggle(controlsGroup, "Invert X-axis", &Options::Option::INVERT_MOUSE); // Graphics Pane
// optionPanes[2]->createToggle(controlsGroup, "Lefty", &Options::Option::LEFT_HANDED); optionPanes[3]->createOptionsGroup("options.group.graphics")
// optionPanes[2]->createToggle(controlsGroup, "Use touch screen", &Options::Option::USE_TOUCHSCREEN); .addOptionItem(&Options::Option::GRAPHICS, minecraft)
// optionPanes[2]->createToggle(controlsGroup, "Split touch controls", &Options::Option::USE_TOUCH_JOYPAD); .addOptionItem(&Options::Option::VIEW_BOBBING, minecraft)
// int feedBackGroup = optionPanes[2]->createOptionsGroup("Feedback"); .addOptionItem(&Options::Option::AMBIENT_OCCLUSION, minecraft)
// optionPanes[2]->createToggle(feedBackGroup, "Vibrate on destroy", &Options::Option::DESTROY_VIBRATION); .addOptionItem(&Options::Option::ANAGLYPH, minecraft)
// .addOptionItem(&Options::Option::LIMIT_FRAMERATE, minecraft)
// int graphicsGroup = optionPanes[3]->createOptionsGroup("Graphics"); .addOptionItem(&Options::Option::VSYNC, minecraft)
// optionPanes[3]->createProgressSlider(minecraft, graphicsGroup, "Gui Scale", &Options::Option::PIXELS_PER_MILLIMETER, 3, 4); .addOptionItem(&Options::Option::MUSIC, minecraft)
// optionPanes[3]->createToggle(graphicsGroup, "Fancy Graphics", &Options::Option::INVERT_MOUSE); .addOptionItem(&Options::Option::SOUND, minecraft);
// optionPanes[3]->createToggle(graphicsGroup, "Fancy Skies", &Options::Option::INVERT_MOUSE);
// optionPanes[3]->createToggle(graphicsGroup, "Animated water", &Options::Option::INVERT_MOUSE);
// int experimentalGraphicsGroup = optionPanes[3]->createOptionsGroup("Experimental graphics");
// optionPanes[3]->createToggle(experimentalGraphicsGroup, "Soft shadows", &Options::Option::INVERT_MOUSE);
} }
void OptionsScreen::mouseClicked( int x, int y, int buttonNum ) { void OptionsScreen::mouseClicked(int x, int y, int buttonNum) {
if(currentOptionPane != NULL)
if (currentOptionPane != NULL)
currentOptionPane->mouseClicked(minecraft, x, y, buttonNum); currentOptionPane->mouseClicked(minecraft, x, y, buttonNum);
super::mouseClicked(x, y, buttonNum); super::mouseClicked(x, y, buttonNum);
} }
void OptionsScreen::mouseReleased( int x, int y, int buttonNum ) { void OptionsScreen::mouseReleased(int x, int y, int buttonNum) {
if(currentOptionPane != NULL)
if (currentOptionPane != NULL)
currentOptionPane->mouseReleased(minecraft, x, y, buttonNum); currentOptionPane->mouseReleased(minecraft, x, y, buttonNum);
super::mouseReleased(x, y, buttonNum); super::mouseReleased(x, y, buttonNum);
} }
void OptionsScreen::tick() { void OptionsScreen::tick() {
if(currentOptionPane != NULL)
if (currentOptionPane != NULL)
currentOptionPane->tick(minecraft); currentOptionPane->tick(minecraft);
super::tick(); super::tick();
} }

View File

@@ -10,28 +10,36 @@ class OptionsPane;
class OptionsScreen: public Screen class OptionsScreen: public Screen
{ {
typedef Screen super; typedef Screen super;
void init();
void init();
void generateOptionScreens(); void generateOptionScreens();
public: public:
OptionsScreen(); OptionsScreen();
~OptionsScreen(); ~OptionsScreen();
void setupPositions(); void setupPositions();
void buttonClicked( Button* button ); void buttonClicked(Button* button);
void render(int xm, int ym, float a); void render(int xm, int ym, float a);
void removed(); void removed();
void selectCategory(int index); void selectCategory(int index);
virtual void mouseClicked( int x, int y, int buttonNum ); virtual void mouseClicked(int x, int y, int buttonNum);
virtual void mouseReleased( int x, int y, int buttonNum ); virtual void mouseReleased(int x, int y, int buttonNum);
virtual void tick(); virtual void tick();
private: private:
Touch::THeader* bHeader; Touch::THeader* bHeader;
ImageButton* btnClose; ImageButton* btnClose;
Button* btnChangeUsername;
Button* btnCredits; // <-- ADD THIS
std::vector<Touch::TButton*> categoryButtons; std::vector<Touch::TButton*> categoryButtons;
std::vector<OptionsPane*> optionPanes; std::vector<OptionsPane*> optionPanes;
OptionsPane* currentOptionPane; OptionsPane* currentOptionPane;
int selectedCategory; int selectedCategory;
}; };

View File

@@ -5,6 +5,7 @@
#include "PauseScreen.h" #include "PauseScreen.h"
#include "RenameMPLevelScreen.h" #include "RenameMPLevelScreen.h"
#include "IngameBlockSelectionScreen.h" #include "IngameBlockSelectionScreen.h"
#include "JoinByIPScreen.h"
#include "touch/TouchStartMenuScreen.h" #include "touch/TouchStartMenuScreen.h"
#include "touch/TouchSelectWorldScreen.h" #include "touch/TouchSelectWorldScreen.h"
#include "touch/TouchJoinGameScreen.h" #include "touch/TouchJoinGameScreen.h"
@@ -19,12 +20,12 @@ Screen* ScreenChooser::createScreen( ScreenId id )
if (_mc->useTouchscreen()) { if (_mc->useTouchscreen()) {
switch (id) { switch (id) {
case SCREEN_STARTMENU: screen = new Touch::StartMenuScreen(); break; case SCREEN_STARTMENU: screen = new Touch::StartMenuScreen(); break;
case SCREEN_SELECTWORLD:screen = new Touch::SelectWorldScreen();break; case SCREEN_SELECTWORLD: screen = new Touch::SelectWorldScreen();break;
case SCREEN_JOINGAME: screen = new Touch::JoinGameScreen(); break; case SCREEN_JOINGAME: screen = new Touch::JoinGameScreen(); break;
case SCREEN_PAUSE: screen = new PauseScreen(false); break; case SCREEN_PAUSE: screen = new PauseScreen(false); break;
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break; case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
case SCREEN_BLOCKSELECTION: screen = new Touch::IngameBlockSelectionScreen(); break; case SCREEN_BLOCKSELECTION: screen = new Touch::IngameBlockSelectionScreen(); break;
case SCREEN_JOINBYIP: screen = new JoinByIPScreen(); break;
case SCREEN_NONE: case SCREEN_NONE:
default: default:
// Do nothing // Do nothing
@@ -33,11 +34,12 @@ Screen* ScreenChooser::createScreen( ScreenId id )
} else { } else {
switch (id) { switch (id) {
case SCREEN_STARTMENU: screen = new StartMenuScreen(); break; case SCREEN_STARTMENU: screen = new StartMenuScreen(); break;
case SCREEN_SELECTWORLD:screen = new SelectWorldScreen();break; case SCREEN_SELECTWORLD: screen = new SelectWorldScreen();break;
case SCREEN_JOINGAME: screen = new JoinGameScreen(); break; case SCREEN_JOINGAME: screen = new JoinGameScreen(); break;
case SCREEN_PAUSE: screen = new PauseScreen(false); break; case SCREEN_PAUSE: screen = new PauseScreen(false); break;
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break; case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
case SCREEN_BLOCKSELECTION: screen = new IngameBlockSelectionScreen(); break; case SCREEN_BLOCKSELECTION: screen = new IngameBlockSelectionScreen(); break;
case SCREEN_JOINBYIP: screen = new JoinByIPScreen(); break;
case SCREEN_NONE: case SCREEN_NONE:
default: default:

View File

@@ -8,7 +8,8 @@ enum ScreenId {
SCREEN_PAUSE, SCREEN_PAUSE,
SCREEN_PAUSEPREV, SCREEN_PAUSEPREV,
SCREEN_SELECTWORLD, SCREEN_SELECTWORLD,
SCREEN_BLOCKSELECTION SCREEN_BLOCKSELECTION,
SCREEN_JOINBYIP
}; };
class Screen; class Screen;

View File

@@ -230,7 +230,6 @@ SelectWorldScreen::SelectWorldScreen()
bBack (3, "Back"), bBack (3, "Back"),
bWorldView(4, ""), bWorldView(4, ""),
worldsList(NULL), worldsList(NULL),
_state(_STATE_DEFAULT),
_hasStartedLevel(false) _hasStartedLevel(false)
{ {
bDelete.active = false; bDelete.active = false;
@@ -244,16 +243,10 @@ SelectWorldScreen::~SelectWorldScreen()
void SelectWorldScreen::buttonClicked(Button* button) void SelectWorldScreen::buttonClicked(Button* button)
{ {
if (button->id == bCreate.id) { if (button->id == bCreate.id) {
//minecraft->setScreen( new CreateWorldScreen() ); // open in-game world-creation screen instead of using platform dialog
//minecraft->locateMultiplayer(); if (!_hasStartedLevel) {
//minecraft->setScreen(new JoinGameScreen()); std::string name = getUniqueLevelName("world");
minecraft->setScreen(new SimpleChooseLevelScreen(name));
//minecraft->hostMultiplayer();
//minecraft->setScreen(new ProgressScreen());
if (_state == _STATE_DEFAULT && !_hasStartedLevel) {
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_CREATE_NEW_WORLD);
_state = _STATE_CREATEWORLD;
} }
} }
if (button->id == bDelete.id) { if (button->id == bDelete.id) {
@@ -294,70 +287,6 @@ static char ILLEGAL_FILE_CHARACTERS[] = {
void SelectWorldScreen::tick() void SelectWorldScreen::tick()
{ {
if (_state == _STATE_CREATEWORLD) {
#if defined(RPI)
std::string levelId = getUniqueLevelName("world");
LevelSettings settings(getEpochTimeS(), GameType::Creative);
minecraft->selectLevel(levelId, levelId, settings);
minecraft->hostMultiplayer();
minecraft->setScreen(new ProgressScreen());
_hasStartedLevel = true;
#elif defined(WIN32)
std::string name = getUniqueLevelName("perf");
minecraft->setScreen(new SimpleChooseLevelScreen(name));
#else
int status = minecraft->platform()->getUserInputStatus();
if (status > -1) {
if (status == 1) {
StringVector sv = minecraft->platform()->getUserInput();
// Read the level name.
// 1) Trim name 2) Remove all bad chars 3) Append '-' chars 'til the name is unique
std::string levelName = Util::stringTrim(sv[0]);
std::string levelId = levelName;
for (int i = 0; i < sizeof(ILLEGAL_FILE_CHARACTERS) / sizeof(char); ++i)
levelId = Util::stringReplace(levelId, std::string(1, ILLEGAL_FILE_CHARACTERS[i]), "");
if ((int)levelId.length() == 0) {
levelId = "no_name";
}
levelId = getUniqueLevelName(levelId);
// Read the seed
int seed = getEpochTimeS();
if (sv.size() >= 2) {
std::string seedString = Util::stringTrim(sv[1]);
if (seedString.length() > 0) {
int tmpSeed;
// Try to read it as an integer
if (sscanf(seedString.c_str(), "%d", &tmpSeed) > 0) {
seed = tmpSeed;
} // Hash the "seed"
else {
seed = Util::hashCode(seedString);
}
}
}
// Read the game mode
bool isCreative = true;
if (sv.size() >= 3 && sv[2] == "survival")
isCreative = false;
// Start a new level with the given name and seed
LevelSettings settings(seed, isCreative? GameType::Creative : GameType::Survival);
LOGI("Creating a level with id '%s', name '%s' and seed '%d'\n", levelId.c_str(), levelName.c_str(), seed);
minecraft->selectLevel(levelId, levelName, settings);
minecraft->hostMultiplayer();
minecraft->setScreen(new ProgressScreen());
_hasStartedLevel = true;
}
_state = _STATE_DEFAULT;
}
#endif
return;
}
worldsList->tick(); worldsList->tick();
if (worldsList->hasPickedLevel) { if (worldsList->hasPickedLevel) {

View File

@@ -104,9 +104,6 @@ private:
bool _mouseHasBeenUp; bool _mouseHasBeenUp;
bool _hasStartedLevel; bool _hasStartedLevel;
int _state;
static const int _STATE_DEFAULT = 0;
static const int _STATE_CREATEWORLD = 1;
//LevelStorageSource* levels; //LevelStorageSource* levels;
}; };

View File

@@ -2,55 +2,121 @@
#include "ProgressScreen.h" #include "ProgressScreen.h"
#include "ScreenChooser.h" #include "ScreenChooser.h"
#include "../components/Button.h" #include "../components/Button.h"
#include "../components/ImageButton.h"
#include "../../Minecraft.h" #include "../../Minecraft.h"
#include "../../../world/level/LevelSettings.h" #include "../../../world/level/LevelSettings.h"
#include "../../../platform/time.h" #include "../../../platform/time.h"
#include "../../../platform/input/Keyboard.h"
#include "../../../platform/log.h"
SimpleChooseLevelScreen::SimpleChooseLevelScreen(const std::string& levelName) SimpleChooseLevelScreen::SimpleChooseLevelScreen(const std::string& levelName)
: bCreative(0), : bHeader(0),
bSurvival(0), bGamemode(0),
bBack(0), bBack(0),
bCreate(0),
levelName(levelName), levelName(levelName),
hasChosen(false) hasChosen(false),
gamemode(GameType::Survival),
tLevelName(0, "World name"),
tSeed(1, "World seed")
{ {
} }
SimpleChooseLevelScreen::~SimpleChooseLevelScreen() SimpleChooseLevelScreen::~SimpleChooseLevelScreen()
{ {
delete bCreative; if (bHeader) delete bHeader;
delete bSurvival; delete bGamemode;
delete bBack; delete bBack;
delete bCreate;
} }
void SimpleChooseLevelScreen::init() void SimpleChooseLevelScreen::init()
{ {
if (minecraft->useTouchscreen()) { tLevelName.text = "New world";
bCreative = new Touch::TButton(1, "Creative mode");
bSurvival = new Touch::TButton(2, "Survival mode");
bBack = new Touch::TButton(3, "Back");
} else {
bCreative = new Button(1, "Creative mode");
bSurvival = new Button(2, "Survival mode");
bBack = new Button(3, "Back");
}
buttons.push_back(bCreative);
buttons.push_back(bSurvival);
buttons.push_back(bBack);
tabButtons.push_back(bCreative); // header + close button
tabButtons.push_back(bSurvival); bHeader = new Touch::THeader(0, "Create World");
// create the back/X button as ImageButton like CreditsScreen
bBack = new ImageButton(2, "");
{
ImageDef def;
def.name = "gui/touchgui.png";
def.width = 34;
def.height = 26;
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
bBack->setImageDef(def, true);
}
if (minecraft->useTouchscreen()) {
bGamemode = new Touch::TButton(1, "Survival mode");
bCreate = new Touch::TButton(3, "Create");
} else {
bGamemode = new Button(1, "Survival mode");
bCreate = new Button(3, "Create");
}
buttons.push_back(bHeader);
buttons.push_back(bBack);
buttons.push_back(bGamemode);
buttons.push_back(bCreate);
tabButtons.push_back(bGamemode);
tabButtons.push_back(bBack); tabButtons.push_back(bBack);
tabButtons.push_back(bCreate);
textBoxes.push_back(&tLevelName);
textBoxes.push_back(&tSeed);
} }
void SimpleChooseLevelScreen::setupPositions() void SimpleChooseLevelScreen::setupPositions()
{ {
bCreative->width = bSurvival->width = bBack->width = 120; int buttonHeight = bBack->height;
bCreative->x = (width - bCreative->width) / 2;
bCreative->y = height/3 - 40; // position back button in upper-right
bSurvival->x = (width - bSurvival->width) / 2; bBack->x = width - bBack->width;
bSurvival->y = 2*height/3 - 40; bBack->y = 0;
bBack->x = bSurvival->x + bSurvival->width - bBack->width;
bBack->y = height - 40; // header occupies remaining top bar
if (bHeader) {
bHeader->x = 0;
bHeader->y = 0;
bHeader->width = width - bBack->width;
bHeader->height = buttonHeight;
}
// layout the form elements below the header
int centerX = width / 2;
const int padding = 5;
tLevelName.width = tSeed.width = 200;
tLevelName.x = centerX - tLevelName.width / 2;
tLevelName.y = buttonHeight + 20;
tSeed.x = tLevelName.x;
tSeed.y = tLevelName.y + 30;
bGamemode->width = 140;
bGamemode->x = centerX - bGamemode->width / 2;
// compute vertical centre for gamemode in remaining space
{
int bottomPad = 20;
int availTop = buttonHeight + 20 + 30 + 10; // just below seed
int availBottom = height - bottomPad - bCreate->height - 10; // leave some gap before create
int availHeight = availBottom - availTop;
if (availHeight < 0) availHeight = 0;
bGamemode->y = availTop + (availHeight - bGamemode->height) / 2;
}
bCreate->width = 100;
bCreate->x = centerX - bCreate->width / 2;
int bottomPadding = 20;
bCreate->y = height - bottomPadding - bCreate->height;
}
void SimpleChooseLevelScreen::tick()
{
// let any textboxes handle their own blinking/input
for (auto* tb : textBoxes)
tb->tick(minecraft);
} }
void SimpleChooseLevelScreen::render( int xm, int ym, float a ) void SimpleChooseLevelScreen::render( int xm, int ym, float a )
@@ -58,36 +124,109 @@ void SimpleChooseLevelScreen::render( int xm, int ym, float a )
renderDirtBackground(0); renderDirtBackground(0);
glEnable2(GL_BLEND); glEnable2(GL_BLEND);
drawCenteredString(minecraft->font, "Mobs, health and gather resources", width/2, bSurvival->y + bSurvival->height + 4, 0xffcccccc); const char* str = NULL;
drawCenteredString(minecraft->font, "Unlimited resources and flying", width/2, bCreative->y + bCreative->height + 4, 0xffcccccc); if (gamemode == GameType::Survival) {
str = "Mobs, health and gather resources";
} else if (gamemode == GameType::Creative) {
str = "Unlimited resources and flying";
}
if (str) {
drawCenteredString(minecraft->font, str, width/2, bGamemode->y + bGamemode->height + 4, 0xffcccccc);
}
drawString(minecraft->font, "World name:", tLevelName.x, tLevelName.y - Font::DefaultLineHeight - 2, 0xffcccccc);
drawString(minecraft->font, "World seed:", tSeed.x, tSeed.y - Font::DefaultLineHeight - 2, 0xffcccccc);
Screen::render(xm, ym, a); Screen::render(xm, ym, a);
glDisable2(GL_BLEND); glDisable2(GL_BLEND);
} }
// mouse clicks should also manage textbox focus explicitly
void SimpleChooseLevelScreen::mouseClicked(int x, int y, int buttonNum)
{
if (buttonNum == MouseAction::ACTION_LEFT) {
// determine if the click landed on either textbox or its label above
int lvlTop = tLevelName.y - (Font::DefaultLineHeight + 4);
int lvlBottom = tLevelName.y + tLevelName.height;
int lvlLeft = tLevelName.x;
int lvlRight = tLevelName.x + tLevelName.width;
bool clickedLevel = x >= lvlLeft && x < lvlRight && y >= lvlTop && y < lvlBottom;
int seedTop = tSeed.y - (Font::DefaultLineHeight + 4);
int seedBottom = tSeed.y + tSeed.height;
int seedLeft = tSeed.x;
int seedRight = tSeed.x + tSeed.width;
bool clickedSeed = x >= seedLeft && x < seedRight && y >= seedTop && y < seedBottom;
if (clickedLevel) {
LOGI("SimpleChooseLevelScreen: level textbox clicked (%d,%d)\n", x, y);
tLevelName.setFocus(minecraft);
tSeed.loseFocus(minecraft);
} else if (clickedSeed) {
LOGI("SimpleChooseLevelScreen: seed textbox clicked (%d,%d)\n", x, y);
tSeed.setFocus(minecraft);
tLevelName.loseFocus(minecraft);
} else {
// click outside both fields -> blur both
tLevelName.loseFocus(minecraft);
tSeed.loseFocus(minecraft);
}
}
// allow normal button and textbox handling too
Screen::mouseClicked(x, y, buttonNum);
}
void SimpleChooseLevelScreen::buttonClicked( Button* button ) void SimpleChooseLevelScreen::buttonClicked( Button* button )
{ {
if (button == bBack) {
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
return;
}
if (hasChosen) if (hasChosen)
return; return;
int gameType; if (button == bGamemode) {
gamemode ^= 1;
bGamemode->msg = (gamemode == GameType::Survival) ? "Survival mode" : "Creative mode";
return;
}
if (button == bCreative) if (button == bCreate && !tLevelName.text.empty()) {
gameType = GameType::Creative; int seed = getEpochTimeS();
if (!tSeed.text.empty()) {
if (button == bSurvival) std::string seedString = Util::stringTrim(tSeed.text);
gameType = GameType::Survival; int tmpSeed;
if (sscanf(seedString.c_str(), "%d", &tmpSeed) > 0) {
std::string levelId = getUniqueLevelName(levelName); seed = tmpSeed;
LevelSettings settings(getEpochTimeS(), gameType); } else {
seed = Util::hashCode(seedString);
}
}
std::string levelId = getUniqueLevelName(tLevelName.text);
LevelSettings settings(seed, gamemode);
minecraft->selectLevel(levelId, levelId, settings); minecraft->selectLevel(levelId, levelId, settings);
minecraft->hostMultiplayer(); minecraft->hostMultiplayer();
minecraft->setScreen(new ProgressScreen()); minecraft->setScreen(new ProgressScreen());
hasChosen = true; hasChosen = true;
return;
}
if (button == bBack) {
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
}
void SimpleChooseLevelScreen::keyPressed(int eventKey)
{
if (eventKey == Keyboard::KEY_ESCAPE) {
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
return;
}
// let base class handle navigation and text box keys
Screen::keyPressed(eventKey);
}
void SimpleChooseLevelScreen::keyboardNewChar(char inputChar)
{
// forward character input to focused textbox(s)
for (auto* tb : textBoxes) tb->handleChar(inputChar);
} }
bool SimpleChooseLevelScreen::handleBackEvent(bool isDown) { bool SimpleChooseLevelScreen::handleBackEvent(bool isDown) {

View File

@@ -2,7 +2,10 @@
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__ #define NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__
#include "ChooseLevelScreen.h" #include "ChooseLevelScreen.h"
#include "../components/TextBox.h"
#include "../components/Button.h" // for Touch::THeader
class Button; class Button;
class ImageButton;
class SimpleChooseLevelScreen: public ChooseLevelScreen class SimpleChooseLevelScreen: public ChooseLevelScreen
{ {
@@ -12,21 +15,29 @@ public:
virtual ~SimpleChooseLevelScreen(); virtual ~SimpleChooseLevelScreen();
void init(); void init();
void setupPositions(); void setupPositions();
void tick();
void render(int xm, int ym, float a); void render(int xm, int ym, float a);
void buttonClicked(Button* button); void buttonClicked(Button* button);
bool handleBackEvent(bool isDown); bool handleBackEvent(bool isDown);
virtual void keyPressed(int eventKey);
virtual void keyboardNewChar(char inputChar);
virtual void mouseClicked(int x, int y, int buttonNum);
private: private:
Button* bCreative; Touch::THeader* bHeader;
Button* bSurvival; Button* bGamemode;
Button* bBack; ImageButton* bBack;
Button* bCreate;
bool hasChosen; bool hasChosen;
std::string levelName; std::string levelName;
int gamemode;
TextBox tLevelName;
TextBox tSeed;
}; };
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__*/ #endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__*/

View File

@@ -1,12 +1,11 @@
#include "StartMenuScreen.h" #include "StartMenuScreen.h"
#include "UsernameScreen.h"
#include "SelectWorldScreen.h" #include "SelectWorldScreen.h"
#include "ProgressScreen.h" #include "ProgressScreen.h"
#include "JoinGameScreen.h" #include "JoinGameScreen.h"
#include "OptionsScreen.h" #include "OptionsScreen.h"
#include "PauseScreen.h" #include "PauseScreen.h"
#include "InvalidLicenseScreen.h"
#include "PrerenderTilesScreen.h" // test button #include "PrerenderTilesScreen.h" // test button
//#include "BuyGameScreen.h"
#include "../../../util/Mth.h" #include "../../../util/Mth.h"
@@ -26,9 +25,7 @@
StartMenuScreen::StartMenuScreen() StartMenuScreen::StartMenuScreen()
: bHost( 2, 0, 0, 160, 24, "Start Game"), : bHost( 2, 0, 0, 160, 24, "Start Game"),
bJoin( 3, 0, 0, 160, 24, "Join Game"), bJoin( 3, 0, 0, 160, 24, "Join Game"),
bOptions( 4, 0, 0, 78, 22, "Options"), bOptions( 4, 0, 0, 78, 22, "Options")
bBuy( 5, 0, 0, 78, 22, "Buy"),
bTest( 999, 0, 0, 78, 22, "Create")
{ {
} }
@@ -38,6 +35,13 @@ StartMenuScreen::~StartMenuScreen()
void StartMenuScreen::init() void StartMenuScreen::init()
{ {
bJoin.active = bHost.active = bOptions.active = true;
if (minecraft->options.username.empty()) {
return; // tick() will redirect to UsernameScreen
}
buttons.push_back(&bHost); buttons.push_back(&bHost);
buttons.push_back(&bJoin); buttons.push_back(&bJoin);
//buttons.push_back(&bTest); //buttons.push_back(&bTest);
@@ -57,11 +61,8 @@ void StartMenuScreen::init()
copyright = "\xffMojang AB";//. Do not distribute!"; copyright = "\xffMojang AB";//. Do not distribute!";
#ifdef PRE_ANDROID23 // always show base version string, suffix was previously added for Android builds
std::string versionString = Common::getGameVersionString("j");
#else
std::string versionString = Common::getGameVersionString(); std::string versionString = Common::getGameVersionString();
#endif
#ifdef DEMO_MODE #ifdef DEMO_MODE
#ifdef __APPLE__ #ifdef __APPLE__
@@ -92,21 +93,22 @@ void StartMenuScreen::setupPositions() {
#endif #endif
bOptions.y = yBase + 28 + 2; bOptions.y = yBase + 28 + 2;
bTest.y = bBuy.y = bOptions.y;
//#endif //#endif
// Center buttons // Center buttons
bHost.x = (width - bHost.width) / 2; bHost.x = (width - bHost.width) / 2;
bJoin.x = (width - bJoin.width) / 2; bJoin.x = (width - bJoin.width) / 2;
bOptions.x = (width - bJoin.width) / 2; bOptions.x = (width - bJoin.width) / 2;
bTest.x = bBuy.x = bOptions.x + bOptions.width + 4;
copyrightPosX = width - minecraft->font->width(copyright) - 1; copyrightPosX = width - minecraft->font->width(copyright) - 1;
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2; versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
} }
void StartMenuScreen::tick() { void StartMenuScreen::tick() {
_updateLicense(); if (minecraft->options.username.empty()) {
minecraft->setScreen(new UsernameScreen());
return;
}
} }
void StartMenuScreen::buttonClicked(Button* button) { void StartMenuScreen::buttonClicked(Button* button) {
@@ -128,16 +130,6 @@ void StartMenuScreen::buttonClicked(Button* button) {
{ {
minecraft->setScreen(new OptionsScreen()); minecraft->setScreen(new OptionsScreen());
} }
if (button->id == bTest.id)
{
//minecraft->setScreen(new PauseScreen());
//minecraft->setScreen(new PrerenderTilesScreen());
}
if (button->id == bBuy.id)
{
minecraft->platform()->buyGame();
//minecraft->setScreen(new BuyGameScreen());
}
} }
bool StartMenuScreen::isInGameScreen() { return false; } bool StartMenuScreen::isInGameScreen() { return false; }
@@ -181,25 +173,30 @@ void StartMenuScreen::render( int xm, int ym, float a )
drawString(font, version, versionPosX, 62, /*50,*/ 0xffcccccc);//0x666666); drawString(font, version, versionPosX, 62, /*50,*/ 0xffcccccc);//0x666666);
drawString(font, copyright, copyrightPosX, height - 10, 0xffffff); drawString(font, copyright, copyrightPosX, height - 10, 0xffffff);
glEnable2(GL_BLEND);
Screen::render(xm, ym, a); glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f2(1, 1, 1, 1);
if (Textures::isTextureIdValid(minecraft->textures->loadAndBindTexture("gui/logo/github.png")))
blit(2, height - 10, 0, 0, 8, 8, 256, 256);
{
std::string txt = "Kolyah35/minecraft-pe-0.6.1";
float wtxt = font->width(txt);
Gui::drawColoredString(font, txt, 12, height - 10, 255);
// underline link
float y0 = height - 10 + font->lineHeight - 1;
this->fill(12, (int)y0, 12 + (int)wtxt, (int)(y0 + 1), 0xffffffff);
}
} }
void StartMenuScreen::_updateLicense() void StartMenuScreen::mouseClicked(int x, int y, int buttonNum) {
{ const int logoX = 2;
int id = minecraft->getLicenseId(); const int logoW = 8 + 2 + font->width("Kolyah35/minecraft-pe-0.6.1");
if (LicenseCodes::isReady(id)) const int logoY = height - 10;
{ const int logoH = 10;
if (LicenseCodes::isOk(id)) if (x >= logoX && x <= logoX + logoW && y >= logoY && y <= logoY + logoH)
bJoin.active = bHost.active = bOptions.active = true; minecraft->platform()->openURL("https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1");
else else
{ Screen::mouseClicked(x, y, buttonNum);
bool hasBuyButton = minecraft->platform()->hasBuyButtonWhenInvalidLicense();
minecraft->setScreen(new InvalidLicenseScreen(id, hasBuyButton));
}
} else {
bJoin.active = bHost.active = bOptions.active = false;
}
} }
bool StartMenuScreen::handleBackEvent( bool isDown ) { bool StartMenuScreen::handleBackEvent( bool isDown ) {

View File

@@ -17,16 +17,14 @@ public:
void render(int xm, int ym, float a); void render(int xm, int ym, float a);
void buttonClicked(Button* button); void buttonClicked(Button* button);
virtual void mouseClicked(int x, int y, int buttonNum);
bool handleBackEvent(bool isDown); bool handleBackEvent(bool isDown);
bool isInGameScreen(); bool isInGameScreen();
private: private:
void _updateLicense();
Button bHost; Button bHost;
Button bJoin; Button bJoin;
Button bOptions; Button bOptions;
Button bTest;
Button bBuy;
std::string copyright; std::string copyright;
int copyrightPosX; int copyrightPosX;

View File

@@ -0,0 +1,126 @@
#include "UsernameScreen.h"
#include "StartMenuScreen.h"
#include "../../Minecraft.h"
#include "../../User.h"
#include "../Font.h"
#include "../components/Button.h"
#include "../../../platform/input/Keyboard.h"
#include "../../../AppPlatform.h"
UsernameScreen::UsernameScreen()
: _btnDone(0, "Done"),
tUsername(0, "Username"),
_cursorBlink(0)
{
}
UsernameScreen::~UsernameScreen()
{
}
void UsernameScreen::init()
{
_input = "";
_btnDone.active = false; // disabled until name typed
buttons.push_back(&_btnDone);
tabButtons.push_back(&_btnDone);
textBoxes.push_back(&tUsername);
setupPositions();
}
void UsernameScreen::setupPositions()
{
int cx = width / 2;
int cy = height / 2;
_btnDone.width = 120;
_btnDone.height = 20;
_btnDone.x = (width - _btnDone.width) / 2;
_btnDone.y = height / 2 + 52;
tUsername.x = _btnDone.x;
tUsername.y = _btnDone.y - 60;
tUsername.width = 120;
tUsername.height = 20;
}
void UsernameScreen::tick()
{
for (auto* tb : textBoxes)
tb->tick(minecraft);
}
void UsernameScreen::keyPressed(int eventKey)
{
if (eventKey == Keyboard::KEY_RETURN) {
if (!tUsername.text.empty())
buttonClicked(&_btnDone);
}
// deliberately do NOT call super::keyPressed — that would close the screen on Escape
_btnDone.active = !tUsername.text.empty();
Screen::keyPressed(eventKey);
}
void UsernameScreen::keyboardNewChar(char inputChar)
{
for (auto* tb : textBoxes) tb->handleChar(inputChar);
}
void UsernameScreen::mouseClicked(int x, int y, int button)
{
int lvlTop = tUsername.y - (Font::DefaultLineHeight + 4);
int lvlBottom = tUsername.y + tUsername.height;
int lvlLeft = tUsername.x;
int lvlRight = tUsername.x + tUsername.width;
bool clickedLevel = x >= lvlLeft && x < lvlRight && y >= lvlTop && y < lvlBottom;
if (clickedLevel) {
tUsername.setFocus(minecraft);
} else {
// click outside both fields -> blur both
tUsername.loseFocus(minecraft);
}
// also let the parent class handle button presses/etc.
Screen::mouseClicked(x, y, button);
}
void UsernameScreen::removed()
{
minecraft->platform()->hideKeyboard();
}
void UsernameScreen::buttonClicked(Button* button)
{
if (button == &_btnDone && !tUsername.text.empty()) {
minecraft->options.username = tUsername.text;
minecraft->options.save();
minecraft->user->name = tUsername.text;
minecraft->setScreen(NULL); // goes to StartMenuScreen
}
}
void UsernameScreen::render(int xm, int ym, float a)
{
// Dark dirt background
renderBackground();
int cx = width / 2;
int cy = height / 2;
// Title
drawCenteredString(font, "Enter your username", cx, cy - 70, 0xffffffff);
// Subtitle
drawCenteredString(font, "Please choose a username so others can easily", cx, cy - 52, 0xffaaaaaa);
drawCenteredString(font, "identify you in chat. Don't worry, you can", cx, cy - 40, 0xffaaaaaa);
drawCenteredString(font, "change it anytime.", cx, cy - 28, 0xffaaaaaa);
// // Hint below box
// drawCenteredString(font, "Max 16 characters", cx, cy + 20, 0xff808080);
// Buttons (Done)
super::render(xm, ym, a);
}

View File

@@ -0,0 +1,39 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__UsernameScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__UsernameScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
#include "client/gui/components/TextBox.h"
#include <string>
class UsernameScreen : public Screen
{
typedef Screen super;
public:
UsernameScreen();
virtual ~UsernameScreen();
void init();
virtual void setupPositions() override;
void render(int xm, int ym, float a);
void tick();
virtual bool isPauseScreen() { return false; }
virtual void keyPressed(int eventKey);
virtual void keyboardNewChar(char inputChar);
virtual bool handleBackEvent(bool isDown) { return true; } // block back/escape
virtual void removed();
virtual void mouseClicked(int x, int y, int button);
protected:
virtual void buttonClicked(Button* button);
private:
Button _btnDone;
TextBox tUsername;
std::string _input;
int _cursorBlink;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__UsernameScreen_H__*/

View File

@@ -64,6 +64,7 @@ void AvailableGamesList::renderItem( int i, int x, int y, int h, Tesselator& t )
JoinGameScreen::JoinGameScreen() JoinGameScreen::JoinGameScreen()
: bJoin( 2, "Join Game"), : bJoin( 2, "Join Game"),
bBack( 3, "Back"), bBack( 3, "Back"),
bJoinByIp(4, "Join By IP"),
bHeader(0, ""), bHeader(0, ""),
gamesList(NULL) gamesList(NULL)
{ {
@@ -80,6 +81,7 @@ void JoinGameScreen::init()
{ {
//buttons.push_back(&bJoin); //buttons.push_back(&bJoin);
buttons.push_back(&bBack); buttons.push_back(&bBack);
buttons.push_back(&bJoinByIp);
buttons.push_back(&bHeader); buttons.push_back(&bHeader);
minecraft->raknetInstance->clearServerList(); minecraft->raknetInstance->clearServerList();
@@ -88,6 +90,7 @@ void JoinGameScreen::init()
#ifdef ANDROID #ifdef ANDROID
//tabButtons.push_back(&bJoin); //tabButtons.push_back(&bJoin);
tabButtons.push_back(&bBack); tabButtons.push_back(&bBack);
tabButtons.push_back(&bJoinByIp);
#endif #endif
} }
@@ -97,14 +100,16 @@ void JoinGameScreen::setupPositions() {
//#ifdef ANDROID //#ifdef ANDROID
bJoin.y = 0; bJoin.y = 0;
bBack.y = 0; bBack.y = 0;
bJoinByIp.y = 0;
bHeader.y = 0; bHeader.y = 0;
//#endif //#endif
// Center buttons // Center buttons
//bJoin.x = width / 2 - 4 - bJoin.w; //bJoin.x = width / 2 - 4 - bJoin.w;
bBack.x = 0;//width / 2 + 4; bBack.x = 0;//width / 2 + 4;
bHeader.x = bBack.width; bJoinByIp.x = width - bJoinByIp.width;;
bHeader.width = width - bHeader.x; bHeader.x = bJoinByIp.width;
bHeader.width = width - (bBack.width + bJoinByIp.width);
} }
void JoinGameScreen::buttonClicked(Button* button) void JoinGameScreen::buttonClicked(Button* button)
@@ -124,6 +129,11 @@ void JoinGameScreen::buttonClicked(Button* button)
//minecraft->locateMultiplayer(); //minecraft->locateMultiplayer();
//minecraft->setScreen(new JoinGameScreen()); //minecraft->setScreen(new JoinGameScreen());
} }
if(button->id == bJoinByIp.id) {
minecraft->cancelLocateMultiplayer();
minecraft->screenChooser.setScreen(SCREEN_JOINBYIP);
}
if (button->id == bBack.id) if (button->id == bBack.id)
{ {
minecraft->cancelLocateMultiplayer(); minecraft->cancelLocateMultiplayer();

View File

@@ -65,6 +65,7 @@ public:
private: private:
Button bJoin; Button bJoin;
TButton bBack; TButton bBack;
TButton bJoinByIp;
THeader bHeader; THeader bHeader;
AvailableGamesList* gamesList; AvailableGamesList* gamesList;
}; };

View File

@@ -283,8 +283,7 @@ SelectWorldScreen::SelectWorldScreen()
bHeader (0, "Select world"), bHeader (0, "Select world"),
bWorldView(4, ""), bWorldView(4, ""),
worldsList(NULL), worldsList(NULL),
_hasStartedLevel(false), _hasStartedLevel(false)
_state(_STATE_DEFAULT)
{ {
bDelete.active = false; bDelete.active = false;
@@ -349,9 +348,9 @@ void SelectWorldScreen::setupPositions() {
void SelectWorldScreen::buttonClicked(Button* button) void SelectWorldScreen::buttonClicked(Button* button)
{ {
if (button->id == bCreate.id) { if (button->id == bCreate.id) {
if (_state == _STATE_DEFAULT && !_hasStartedLevel) { if (!_hasStartedLevel) {
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_CREATE_NEW_WORLD); std::string name = getUniqueLevelName("World");
_state = _STATE_CREATEWORLD; minecraft->setScreen(new SimpleChooseLevelScreen(name));
} }
} }
if (button->id == bDelete.id) { if (button->id == bDelete.id) {
@@ -392,9 +391,10 @@ static char ILLEGAL_FILE_CHARACTERS[] = {
void SelectWorldScreen::tick() void SelectWorldScreen::tick()
{ {
#if 0
if (_state == _STATE_CREATEWORLD) { if (_state == _STATE_CREATEWORLD) {
#if defined(RPI) #if defined(RPI)
std::string levelId = getUniqueLevelName("perf"); std::string levelId = getUniqueLevelName("World");
//int seed = Util::hashCode("/r/Minecraft"); //int seed = Util::hashCode("/r/Minecraft");
LevelSettings settings(getEpochTimeS(), GameType::Creative); LevelSettings settings(getEpochTimeS(), GameType::Creative);
minecraft->selectLevel(levelId, levelId, settings); minecraft->selectLevel(levelId, levelId, settings);
@@ -402,7 +402,7 @@ void SelectWorldScreen::tick()
minecraft->setScreen(new ProgressScreen()); minecraft->setScreen(new ProgressScreen());
_hasStartedLevel = true; _hasStartedLevel = true;
#elif defined(PLATFORM_DESKTOP) #elif defined(PLATFORM_DESKTOP)
std::string name = getUniqueLevelName("perf"); std::string name = getUniqueLevelName("World");
minecraft->setScreen(new SimpleChooseLevelScreen(name)); minecraft->setScreen(new SimpleChooseLevelScreen(name));
#else #else
int status = minecraft->platform()->getUserInputStatus(); int status = minecraft->platform()->getUserInputStatus();
@@ -461,14 +461,15 @@ void SelectWorldScreen::tick()
worldsList->hasPickedLevel = false; worldsList->hasPickedLevel = false;
return; return;
} }
#endif
worldsList->tick(); worldsList->tick();
if (worldsList->hasPickedLevel) { if (worldsList->hasPickedLevel) {
if (worldsList->pickedIndex == worldsList->levels.size()) { if (worldsList->pickedIndex == worldsList->levels.size()) {
worldsList->hasPickedLevel = false; worldsList->hasPickedLevel = false;
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_CREATE_NEW_WORLD); std::string name = getUniqueLevelName("World");
_state = _STATE_CREATEWORLD; minecraft->setScreen(new SimpleChooseLevelScreen(name));
} else { } else {
minecraft->selectLevel(worldsList->pickedLevel.id, worldsList->pickedLevel.name, LevelSettings::None()); minecraft->selectLevel(worldsList->pickedLevel.id, worldsList->pickedLevel.name, LevelSettings::None());
minecraft->hostMultiplayer(); minecraft->hostMultiplayer();

View File

@@ -112,9 +112,6 @@ private:
bool _mouseHasBeenUp; bool _mouseHasBeenUp;
bool _hasStartedLevel; bool _hasStartedLevel;
int _state;
static const int _STATE_DEFAULT = 0;
static const int _STATE_CREATEWORLD = 1;
//LevelStorageSource* levels; //LevelStorageSource* levels;
}; };
}; };

View File

@@ -2,8 +2,6 @@
#include "../ProgressScreen.h" #include "../ProgressScreen.h"
#include "../OptionsScreen.h" #include "../OptionsScreen.h"
#include "../PauseScreen.h" #include "../PauseScreen.h"
#include "../InvalidLicenseScreen.h"
//#include "BuyGameScreen.h"
#include "../../Font.h" #include "../../Font.h"
#include "../../components/SmallButton.h" #include "../../components/SmallButton.h"
@@ -22,62 +20,6 @@
#include "../DialogDefinitions.h" #include "../DialogDefinitions.h"
#include "../SimpleChooseLevelScreen.h" #include "../SimpleChooseLevelScreen.h"
//
// Buy Button implementation
//
BuyButton::BuyButton(int id)
: super(id, "")
{
ImageDef def;
// Setup the source rectangle
def.setSrc(IntRectangle(64, 182, 190, 55));
def.width = 75;//rc.w / 3;
def.height = 75 * (55.0f / 190.0f);//rc.h / 3;
def.name = "gui/gui.png";
setImageDef(def, true);
}
void BuyButton::render(Minecraft* minecraft, int xm, int ym) {
glColor4f2(1, 1, 1, 1);
bool hovered = active && (minecraft->useTouchscreen()? (xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
renderBg(minecraft, xm, ym);
TextureId texId = (_imageDef.name.length() > 0)? minecraft->textures->loadAndBindTexture(_imageDef.name) : Textures::InvalidId;
if ( Textures::isTextureIdValid(texId) ) {
const ImageDef& d = _imageDef;
Tesselator& t = Tesselator::instance;
t.begin();
if (!active) t.color(0xff808080);
else if (hovered||selected) t.color(0xffcccccc);
//else t.color(0xffe0e0e0);
else t.color(0xffffffff);
float hx = ((float) d.width) * 0.5f;
float hy = ((float) d.height) * 0.5f;
const float cx = ((float)x+d.x) + hx;
const float cy = ((float)y+d.y) + hy;
if (hovered) {
hx *= 0.95f;
hy *= 0.95f;
}
const TextureData* td = minecraft->textures->getTemporaryTextureData(texId);
const IntRectangle* src = _imageDef.getSrc();
if (td != NULL && src != NULL) {
float u0 = (src->x) / (float)td->w;
float u1 = (src->x+src->w) / (float)td->w;
float v0 = (src->y) / (float)td->h;
float v1 = (src->y+src->h) / (float)td->h;
t.vertexUV(cx-hx, cy-hy, blitOffset, u0, v0);
t.vertexUV(cx-hx, cy+hy, blitOffset, u0, v1);
t.vertexUV(cx+hx, cy+hy, blitOffset, u1, v1);
t.vertexUV(cx+hx, cy-hy, blitOffset, u1, v0);
}
t.draw();
}
}
namespace Touch { namespace Touch {
// //
@@ -88,9 +30,7 @@ namespace Touch {
StartMenuScreen::StartMenuScreen() StartMenuScreen::StartMenuScreen()
: bHost( 2, "Start Game"), : bHost( 2, "Start Game"),
bJoin( 3, "Join Game"), bJoin( 3, "Join Game"),
bOptions( 4, "Options"), bOptions( 4, "Options")
bBuy( 5),
bTest( 9, "Create")
{ {
ImageDef def; ImageDef def;
bJoin.width = 75; bJoin.width = 75;
@@ -119,7 +59,7 @@ void StartMenuScreen::init()
buttons.push_back(&bJoin); buttons.push_back(&bJoin);
buttons.push_back(&bOptions); buttons.push_back(&bOptions);
//buttons.push_back(&bTest);
tabButtons.push_back(&bHost); tabButtons.push_back(&bHost);
tabButtons.push_back(&bJoin); tabButtons.push_back(&bJoin);
@@ -132,11 +72,8 @@ void StartMenuScreen::init()
copyright = "\xffMojang AB";//. Do not distribute!"; copyright = "\xffMojang AB";//. Do not distribute!";
#ifdef PRE_ANDROID23 // always show base version string
std::string versionString = Common::getGameVersionString("j");
#else
std::string versionString = Common::getGameVersionString(); std::string versionString = Common::getGameVersionString();
#endif
#ifdef DEMO_MODE #ifdef DEMO_MODE
#ifdef __APPLE__ #ifdef __APPLE__
@@ -152,7 +89,7 @@ void StartMenuScreen::init()
version = versionString + " (Demo)"; version = versionString + " (Demo)";
#endif #endif
bJoin.active = bHost.active = bOptions.active = false; bJoin.active = bHost.active = bOptions.active = true;
} }
void StartMenuScreen::setupPositions() { void StartMenuScreen::setupPositions() {
@@ -166,37 +103,17 @@ void StartMenuScreen::setupPositions() {
bOptions.y = yBase; bOptions.y = yBase;
//#endif //#endif
//bTest.x = 0; //width - bTest.w;
//bTest.y = height - bTest.h;
// Center buttons // Center buttons
bJoin.x = 0*buttonWidth + (int)(1*spacing); bJoin.x = 0*buttonWidth + (int)(1*spacing);
bHost.x = 1*buttonWidth + (int)(2*spacing); bHost.x = 1*buttonWidth + (int)(2*spacing);
bOptions.x = 2*buttonWidth + (int)(3*spacing); bOptions.x = 2*buttonWidth + (int)(3*spacing);
//bBuy.y = bOptions.y - bBuy.h - 6;
//bBuy.x = bOptions.x + bOptions.w - bBuy.w;
bBuy.y = height - bBuy.height - 3;
bBuy.x = (width - bBuy.width) / 2;
bTest.x = 4;
bTest.y = height - bTest.height - 4;
copyrightPosX = width - minecraft->font->width(copyright) - 1; copyrightPosX = width - minecraft->font->width(copyright) - 1;
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2; versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
} }
void StartMenuScreen::tick() {
_updateLicense();
}
void StartMenuScreen::buttonClicked(::Button* button) { void StartMenuScreen::buttonClicked(::Button* button) {
//if (button->id == bTest.id) {
// minecraft->selectLevel("Broken", "Broken", 1317199248);
// minecraft->hostMultiplayer();
// minecraft->setScreen(new ProgressScreen());
//}
if (button->id == bHost.id) if (button->id == bHost.id)
{ {
#if defined(DEMO_MODE) || defined(APPLE_DEMO_PROMOTION) #if defined(DEMO_MODE) || defined(APPLE_DEMO_PROMOTION)
@@ -218,11 +135,6 @@ void StartMenuScreen::buttonClicked(::Button* button) {
{ {
minecraft->setScreen(new OptionsScreen()); minecraft->setScreen(new OptionsScreen());
} }
if (button->id == bBuy.id)
{
minecraft->platform()->buyGame();
//minecraft->setScreen(new BuyGameScreen());
}
} }
bool StartMenuScreen::isInGameScreen() { return false; } bool StartMenuScreen::isInGameScreen() { return false; }
@@ -261,27 +173,26 @@ void StartMenuScreen::render( int xm, int ym, float a )
drawString(font, version, versionPosX, (int)(y+h)+2, /*50,*/ 0xffcccccc);//0x666666); drawString(font, version, versionPosX, (int)(y+h)+2, /*50,*/ 0xffcccccc);//0x666666);
drawString(font, copyright, copyrightPosX, height - 10, 0xffffff); drawString(font, copyright, copyrightPosX, height - 10, 0xffffff);
glColor4f2(1, 1, 1, 1);
if (Textures::isTextureIdValid(minecraft->textures->loadAndBindTexture("gui/logo/github.png")))
blit(2, height - 10, 0, 0, 8, 8, 256, 256);
drawString(font, "Kolyah35/minecraft-pe-0.6.1", 12, height - 10, 0xffcccccc);
//patch->draw(t, 0, 20); //patch->draw(t, 0, 20);
} }
Screen::render(xm, ym, a); Screen::render(xm, ym, a);
glDisable2(GL_BLEND); glDisable2(GL_BLEND);
} }
void StartMenuScreen::_updateLicense()
{ void StartMenuScreen::mouseClicked(int x, int y, int buttonNum) {
int id = minecraft->getLicenseId(); const int logoX = 2;
if (LicenseCodes::isReady(id)) const int logoW = 8 + 2 + font->width("Kolyah35/minecraft-pe-0.6.1");
{ const int logoY = height - 10;
if (LicenseCodes::isOk(id)) const int logoH = 10;
bJoin.active = bHost.active = bOptions.active = true; if (x >= logoX && x <= logoX + logoW && y >= logoY && y <= logoY + logoH)
minecraft->platform()->openURL("https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1");
else else
{ Screen::mouseClicked(x, y, buttonNum);
bool hasBuyButton = minecraft->platform()->hasBuyButtonWhenInvalidLicense();
minecraft->setScreen(new InvalidLicenseScreen(id, hasBuyButton));
}
} else {
bJoin.active = bHost.active = bOptions.active = false;
}
} }
bool StartMenuScreen::handleBackEvent( bool isDown ) { bool StartMenuScreen::handleBackEvent( bool isDown ) {
@@ -289,4 +200,5 @@ bool StartMenuScreen::handleBackEvent( bool isDown ) {
return true; return true;
} }
}; } // namespace Touch

View File

@@ -3,15 +3,7 @@
#include "../../Screen.h" #include "../../Screen.h"
#include "../../components/LargeImageButton.h" #include "../../components/LargeImageButton.h"
#include "../../components/TextBox.h"
class BuyButton: public ImageButton {
typedef ImageButton super;
public:
BuyButton(int id);
void render(Minecraft* minecraft, int xm, int ym);
};
namespace Touch { namespace Touch {
@@ -24,20 +16,17 @@ public:
void init(); void init();
void setupPositions(); void setupPositions();
void tick();
void render(int xm, int ym, float a); void render(int xm, int ym, float a);
void buttonClicked(Button* button); void buttonClicked(Button* button);
virtual void mouseClicked(int x, int y, int buttonNum);
bool handleBackEvent(bool isDown); bool handleBackEvent(bool isDown);
bool isInGameScreen(); bool isInGameScreen();
private: private:
void _updateLicense();
LargeImageButton bHost; LargeImageButton bHost;
LargeImageButton bJoin; LargeImageButton bJoin;
LargeImageButton bOptions; LargeImageButton bOptions;
TButton bTest;
BuyButton bBuy;
std::string copyright; std::string copyright;
int copyrightPosX; int copyrightPosX;

View File

@@ -50,7 +50,10 @@ LocalPlayer::LocalPlayer(Minecraft* minecraft, Level* level, User* user, int dim
sentInventoryItemId(-1), sentInventoryItemId(-1),
sentInventoryItemData(-1), sentInventoryItemData(-1),
autoJumpEnabled(true), autoJumpEnabled(true),
armorTypeHash(0) armorTypeHash(0),
sprinting(false),
sprintDoubleTapTimer(0),
prevForwardHeld(false)
{ {
this->dimension = dimension; this->dimension = dimension;
_init(); _init();
@@ -176,6 +179,25 @@ void LocalPlayer::aiStep() {
if (!screenCovering) if (!screenCovering)
input->tick(this); input->tick(this);
// Sprint: detect W double-tap
{
bool forwardHeld = (input->ya > 0);
if (forwardHeld && !prevForwardHeld) {
// leading edge of W press
if (sprintDoubleTapTimer > 0)
sprinting = true;
else
sprintDoubleTapTimer = 7;
}
if (!forwardHeld) {
sprinting = false;
}
if (sprintDoubleTapTimer > 0) sprintDoubleTapTimer--;
prevForwardHeld = forwardHeld;
}
if (input->sneaking || abilities.flying)
sprinting = false;
if (input->sneaking) { if (input->sneaking) {
if (ySlideOffset < 0.2f) ySlideOffset = 0.2f; if (ySlideOffset < 0.2f) ySlideOffset = 0.2f;
} }
@@ -296,6 +318,10 @@ void LocalPlayer::releaseAllKeys()
if (input) input->releaseAllKeys(); if (input) input->releaseAllKeys();
} }
float LocalPlayer::getWalkingSpeedModifier() {
return sprinting ? 1.3f : 1.0f;
}
float LocalPlayer::getFieldOfViewModifier() { float LocalPlayer::getFieldOfViewModifier() {
float targetFov = 1.0f; float targetFov = 1.0f;
if(abilities.flying) targetFov *= 1.1f; if(abilities.flying) targetFov *= 1.1f;

View File

@@ -70,6 +70,7 @@ public:
void swing(); void swing();
virtual void openTextEdit( TileEntity* tileEntity ); virtual void openTextEdit( TileEntity* tileEntity );
virtual float getWalkingSpeedModifier();
private: private:
void calculateFlight(float xa, float ya, float za); void calculateFlight(float xa, float ya, float za);
bool isSolidTile(int x, int y, int z); bool isSolidTile(int x, int y, int z);
@@ -99,6 +100,11 @@ private:
int sentInventoryItemData; int sentInventoryItemData;
int armorTypeHash; int armorTypeHash;
// sprinting
bool sprinting;
int sprintDoubleTapTimer;
bool prevForwardHeld;
}; };
#endif /*NET_MINECRAFT_CLIENT_PLAYER__LocalPlayer_H__*/ #endif /*NET_MINECRAFT_CLIENT_PLAYER__LocalPlayer_H__*/

View File

@@ -52,7 +52,7 @@ void KeyboardInput::tick( Player* player )
ya *= 0.3f; ya *= 0.3f;
} }
#ifdef RPI #if defined(RPI) || defined(PLATFORM_DESKTOP)
wantUp = jumping; wantUp = jumping;
wantDown = sneaking; wantDown = sneaking;
#endif #endif

View File

@@ -270,15 +270,15 @@ void GameRenderer::renderLevel(float a) {
screenScissorArea.w, screenScissorArea.h); screenScissorArea.w, screenScissorArea.h);
} }
// if(mc->options.fancyGraphics) { if(mc->options.fancyGraphics) {
// setupFog(-1); setupFog(-1);
// TIMER_POP_PUSH("sky"); TIMER_POP_PUSH("sky");
// glFogf(GL_FOG_START, renderDistance * 0.2f); glFogf(GL_FOG_START, renderDistance * 0.2f);
// glFogf(GL_FOG_END, renderDistance *0.75); glFogf(GL_FOG_END, renderDistance *0.75);
// levelRenderer->renderSky(a); levelRenderer->renderSky(a);
// glFogf(GL_FOG_START, renderDistance * 0.6f); glFogf(GL_FOG_START, renderDistance * 0.6f);
// glFogf(GL_FOG_END, renderDistance); glFogf(GL_FOG_END, renderDistance);
// } }
glEnable2(GL_FOG); glEnable2(GL_FOG);
setupFog(1); setupFog(1);

View File

@@ -16,11 +16,11 @@
#if defined(__APPLE__) #if defined(__APPLE__)
#import <OpenGLES/ES1/gl.height> #import <OpenGLES/ES1/gl.height>
#import <OpenGLES/ES1/glext.height> #import <OpenGLES/ES1/glext.height>
#elif defined(ANDROID)
#include <GLES/gl.h>
#include <GLES/glext.h>
#else #else
#include <glad/glad.h> #include <glad/glad.h>
#if defined(ANDROID)
#include<GLES/glext.h>
#endif
#endif #endif
#else #else
// Uglyness to fix redeclaration issues // Uglyness to fix redeclaration issues

View File

@@ -43,6 +43,7 @@ public:
void destroy() const { void destroy() const {
if (isValid()) { if (isValid()) {
delete buffer;
buffer = 0; buffer = 0;
} }
} }

View File

@@ -230,10 +230,13 @@ void SoundEngine::playUI(const std::string& name, float volume, float pitch) {}
void SoundEngine::play(const std::string& name, float x, float y, float z, float volume, float pitch) { void SoundEngine::play(const std::string& name, float x, float y, float z, float volume, float pitch) {
if ((volume *= options->sound) <= 0) return; if ((volume *= options->sound) <= 0) return;
volume = Mth::clamp(volume, 0.0f, 1.0f); volume = Mth::clamp( volume * _getVolumeMult(x, y, z), 0.0f, 1.0f);
if (/*!loaded || */options->sound == 0 || volume <= 0) return;
SoundDesc sound; SoundDesc sound;
if (sounds.get(name, sound)) { if (sounds.get(name, sound)) {
float dist = SOUND_DISTANCE;
if (volume > 1) dist *= volume;
soundSystem.playAt(sound, x-_x, y-_y, z-_z, volume, pitch); soundSystem.playAt(sound, x-_x, y-_y, z-_z, volume, pitch);
} }
} }

View File

@@ -5,7 +5,7 @@
#if defined(ANDROID) && !defined(PRE_ANDROID23) #if defined(ANDROID) && !defined(PRE_ANDROID23)
#include "../../platform/audio/SoundSystemSL.h" #include "../../platform/audio/SoundSystemSL.h"
#elif defined(__APPLE__) || defined (PLATFORM_DESKTOP) #elif defined(__APPLE__) || defined(PLATFORM_DESKTOP)
#include "../../platform/audio/SoundSystemAL.h" #include "../../platform/audio/SoundSystemAL.h"
#else #else
#include "../../platform/audio/SoundSystem.h" #include "../../platform/audio/SoundSystem.h"
@@ -23,7 +23,7 @@ class SoundEngine
#if defined(ANDROID) && !defined(PRE_ANDROID23) && !defined(RPI) #if defined(ANDROID) && !defined(PRE_ANDROID23) && !defined(RPI)
SoundSystemSL soundSystem; SoundSystemSL soundSystem;
#elif defined(__APPLE__) || defined (PLATFORM_DESKTOP) #elif defined(__APPLE__) || defined(PLATFORM_DESKTOP)
SoundSystemAL soundSystem; SoundSystemAL soundSystem;
#else #else
SoundSystem soundSystem; SoundSystem soundSystem;

View File

@@ -1,5 +1,6 @@
#include "App.h" #include "App.h"
#include "AppPlatform_android.h" #include "AppPlatform_android.h"
#include <android_native_app_glue.h>
// Horrible, I know. / A // Horrible, I know. / A
#ifndef MAIN_CLASS #ifndef MAIN_CLASS
@@ -38,7 +39,15 @@ static void setupExternalPath(struct android_app* state, MAIN_CLASS* app)
const char* str = env->GetStringUTFChars((jstring) pathString, NULL); const char* str = env->GetStringUTFChars((jstring) pathString, NULL);
app->externalStoragePath = str; app->externalStoragePath = str;
app->externalCacheStoragePath = str; app->externalCacheStoragePath = str;
LOGI(str); LOGI("%s", str);
// ensure the process working directory is set to a writable location
// on Android the default cwd may be '/' which isn't writable. By chdir'ing
// to the external storage path we make relative fopen calls (e.g. "options.txt")
// succeed and persist across launches, fixing the "options never save" bug.
if (chdir(str) != 0) {
LOGI("chdir to %s failed: %s", str, strerror(errno));
}
env->ReleaseStringUTFChars((jstring)pathString, str); env->ReleaseStringUTFChars((jstring)pathString, str);

View File

@@ -1,8 +1,14 @@
#include "App.h" #include "App.h"
#include "AppPlatform_android.h" #include "AppPlatform_android.h"
// JNI keycode constants
#include <android/keycodes.h>
//#include "main_android_java.h" //#include "main_android_java.h"
#include "platform/input/Multitouch.h" #include "platform/input/Multitouch.h"
#include <unistd.h>
#include <sys/syscall.h>
#define gettid() ((int)syscall(SYS_gettid))
// Horrible, I know. / A // Horrible, I know. / A
#ifndef MAIN_CLASS #ifndef MAIN_CLASS
@@ -39,7 +45,12 @@ static void setupExternalPath(JNIEnv* env, MAIN_CLASS* app)
const char* str = env->GetStringUTFChars((jstring) pathString, NULL); const char* str = env->GetStringUTFChars((jstring) pathString, NULL);
app->externalStoragePath = str; app->externalStoragePath = str;
app->externalCacheStoragePath = str; app->externalCacheStoragePath = str;
LOGI(str); LOGI("%s", str);
// same fix as the native entry point: make sure cwd is writable
if (chdir(str) != 0) {
LOGI("chdir to %s failed: %s", str, strerror(errno));
}
env->ReleaseStringUTFChars((jstring)pathString, str); env->ReleaseStringUTFChars((jstring)pathString, str);
} }
@@ -57,6 +68,7 @@ static void pointerMove(int pointerId, int x, int y) {
static App* gApp = 0; static App* gApp = 0;
static AppContext gContext; static AppContext gContext;
static bool g_inNativeOnCreate = false;
extern "C" { extern "C" {
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
@@ -81,34 +93,53 @@ Java_com_mojang_minecraftpe_MainActivity_nativeUnregisterThis(JNIEnv* env, jobje
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_mojang_minecraftpe_MainActivity_nativeOnCreate(JNIEnv* env) { Java_com_mojang_minecraftpe_MainActivity_nativeOnCreate(JNIEnv* env, jobject thiz, jint screenWidth, jint screenHeight) {
LOGI("@nativeOnCreate\n"); LOGI("@nativeOnCreate w=%d h=%d\n", (int)screenWidth, (int)screenHeight);
g_inNativeOnCreate = true;
appPlatform.instance = g_pActivity; appPlatform.instance = g_pActivity;
appPlatform.initConsts(); appPlatform.setScreenDimensions((int)screenWidth, (int)screenHeight);
LOGI("nativeOnCreate: screen set, no initConsts needed\n");
gContext.doRender = false; gContext.doRender = false;
gContext.platform = &appPlatform; gContext.platform = &appPlatform;
LOGI("nativeOnCreate: creating gApp\n");
gApp = new MAIN_CLASS(); gApp = new MAIN_CLASS();
LOGI("nativeOnCreate: gApp=%p\n", gApp);
setupExternalPath(env, (MAIN_CLASS*)gApp); setupExternalPath(env, (MAIN_CLASS*)gApp);
if (env->ExceptionOccurred()) {
LOGI("nativeOnCreate: exception after setupExternalPath!\n");
env->ExceptionDescribe();
env->ExceptionClear();
}
LOGI("nativeOnCreate: done\n");
g_inNativeOnCreate = false;
//gApp->init(gContext); //gApp->init(gContext);
} }
static int s_surfaceCreatedCount = 0;
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_mojang_minecraftpe_GLRenderer_nativeOnSurfaceCreated(JNIEnv* env) { Java_com_mojang_minecraftpe_GLRenderer_nativeOnSurfaceCreated(JNIEnv* env) {
LOGI("@nativeOnSurfaceCreated\n"); s_surfaceCreatedCount++;
if (g_inNativeOnCreate) {
// Skip re-entrant surface callbacks that fire during nativeOnCreate
return;
}
LOGI("@nativeOnSurfaceCreated #%d tid=%d\n", s_surfaceCreatedCount, (int)gettid());
if (gApp) { if (gApp) {
// gApp->setSize( gContext.platform->getScreenWidth(),
// gContext.platform->getScreenHeight(),
// gContext.platform->isTouchscreen());
// Don't call onGraphicsReset the first time // Don't call onGraphicsReset the first time
if (gApp->isInited()) if (gApp->isInited()) {
LOGI("nativeOnSurfaceCreated: calling onGraphicsReset\n");
gApp->onGraphicsReset(gContext); gApp->onGraphicsReset(gContext);
}
if (!gApp->isInited()) if (!gApp->isInited()) {
LOGI("nativeOnSurfaceCreated: calling init\n");
gApp->init(gContext); gApp->init(gContext);
LOGI("nativeOnSurfaceCreated: init done, isInited=%d\n", (int)gApp->isInited());
}
} }
} }
@@ -153,15 +184,40 @@ Java_com_mojang_minecraftpe_GLRenderer_nativeUpdate(JNIEnv* env) {
// //
// Keyboard events // Keyboard events
// //
// helper to convert Android keycodes to our internal Keyboard constants
static int androidKeyToInternal(int androidKey) {
switch(androidKey) {
case AKEYCODE_DEL: return Keyboard::KEY_BACKSPACE;
case AKEYCODE_ENTER:
case AKEYCODE_NUMPAD_ENTER:
return Keyboard::KEY_RETURN;
// letters are delivered via nativeTextChar so no need to map here
default:
return androidKey; // fall back to raw code
}
}
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_mojang_minecraftpe_MainActivity_nativeOnKeyDown(JNIEnv* env, jclass cls, jint keyCode) { Java_com_mojang_minecraftpe_MainActivity_nativeOnKeyDown(JNIEnv* env, jclass cls, jint keyCode) {
LOGI("@nativeOnKeyDown: %d\n", keyCode); LOGI("@nativeOnKeyDown: %d\n", keyCode);
Keyboard::feed(keyCode, true); int mapped = androidKeyToInternal(keyCode);
Keyboard::feed(mapped, true);
}
JNIEXPORT void JNICALL
Java_com_mojang_minecraftpe_MainActivity_nativeTextChar(JNIEnv* env, jclass cls, jint unicodeChar) {
// soft-keyboards may send a backspace as a character code
if (unicodeChar == 8) {
Keyboard::feed(Keyboard::KEY_BACKSPACE, true);
Keyboard::feed(Keyboard::KEY_BACKSPACE, false);
} else if (unicodeChar > 0 && unicodeChar < 128) {
Keyboard::feedText((char)unicodeChar);
}
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_mojang_minecraftpe_MainActivity_nativeOnKeyUp(JNIEnv* env, jclass cls, jint keyCode) { Java_com_mojang_minecraftpe_MainActivity_nativeOnKeyUp(JNIEnv* env, jclass cls, jint keyCode) {
LOGI("@nativeOnKeyUp: %d\n", (int)keyCode); LOGI("@nativeOnKeyUp: %d\n", (int)keyCode);
Keyboard::feed(keyCode, false); int mapped = androidKeyToInternal(keyCode);
Keyboard::feed(mapped, false);
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL

View File

@@ -7,6 +7,8 @@
#include "SharedConstants.h" #include "SharedConstants.h"
#include <cstdio> #include <cstdio>
#include <chrono>
#include <thread>
#include "platform/input/Keyboard.h" #include "platform/input/Keyboard.h"
#include "platform/input/Mouse.h" #include "platform/input/Mouse.h"
#include "platform/input/Multitouch.h" #include "platform/input/Multitouch.h"
@@ -32,6 +34,20 @@ int transformKey(int glfwkey) {
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if(action == GLFW_REPEAT) return; if(action == GLFW_REPEAT) return;
if (key == GLFW_KEY_F11 && action == GLFW_PRESS) {
GLFWmonitor* monitor = glfwGetWindowMonitor(window);
if (monitor) {
// Currently fullscreen → go windowed
glfwSetWindowMonitor(window, NULL, 80, 80, 854, 480, 0);
} else {
// Currently windowed → go fullscreen on primary monitor
GLFWmonitor* primary = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(primary);
glfwSetWindowMonitor(window, primary, 0, 0, mode->width, mode->height, mode->refreshRate);
}
return;
}
Keyboard::feed(transformKey(key), action); Keyboard::feed(transformKey(key), action);
} }
@@ -126,8 +142,9 @@ int main(void) {
glfwSetWindowSizeCallback(window, window_size_callback); glfwSetWindowSizeCallback(window, window_size_callback);
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
gladLoadGLES1Loader((GLADloadproc)glfwGetProcAddress); gladLoadGLES1Loader((GLADloadproc)winGLLoader);
glfwSwapInterval(1); glfwSwapInterval(0);
glPatchDesktopCompat();
#endif #endif
App* app = new MAIN_CLASS(); App* app = new MAIN_CLASS();
@@ -139,11 +156,23 @@ int main(void) {
g_app->setSize(appContext.platform->getScreenWidth(), appContext.platform->getScreenHeight()); g_app->setSize(appContext.platform->getScreenWidth(), appContext.platform->getScreenHeight());
// Main event loop // Main event loop
using clock = std::chrono::steady_clock;
while(!glfwWindowShouldClose(window) && !app->wantToQuit()) { while(!glfwWindowShouldClose(window) && !app->wantToQuit()) {
auto frameStart = clock::now();
app->update(); app->update();
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents(); glfwPollEvents();
glfwSwapInterval(((MAIN_CLASS*)app)->options.vsync ? 1 : 0);
if(((MAIN_CLASS*)app)->options.limitFramerate) {
auto frameEnd = clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(frameEnd - frameStart);
auto target = std::chrono::microseconds(33333); // ~30 fps
if(elapsed < target)
std::this_thread::sleep_for(target - elapsed);
}
} }
delete app; delete app;

View File

@@ -134,6 +134,11 @@ void ServerSideNetworkHandler::displayGameMessage(const std::string& message)
raknetInstance->send(packet); raknetInstance->send(packet);
} }
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPacket* packet)
{
displayGameMessage(packet->message);
}
void ServerSideNetworkHandler::onNewClient(const RakNet::RakNetGUID& clientGuid) void ServerSideNetworkHandler::onNewClient(const RakNet::RakNetGUID& clientGuid)
{ {
LOGI("onNewClient, client guid: %s\n", clientGuid.ToString()); LOGI("onNewClient, client guid: %s\n", clientGuid.ToString());
@@ -256,6 +261,11 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID
SetTimePacket(level->getTime()).write(&bitStream); SetTimePacket(level->getTime()).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false); rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
// send adventure settings (includes showNameTags, etc.)
bitStream.Reset();
AdventureSettingsPacket(level->adventureSettings).write(&bitStream);
rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, source, false);
// send all pre-existing players to the new player // send all pre-existing players to the new player
const PlayerList& players = level->players; const PlayerList& players = level->players;
for (unsigned int i = 0; i < players.size(); i++) { for (unsigned int i = 0; i < players.size(); i++) {

View File

@@ -57,18 +57,18 @@ public:
virtual void handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet); virtual void handle(const RakNet::RakNetGUID& source, ContainerSetSlotPacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet); virtual void handle(const RakNet::RakNetGUID& source, ContainerClosePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet); virtual void handle(const RakNet::RakNetGUID& source, SignUpdatePacket* packet);
virtual void handle(const RakNet::RakNetGUID& source, ChatPacket* packet);
bool allowsIncomingConnections() { return _allowIncoming; } bool allowsIncomingConnections() { return _allowIncoming; }
void allowIncomingConnections(bool doAllow); void allowIncomingConnections(bool doAllow);
Player* popPendingPlayer(const RakNet::RakNetGUID& source); Player* popPendingPlayer(const RakNet::RakNetGUID& source);
void displayGameMessage(const std::string& message);
private: private:
void redistributePacket(Packet* packet, const RakNet::RakNetGUID& fromPlayer); void redistributePacket(Packet* packet, const RakNet::RakNetGUID& fromPlayer);
void displayGameMessage(const std::string& message);
Player* getPlayer(const RakNet::RakNetGUID& source); Player* getPlayer(const RakNet::RakNetGUID& source);
private:
Minecraft* minecraft; Minecraft* minecraft;
Level* level; Level* level;

View File

@@ -4,6 +4,7 @@
//package net.minecraft.network.packet; //package net.minecraft.network.packet;
#include "../Packet.h" #include "../Packet.h"
#include <cstdint>
class SetTimePacket: public Packet { class SetTimePacket: public Packet {
public: public:
@@ -11,7 +12,7 @@ public:
} }
SetTimePacket(long time) SetTimePacket(long time)
: time(time) : time((int32_t)time)
{} {}
void write(RakNet::BitStream* bitStream) void write(RakNet::BitStream* bitStream)
@@ -30,7 +31,7 @@ public:
callback->handle(source, (SetTimePacket*)this); callback->handle(source, (SetTimePacket*)this);
} }
long time; int32_t time;
}; };
#endif /*NET_MINECRAFT_NETWORK_PACKET__SetTimePacket_H__*/ #endif /*NET_MINECRAFT_NETWORK_PACKET__SetTimePacket_H__*/

View File

@@ -2,11 +2,12 @@
#define NET_MINECRAFT_NETWORK_PACKET__StartGamePacket_H__ #define NET_MINECRAFT_NETWORK_PACKET__StartGamePacket_H__
#include "../Packet.h" #include "../Packet.h"
#include <cstdint>
class StartGamePacket : public Packet class StartGamePacket : public Packet
{ {
public: public:
long levelSeed; int32_t levelSeed;
int levelGeneratorVersion; int levelGeneratorVersion;
int gameType; int gameType;
@@ -18,7 +19,7 @@ public:
} }
StartGamePacket(long seed, int levelGeneratorVersion, int gameType, int entityId, float x, float y, float z) StartGamePacket(long seed, int levelGeneratorVersion, int gameType, int entityId, float x, float y, float z)
: levelSeed(seed), : levelSeed((int32_t)seed),
levelGeneratorVersion(levelGeneratorVersion), levelGeneratorVersion(levelGeneratorVersion),
gameType(gameType), gameType(gameType),
entityId(entityId), entityId(entityId),

View File

@@ -64,7 +64,8 @@
TerminateThread(m_threadHandle, 0); TerminateThread(m_threadHandle, 0);
#endif #endif
#if defined(LINUX) || defined(ANDROID) || defined(__APPLE__) || defined(POSIX) #if defined(LINUX) || defined(ANDROID) || defined(__APPLE__) || defined(POSIX)
pthread_join(m_thread, NULL); // Thread was created detached; pthread_join on a detached thread is undefined
// and causes SIGABRT when the pthread_t is no longer valid.
pthread_attr_destroy(&m_attributes); pthread_attr_destroy(&m_attributes);
#endif #endif
} }

View File

@@ -140,7 +140,7 @@ void SoundSystemAL::playAt( const SoundDesc& sound, float x, float y, float z, f
{ {
if (pitch < 0.01f) pitch = 1; if (pitch < 0.01f) pitch = 1;
LOGI("playing sound '%s' with volume/pitch: %f, %f @ %f, %f, %f\n", sound.name.c_str(), volume, pitch, x, y, z); //LOGI("playing sound '%s' with volume/pitch: %f, %f @ %f, %f, %f\n", sound.name.c_str(), volume, pitch, x, y, z);
ALuint bufferID; ALuint bufferID;
if (!getBufferId(sound, &bufferID)) { if (!getBufferId(sound, &bufferID)) {
@@ -151,7 +151,7 @@ void SoundSystemAL::playAt( const SoundDesc& sound, float x, float y, float z, f
} }
errIdString = "Get buffer"; errIdString = "Get buffer";
checkError(); checkError();
LOGI("playing sound %d - '%s' with volume/pitch: %f, %f @ %f, %f, %f\n", bufferID, sound.name.c_str(), volume, pitch, x, y, z); //LOGI("playing sound %d - '%s' with volume/pitch: %f, %f @ %f, %f, %f\n", bufferID, sound.name.c_str(), volume, pitch, x, y, z);
int sourceIndex; int sourceIndex;
errIdString = "Get free index"; errIdString = "Get free index";
@@ -232,12 +232,12 @@ bool SoundSystemAL::getBufferId(const SoundDesc& sound, ALuint* buf) {
: (sound.channels==2? AL_FORMAT_STEREO8 : AL_FORMAT_MONO8); : (sound.channels==2? AL_FORMAT_STEREO8 : AL_FORMAT_MONO8);
alBufferData(bufferID, format, sound.frames, sound.size, sound.frameRate); alBufferData(bufferID, format, sound.frames, sound.size, sound.frameRate);
LOGI("Creating %d (%p) from sound: '%s'\n", bufferID, sound.frames, sound.name.c_str()); //LOGI("Creating %d (%p) from sound: '%s'\n", bufferID, sound.frames, sound.name.c_str());
errIdString = "Buffer data"; errIdString = "Buffer data";
LOGI("Creating buffer with data: %d (%d), %p, %d, %d\n", format, sound.byteWidth, sound.frames, sound.size, sound.frameRate); //LOGI("Creating buffer with data: %d (%d), %p, %d, %d\n", format, sound.byteWidth, sound.frames, sound.size, sound.frameRate);
checkError(); checkError();
LOGI("Sound ch: %d, fmt: %d, frames: %p, len: %f, fr: %d, sz: %d, numfr: %d\n", sound.channels, format, sound.frames, sound.length(), sound.frameRate, sound.size, sound.numFrames); //LOGI("Sound ch: %d, fmt: %d, frames: %p, len: %f, fr: %d, sz: %d, numfr: %d\n", sound.channels, format, sound.frames, sound.length(), sound.frameRate, sound.size, sound.numFrames);
Buffer buffer; Buffer buffer;
@@ -248,6 +248,10 @@ bool SoundSystemAL::getBufferId(const SoundDesc& sound, ALuint* buf) {
_buffers.push_back(buffer); _buffers.push_back(buffer);
// @huge @attn @note @fix: The original data is free'd // @huge @attn @note @fix: The original data is free'd
// On PLATFORM_DESKTOP the PCM data lives in static arrays (not heap),
// so calling delete[] on them causes a debug-heap __debugbreak crash.
#if !defined(PLATFORM_DESKTOP)
sound.destroy(); sound.destroy();
#endif
return true; return true;
} }

View File

@@ -91,7 +91,7 @@ void SoundSystemSL::setListenerPos( float x, float y, float z )
return; return;
} }
SLVec3D pos = {1000.0f * x, 1000.0f * y, 1000.0f * z}; SLVec3D pos = {(SLint32)(1000.0f * x), (SLint32)(1000.0f * y), (SLint32)(1000.0f * z)};
SLresult res = (*listener)->SetLocationCartesian(listener, &pos); SLresult res = (*listener)->SetLocationCartesian(listener, &pos);
checkErr(res); checkErr(res);
} }
@@ -115,10 +115,10 @@ void SoundSystemSL::playAt( const SoundDesc& sound, float x, float y, float z, f
SLDataLocator_AndroidSimpleBufferQueue uri = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; SLDataLocator_AndroidSimpleBufferQueue uri = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM mime = { SLDataFormat_PCM mime = {
SL_DATAFORMAT_PCM, SL_DATAFORMAT_PCM,
sound.channels, (SLuint32)sound.channels,
sound.frameRate * 1000, (SLuint32)(sound.frameRate * 1000),
sound.byteWidth << 3, (SLuint32)(sound.byteWidth << 3),
sound.byteWidth << 3, (SLuint32)(sound.byteWidth << 3),
sound.channels==1? SL_SPEAKER_FRONT_CENTER : sound.channels==1? SL_SPEAKER_FRONT_CENTER :
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN SL_BYTEORDER_LITTLEENDIAN

View File

@@ -2236,6 +2236,6 @@ AdventureSettings::AdventureSettings()
noPvM(false), noPvM(false),
noMvP(false), noMvP(false),
immutableWorld(false), immutableWorld(false),
showNameTags(false) showNameTags(true)
{ {
} }