Compare commits
67 Commits
0.6.1-alph
...
754329fc49
| Author | SHA1 | Date | |
|---|---|---|---|
| 754329fc49 | |||
| 5385342272 | |||
| 0db3a547c7 | |||
| 94f4317b71 | |||
| bf2248063d | |||
| 13dcf593d8 | |||
| b547286e53 | |||
| ce5307aa30 | |||
| 85224c42b7 | |||
| 450f0d9ec2 | |||
| 12d5835711 | |||
| 969d6b3ee7 | |||
| b0de432339 | |||
| 6f7812293e | |||
| 37e28d0fcc | |||
| 954ec6e505 | |||
| b1cd6c6581 | |||
| 248e9cb69a | |||
| caedc293eb | |||
| 2e9a9b810c | |||
| ce4c3e9d93 | |||
| 470509ee52 | |||
| 0ea8b87970 | |||
| b4f54083dc | |||
| f17a11c670 | |||
| adb23d18c6 | |||
| 4b6039d8a4 | |||
| 1e908423d5 | |||
| 4bd3821ff6 | |||
| 28a49debcf | |||
| d2a5f4755c | |||
| 7f3af5c98a | |||
| d82d19be68 | |||
| 33590751c5 | |||
| a80d2ee847 | |||
| 8875342557 | |||
| 933ef9c988 | |||
| 09d28be195 | |||
| ffd9dda611 | |||
| 6ed2d40edc | |||
| ce6a987651 | |||
| 23cdc15285 | |||
| 904bf68cd6 | |||
| e529bd5d64 | |||
| 099b560273 | |||
| 2d70b68b73 | |||
| 01f78eabc7 | |||
|
|
99164a781d | ||
|
|
d25a04f154 | ||
|
|
3c71139a7c | ||
|
|
9991ba312d | ||
|
|
11d5551d02 | ||
|
|
d0939875fc | ||
| da1906f94b | |||
| 04f13ab4a7 | |||
| 2d17f9d152 | |||
| ae84705332 | |||
| 12b30c245a | |||
| 7345f68aee | |||
| 311e97bd77 | |||
| 6d43273b18 | |||
| 2fc323639a | |||
|
|
0c97ceb340 | ||
| 65d25748db | |||
| 8a53d3432d | |||
| 5311b134ac | |||
| 310ff754ee |
203
.gitignore
vendored
203
.gitignore
vendored
@@ -1,3 +1,202 @@
|
||||
# Build output
|
||||
build/
|
||||
linux-build/
|
||||
.cache/
|
||||
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/
|
||||
conan/
|
||||
|
||||
219
CMakeLists.txt
219
CMakeLists.txt
@@ -5,11 +5,11 @@ include(cmake/CPM.cmake)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||
|
||||
set(CMAKE_POLICY_VERSION_MINIMUM 3.10)
|
||||
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()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
CPMAddPackage("gh:madler/zlib@1.3.2")
|
||||
CPMAddPackage(
|
||||
NAME "libpng"
|
||||
@@ -44,8 +44,191 @@ CPMAddPackage(
|
||||
"GLFW_BUILD_DOCS OFF"
|
||||
"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/HttpClient.cpp"
|
||||
"src/platform/PngLoader.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/gamemode/*.cpp"
|
||||
@@ -129,18 +312,29 @@ endif()
|
||||
|
||||
|
||||
if(PLATFORM STREQUAL "PLATFORM_WIN32")
|
||||
list(APPEND SOURCES "src/AppPlatform_win32.cpp")
|
||||
list(APPEND CLIENT_SOURCES "src/AppPlatform_win32.cpp")
|
||||
endif()
|
||||
|
||||
if(PLATFORM STREQUAL "PLATFORM_GLFW")
|
||||
list(APPEND SOURCES "src/AppPlatform_glfw.cpp")
|
||||
list(APPEND CLIENT_SOURCES "src/AppPlatform_glfw.cpp")
|
||||
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}
|
||||
${SOURCES}
|
||||
${CLIENT_SOURCES}
|
||||
"glad/src/glad.c"
|
||||
)
|
||||
|
||||
#add_executable("${PROJECT_NAME}-server"
|
||||
# ${SERVER_SOURCES}
|
||||
#)
|
||||
|
||||
if(WIN32)
|
||||
set(EXTRA_LIBS "ws2_32")
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC "_CRT_SECURE_NO_WARNINGS")
|
||||
@@ -150,6 +344,7 @@ if(PLATFORM STREQUAL "PLATFORM_WIN32" OR PLATFORM STREQUAL "PLATFORM_GLFW")
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC "PLATFORM_DESKTOP")
|
||||
endif()
|
||||
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"${CMAKE_SOURCE_DIR}/glad/include/"
|
||||
"${CMAKE_SOURCE_DIR}/src"
|
||||
@@ -158,6 +353,16 @@ target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"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_link_libraries(${PROJECT_NAME} zlib png_shared alsoft.common OpenAL::OpenAL glfw ${EXTRA_LIBS})
|
||||
|
||||
|
||||
62
README.md
62
README.md
@@ -1,21 +1,73 @@
|
||||
# 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] Compile for Linux
|
||||
- [ ] Compile for android aarch64
|
||||
- [x] Compile for android aarch64
|
||||
- [x] Touch control improvements
|
||||
- [ ] Screen fixes
|
||||
- [ ] Rewrite platform logic
|
||||
- [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
|
||||
|
||||
## CMake
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake .. -B .
|
||||
make -j4
|
||||
```
|
||||
or
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake --build . --config Release -j 10
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
1. Download **Android NDK r14b**:
|
||||
http://dl.google.com/android/repository/android-ndk-r14b-windows-x86_64.zip
|
||||
|
||||
2. Extract it to the root of your `C:` drive so the path becomes:
|
||||
|
||||
```
|
||||
C:\android-ndk-r14b
|
||||
```
|
||||
|
||||
3. Run the build script:
|
||||
|
||||
```powershell
|
||||
# Full build (NDK + Java + APK + install)
|
||||
.\build.ps1
|
||||
|
||||
# Skip C++ compilation (Java/assets changed only)
|
||||
.\build.ps1 -NoCpp
|
||||
|
||||
# Skip Java compilation (C++ changed only)
|
||||
.\build.ps1 -NoJava
|
||||
|
||||
# Only repackage + install (no compilation)
|
||||
.\build.ps1 -NoBuild
|
||||
```
|
||||
302
build.ps1
Normal file
302
build.ps1
Normal 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
|
||||
BIN
data/images/gui/logo/github.png
Normal file
BIN
data/images/gui/logo/github.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -144,6 +144,16 @@ options.fov.max=Quake Pro
|
||||
options.gamma=Brightness
|
||||
options.gamma.min=Moody
|
||||
options.gamma.max=Bright
|
||||
options.group.mojang=Login
|
||||
options.group.game=Game
|
||||
options.group.controls=Controls
|
||||
options.group.graphics=Graphics
|
||||
options.group.tweaks=Tweaks
|
||||
options.sprint=Sprint
|
||||
options.barontop=HUD above inventory
|
||||
options.autojump=Auto Jump
|
||||
options.thirdperson=Third Person
|
||||
options.servervisible=Server Visible
|
||||
options.sensitivity=Sensitivity
|
||||
options.sensitivity.min=*yawn*
|
||||
options.sensitivity.max=HYPERSPEED!!!
|
||||
@@ -156,6 +166,8 @@ options.viewBobbing=View Bobbing
|
||||
options.ao=Smooth Lighting
|
||||
options.anaglyph=3D Anaglyph
|
||||
options.framerateLimit=Performance
|
||||
options.limitFramerate=Limit Framerate
|
||||
options.vsync=VSync
|
||||
options.difficulty=Difficulty
|
||||
options.difficulty.peaceful=Peaceful
|
||||
options.difficulty.easy=Easy
|
||||
@@ -170,6 +182,7 @@ options.guiScale.auto=Auto
|
||||
options.guiScale.small=Small
|
||||
options.guiScale.normal=Normal
|
||||
options.guiScale.large=Large
|
||||
options.guiScale.larger=Larger
|
||||
options.advancedOpengl=Advanced OpenGL
|
||||
options.renderClouds=Clouds
|
||||
options.farWarning1=A 64 bit Java installation is recommended
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mojang.minecraftpe"
|
||||
android:versionCode="6006"
|
||||
android:versionName="0.6.0"
|
||||
android:installLocation="preferExternal">
|
||||
|
||||
<!-- This is the platform API where NativeActivity was introduced. -->
|
||||
<uses-sdk android:minSdkVersion="9"
|
||||
android:targetSdkVersion="9" />
|
||||
|
||||
<!-- uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/ -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<application android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
>
|
||||
|
||||
<activity android:name="com.mojang.minecraftpe.MainActivity"
|
||||
android:label="@string/app_name_short"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:screenOrientation="landscape"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTop">
|
||||
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="minecraftpe" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.mojang.minecraftpe.MainMenuOptionsActivity"></activity>
|
||||
|
||||
<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"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mojang.minecraftpe"
|
||||
android:versionCode="6010"
|
||||
android:versionName="0.6.1-alpha-0.0.3"
|
||||
android:installLocation="preferExternal">
|
||||
|
||||
<!-- This is the platform API where NativeActivity was introduced. -->
|
||||
<uses-sdk android:minSdkVersion="24"
|
||||
android:targetSdkVersion="24" />
|
||||
|
||||
<!-- uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/ -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<application android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
>
|
||||
|
||||
<activity android:name="com.mojang.minecraftpe.MainActivity"
|
||||
android:label="@string/app_name_short"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:screenOrientation="landscape"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTop">
|
||||
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="minecraftpe" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.mojang.minecraftpe.MainMenuOptionsActivity"></activity>
|
||||
|
||||
<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"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -170,6 +170,7 @@ options.guiScale.auto=Auto
|
||||
options.guiScale.small=Small
|
||||
options.guiScale.normal=Normal
|
||||
options.guiScale.large=Large
|
||||
options.guiScale.larger=Larger
|
||||
options.advancedOpengl=Advanced OpenGL
|
||||
options.renderClouds=Clouds
|
||||
options.farWarning1=A 64 bit Java installation is recommended
|
||||
|
||||
@@ -4,7 +4,7 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := minecraftpe
|
||||
LOCAL_SRC_FILES := ../../../src/main.cpp \
|
||||
../../../src/main_android.cpp \
|
||||
../../../src/main_android_java.cpp \
|
||||
../../../src/platform/audio/SoundSystemSL.cpp \
|
||||
../../../src/platform/input/Controller.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/ScrollingPane.cpp \
|
||||
../../../src/client/gui/components/Slider.cpp \
|
||||
../../../src/client/gui/components/TextBox.cpp \
|
||||
../../../src/client/gui/components/SmallButton.cpp \
|
||||
../../../src/client/gui/Font.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/ArmorScreen.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/ChestScreen.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/JoinGameScreen.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/RenameMPLevelScreen.cpp \
|
||||
../../../src/client/gui/screens/SelectWorldScreen.cpp \
|
||||
../../../src/client/gui/screens/StartMenuScreen.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/TouchJoinGameScreen.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/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 $(LOCAL_CFLAGS)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
APP_PLATFORM := android-9
|
||||
APP_STL := stlport_static
|
||||
APP_PLATFORM := android-21
|
||||
APP_STL := gnustl_static
|
||||
APP_OPTIM := release
|
||||
APP_ABI := armeabi-v7a
|
||||
APP_ABI := arm64-v8a
|
||||
#APP_ABI := armeabi-v7a x86
|
||||
|
||||
@@ -468,17 +468,16 @@ public class MainActivity extends NativeActivity {
|
||||
|
||||
_userInputStatus = 1;
|
||||
InputMethodManager inputManager = (InputMethodManager)getSystemService("input_method");
|
||||
boolean result = inputManager.showSoftInput(this.getCurrentFocus(), InputMethodManager.SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
protected void onStart() {
|
||||
//System.out.println("onStart");
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
protected void onResume() {
|
||||
//System.out.println("onResume");
|
||||
super.onResume();
|
||||
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 onPause() {
|
||||
|
||||
@@ -1,44 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mojang.minecraftpe"
|
||||
android:versionCode="4000"
|
||||
android:versionName="0.4.0"
|
||||
>
|
||||
<!-- android:installLocation="preferExternal" -->
|
||||
|
||||
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="7"/>
|
||||
|
||||
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="true"/>
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<application android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
>
|
||||
|
||||
<activity android:name="com.mojang.minecraftpe.Minecraft_Market"
|
||||
android:label="@string/app_name_short"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:screenOrientation="landscape"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="minecraftpe" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.mojang.minecraftpe.MainMenuOptionsActivity"></activity>
|
||||
|
||||
<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"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mojang.minecraftpe"
|
||||
android:versionCode="6010"
|
||||
android:versionName="0.6.1-alpha-0.0.3">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="24"
|
||||
android:targetSdkVersion="28"/>
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen.multitouch"
|
||||
android:required="true"/>
|
||||
|
||||
<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.VIBRATE"/>
|
||||
|
||||
<application
|
||||
android:icon="@drawable/icon"
|
||||
android:label="@string/app_name"
|
||||
android:hardwareAccelerated="true"
|
||||
android:extractNativeLibs="true"
|
||||
android:requestLegacyExternalStorage="true">
|
||||
|
||||
<activity
|
||||
android:name="com.mojang.minecraftpe.Minecraft_Market"
|
||||
android:label="@string/app_name_short"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
|
||||
android:screenOrientation="landscape"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:exported="true">
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.lib_name"
|
||||
android:value="minecraftpe"/>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.mojang.minecraftpe.MainActivity"
|
||||
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"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -31,6 +31,8 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.graphics.Bitmap.CompressFormat;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.AudioManager;
|
||||
@@ -40,7 +42,6 @@ import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
@@ -55,9 +56,12 @@ import com.mojang.minecraftpe.sound.SoundPlayer;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
/** Called when the activity is first created. */
|
||||
|
||||
private static final int PERMISSION_REQUEST_CODE = 123;
|
||||
|
||||
private GLView _glView;
|
||||
public float invScale = 1.0f;// / 1.5f;
|
||||
private int _screenWidth = 0;
|
||||
private int _screenHeight = 0;
|
||||
|
||||
Vector<MotionEvent> _touchEvents = new Vector<MotionEvent>();
|
||||
Vector<KeyEvent> _keyEvents = new Vector<KeyEvent>();
|
||||
@@ -67,8 +71,13 @@ public class MainActivity extends Activity {
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
super.onCreate(savedInstanceState);
|
||||
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.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
|
||||
@@ -102,18 +111,68 @@ public class MainActivity extends Activity {
|
||||
setContentView(_glView);
|
||||
|
||||
_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 private boolean _isPowerVr = false;
|
||||
public void setIsPowerVR(boolean status) { MainActivity._isPowerVr = status; }
|
||||
static public boolean isPowerVR() { return _isPowerVr; }
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void vibrate(int milliSeconds) {
|
||||
Vibrator v = (Vibrator)this.getSystemService(VIBRATOR_SERVICE);
|
||||
v.vibrate(milliSeconds);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void createAlertDialog(boolean hasOkButton, boolean hasCancelButton, boolean preventBackKey) {
|
||||
@@ -144,9 +203,16 @@ public class MainActivity extends Activity {
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
// TODO Auto-generated method stub
|
||||
//System.out.println("Focus has changed. Has Focus? " + 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
|
||||
@@ -184,9 +250,12 @@ public class MainActivity extends Activity {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN)
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -347,22 +416,15 @@ public class MainActivity extends Activity {
|
||||
}
|
||||
|
||||
public int getScreenWidth() {
|
||||
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
int out = Math.max(display.getWidth(), display.getHeight());
|
||||
//System.out.println("getwidth: " + out);
|
||||
return out;
|
||||
return _screenWidth;
|
||||
}
|
||||
|
||||
public int getScreenHeight() {
|
||||
Display display = ((WindowManager)this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
int out = Math.min(display.getWidth(), display.getHeight());
|
||||
//System.out.println("getheight: " + out);
|
||||
return out;
|
||||
return _screenHeight;
|
||||
}
|
||||
|
||||
public float getPixelsPerMillimeter() {
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
android.util.DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||
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.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
MainActivity.this.mDialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
|
||||
//MainActivity.this.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
|
||||
MainActivity.this.mDialog.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
//MainActivity.this.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -516,6 +578,20 @@ public class MainActivity extends Activity {
|
||||
|
||||
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) {
|
||||
if (id == 0) return android.os.Build.MODEL;
|
||||
return null;
|
||||
@@ -604,10 +680,11 @@ public class MainActivity extends Activity {
|
||||
//
|
||||
native void nativeRegisterThis();
|
||||
native void nativeUnregisterThis();
|
||||
native static void nativeOnCreate();
|
||||
native static void nativeOnCreate(int screenWidth, int screenHeight);
|
||||
native static void nativeOnDestroy();
|
||||
native static void nativeOnKeyDown(int key);
|
||||
native static void nativeOnKeyUp(int key);
|
||||
native static void nativeTextChar(int unicodeChar);
|
||||
native static boolean nativeHandleBack(boolean isDown);
|
||||
native static void nativeMouseDown(int pointerId, int buttonId, float x, float y);
|
||||
native static void nativeMouseUp(int pointerId, int buttonId, float x, float y);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 2.8.7)
|
||||
cmake_minimum_required(VERSION 3.5.0)
|
||||
find_package (Threads)
|
||||
include_directories("${PROJECT_SOURCE_DIR}/../lib_projects/raknet/jni/RaknetSources")
|
||||
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/FurnaceTileEntity.cpp
|
||||
../../src/world/phys/HitResult.cpp)
|
||||
message(${CMAKE_LIBRARY_ARCHITECTURE})
|
||||
|
||||
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
|
||||
"../../src/"
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <stdio.h> // RAKNET_DEBUG_PRINTF
|
||||
#include "RakAssert.h"
|
||||
#if defined(ANDROID)
|
||||
#include <asm/io.h>
|
||||
// <asm/io.h> not needed and unavailable on arm64
|
||||
#elif defined(_WIN32) || defined(__CYGWIN__)
|
||||
#include <io.h>
|
||||
|
||||
|
||||
@@ -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
|
||||
#endif
|
||||
// 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
|
||||
{
|
||||
|
||||
@@ -71,6 +71,7 @@ public:
|
||||
|
||||
virtual void saveScreenshot(const std::string& filename, int glWidth, int glHeight) {}
|
||||
virtual TextureData loadTexture(const std::string& filename_, bool textureFolder) { return TextureData(); }
|
||||
virtual TextureData loadTextureFromMemory(const unsigned char* data, size_t size) { return TextureData(); }
|
||||
|
||||
virtual void playSound(const std::string& fn, float volume, float pitch) {}
|
||||
|
||||
@@ -96,9 +97,6 @@ public:
|
||||
virtual std::string getDateString(int s) { return ""; }
|
||||
//virtual void createUserInputScreen(const char* types) {}
|
||||
|
||||
virtual int checkLicense() { return 0; }
|
||||
virtual bool hasBuyButtonWhenInvalidLicense() { return false; }
|
||||
|
||||
virtual void uploadPlatformDependentData(int id, void* data) {}
|
||||
virtual BinaryBlob readAssetFile(const std::string& filename) { return BinaryBlob(); }
|
||||
virtual void _tick() {}
|
||||
@@ -117,7 +115,7 @@ public:
|
||||
virtual bool isSuperFast() = 0;
|
||||
#endif
|
||||
|
||||
virtual void buyGame() {}
|
||||
virtual void openURL(const std::string& url) {}
|
||||
|
||||
virtual void finish() {}
|
||||
|
||||
|
||||
@@ -68,9 +68,6 @@ public:
|
||||
|
||||
_methodGetDateString(0),
|
||||
|
||||
_methodCheckLicense(0),
|
||||
_methodHasBuyButton(0),
|
||||
_methodBuyGame(0),
|
||||
_methodVibrate(0),
|
||||
_methodSupportsTouchscreen(0),
|
||||
_methodSetIsPowerVR(0),
|
||||
@@ -104,6 +101,7 @@ public:
|
||||
|
||||
int getScreenWidth() { return _screenWidth; }
|
||||
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)
|
||||
// Somewhere between calling this, and calling the AppPlatform methods,
|
||||
@@ -146,10 +144,6 @@ public:
|
||||
|
||||
_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");
|
||||
_methodSupportsTouchscreen = env->GetMethodID( _activityClass, "supportsTouchscreen", "()Z");
|
||||
_methodSetIsPowerVR = env->GetMethodID( _activityClass, "setIsPowerVR", "(Z)V");
|
||||
@@ -157,6 +151,8 @@ public:
|
||||
|
||||
_methodGetPixelsPerMillimeter = env->GetMethodID( _activityClass, "getPixelsPerMillimeter", "()F");
|
||||
_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"));
|
||||
_classContext = (jclass)env->NewGlobalRef(env->FindClass("android/content/Context"));
|
||||
@@ -192,14 +188,20 @@ public:
|
||||
// be rewritten later on anyway
|
||||
int initConsts() {
|
||||
|
||||
LOGI("initConsts: start\n");
|
||||
JVMAttacher ta(_vm);
|
||||
JNIEnv* env = ta.getEnv();
|
||||
|
||||
LOGI("initConsts: getting method IDs\n");
|
||||
jmethodID fWidth = env->GetMethodID( _activityClass, "getScreenWidth", "()I");
|
||||
LOGI("initConsts: got fWidth=%p\n", fWidth);
|
||||
jmethodID fHeight = env->GetMethodID( _activityClass, "getScreenHeight", "()I");
|
||||
LOGI("initConsts: got fHeight=%p, calling getScreenWidth\n", fHeight);
|
||||
|
||||
_screenWidth = env->CallIntMethod(instance, fWidth);
|
||||
LOGI("initConsts: screenWidth=%d, calling getScreenHeight\n", _screenWidth);
|
||||
_screenHeight = env->CallIntMethod(instance, fHeight);
|
||||
LOGI("initConsts: screenHeight=%d, done\n", _screenHeight);
|
||||
}
|
||||
|
||||
void tick() {
|
||||
@@ -376,8 +378,9 @@ public:
|
||||
JVMAttacher ta(_vm);
|
||||
JNIEnv* env = ta.getEnv();
|
||||
|
||||
std::string path = textureFolder ? "images/" + filename : filename;
|
||||
jintArray arr = (jintArray)env->CallObjectMethod(
|
||||
instance, _getImageData, env->NewStringUTF(filename.c_str()));
|
||||
instance, _getImageData, env->NewStringUTF(path.c_str()));
|
||||
|
||||
if (!arr)
|
||||
return TextureData();
|
||||
@@ -464,37 +467,15 @@ public:
|
||||
env->ReleaseStringUTFChars(stringVar, str);
|
||||
return out;
|
||||
}
|
||||
|
||||
int checkLicense() {
|
||||
if (!_isInited) return -2;
|
||||
if (!_methodCheckLicense) return -2;
|
||||
|
||||
JVMAttacher ta(_vm);
|
||||
JNIEnv* env = ta.getEnv();
|
||||
|
||||
return env->CallIntMethod(instance, _methodCheckLicense);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Opens a webpage using an Android intent. Called from native code.
|
||||
virtual void openURL(const std::string& url) {
|
||||
if (!_isInited || !_methodOpenURL) return;
|
||||
JVMAttacher ta(_vm);
|
||||
JNIEnv* env = ta.getEnv();
|
||||
jstring jurl = env->NewStringUTF(url.c_str());
|
||||
env->CallVoidMethod(instance, _methodOpenURL, jurl);
|
||||
env->DeleteLocalRef(jurl);
|
||||
}
|
||||
virtual void finish() {
|
||||
if (!_isInited) return;
|
||||
if (!_methodFinish) return;
|
||||
@@ -636,10 +617,6 @@ private:
|
||||
|
||||
jmethodID _methodGetDateString;
|
||||
|
||||
jmethodID _methodCheckLicense;
|
||||
jmethodID _methodHasBuyButton;
|
||||
jmethodID _methodBuyGame;
|
||||
|
||||
jmethodID _getScreenWidth;
|
||||
jmethodID _getScreenHeight;
|
||||
jmethodID _methodGetPixelsPerMillimeter;
|
||||
@@ -649,6 +626,7 @@ private:
|
||||
jmethodID _methodIsNetworkEnabled;
|
||||
|
||||
jmethodID _methodGetPlatformStringVar;
|
||||
jmethodID _methodOpenURL; // new JNI method for launching browser
|
||||
|
||||
jclass _classWindow;
|
||||
jclass _classContext;
|
||||
|
||||
@@ -1,5 +1,74 @@
|
||||
#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() {
|
||||
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include "AppPlatform.h"
|
||||
#include "platform/log.h"
|
||||
#include "platform/HttpClient.h"
|
||||
#include "platform/PngLoader.h"
|
||||
#include "client/renderer/gles.h"
|
||||
#include "world/level/storage/FolderMethods.h"
|
||||
#include <png.h>
|
||||
@@ -10,6 +12,13 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <ctime>
|
||||
#include "util/StringUtils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
|
||||
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);
|
||||
@@ -49,10 +58,19 @@ public:
|
||||
|
||||
TextureData loadTexture(const std::string& filename_, bool textureFolder)
|
||||
{
|
||||
// Support fetching PNG textures via HTTP/HTTPS (for skins, etc)
|
||||
if (Util::startsWith(filename_, "http://") || Util::startsWith(filename_, "https://")) {
|
||||
std::vector<unsigned char> body;
|
||||
if (HttpClient::download(filename_, body) && !body.empty()) {
|
||||
return loadTextureFromMemory(body.data(), body.size());
|
||||
}
|
||||
return TextureData();
|
||||
}
|
||||
|
||||
TextureData out;
|
||||
|
||||
std::string filename = textureFolder? "data/images/" + filename_
|
||||
: filename_;
|
||||
: filename_;
|
||||
std::ifstream source(filename.c_str(), std::ios::binary);
|
||||
|
||||
if (source) {
|
||||
@@ -101,18 +119,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::string getDateString(int s) {
|
||||
std::stringstream ss;
|
||||
ss << s << " s (UTC)";
|
||||
return ss.str();
|
||||
TextureData loadTextureFromMemory(const unsigned char* data, size_t size) override {
|
||||
return loadPngFromMemory(data, size);
|
||||
}
|
||||
|
||||
virtual int checkLicense() {
|
||||
static int _z = 0;//20;
|
||||
_z--;
|
||||
if (_z < 0) return 0;
|
||||
//if (_z < 0) return 107;
|
||||
return -2;
|
||||
virtual std::string getDateString(int s) override {
|
||||
time_t tm = s;
|
||||
|
||||
char mbstr[100];
|
||||
std::strftime(mbstr, sizeof(mbstr), "%F %T", std::localtime(&tm));
|
||||
|
||||
return std::string(mbstr);
|
||||
}
|
||||
|
||||
virtual int getScreenWidth() { return 854; };
|
||||
@@ -121,9 +138,20 @@ public:
|
||||
virtual float getPixelsPerMillimeter();
|
||||
|
||||
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:
|
||||
};
|
||||
|
||||
void* winGLLoader(const char* name);
|
||||
void glPatchDesktopCompat();
|
||||
|
||||
#endif /*APPPLATFORM_GLFW_H__*/
|
||||
|
||||
@@ -41,17 +41,6 @@ public:
|
||||
|
||||
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 getScreenHeight();
|
||||
virtual float getPixelsPerMillimeter();
|
||||
|
||||
@@ -175,10 +175,6 @@ BinaryBlob AppPlatform_iOS::readAssetFile(const std::string& filename_) {
|
||||
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) {
|
||||
|
||||
NSDate* date = [NSDate dateWithTimeIntervalSince1970:s];
|
||||
|
||||
@@ -14,4 +14,3 @@ float AppPlatform_win32::getPixelsPerMillimeter() {
|
||||
}
|
||||
|
||||
bool AppPlatform_win32::supportsTouchscreen() { return true; }
|
||||
bool AppPlatform_win32::hasBuyButtonWhenInvalidLicense() { return true; }
|
||||
|
||||
@@ -3,12 +3,17 @@
|
||||
|
||||
#include "AppPlatform.h"
|
||||
#include "platform/log.h"
|
||||
#include "platform/HttpClient.h"
|
||||
#include "platform/PngLoader.h"
|
||||
#include "client/renderer/gles.h"
|
||||
#include "world/level/storage/FolderMethods.h"
|
||||
#include "util/StringUtils.h"
|
||||
#include <png.h>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
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);
|
||||
@@ -48,10 +53,19 @@ public:
|
||||
|
||||
TextureData loadTexture(const std::string& filename_, bool textureFolder)
|
||||
{
|
||||
// Support fetching PNG textures via HTTP/HTTPS (for skins, etc).
|
||||
if (Util::startsWith(filename_, "http://") || Util::startsWith(filename_, "https://")) {
|
||||
std::vector<unsigned char> body;
|
||||
if (HttpClient::download(filename_, body) && !body.empty()) {
|
||||
return loadTextureFromMemory(body.data(), body.size());
|
||||
}
|
||||
return TextureData();
|
||||
}
|
||||
|
||||
TextureData out;
|
||||
|
||||
std::string filename = textureFolder? "data/images/" + filename_
|
||||
: filename_;
|
||||
: filename_;
|
||||
std::ifstream source(filename.c_str(), std::ios::binary);
|
||||
|
||||
if (source) {
|
||||
@@ -100,18 +114,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::string getDateString(int s) {
|
||||
std::stringstream ss;
|
||||
ss << s << " s (UTC)";
|
||||
return ss.str();
|
||||
TextureData loadTextureFromMemory(const unsigned char* data, size_t size) override {
|
||||
return loadPngFromMemory(data, size);
|
||||
}
|
||||
time_t tm = s;
|
||||
|
||||
virtual int checkLicense() {
|
||||
static int _z = 0;//20;
|
||||
_z--;
|
||||
if (_z < 0) return 0;
|
||||
//if (_z < 0) return 107;
|
||||
return -2;
|
||||
char mbstr[100];
|
||||
std::strftime(mbstr, sizeof(mbstr), "%F %T", std::localtime(&tm));
|
||||
|
||||
return std::string(mbstr);
|
||||
}
|
||||
|
||||
virtual int getScreenWidth();
|
||||
@@ -120,7 +131,10 @@ public:
|
||||
virtual float getPixelsPerMillimeter();
|
||||
|
||||
virtual bool supportsTouchscreen();
|
||||
virtual bool hasBuyButtonWhenInvalidLicense();
|
||||
|
||||
virtual void openURL(const std::string& url) {
|
||||
ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//#include "world/level/storage/FolderMethods.h"
|
||||
#ifndef STANDALONE_SERVER
|
||||
#include "client/gui/screens/StartMenuScreen.h"
|
||||
#include "client/gui/screens/UsernameScreen.h"
|
||||
#endif
|
||||
#include "client/player/LocalPlayer.h"
|
||||
#ifndef STANDALONE_SERVER
|
||||
@@ -110,6 +111,9 @@ void NinecraftApp::init()
|
||||
#ifndef STANDALONE_SERVER
|
||||
LOGI("This: %p\n", this);
|
||||
screenChooser.setScreen(SCREEN_STARTMENU);
|
||||
if (options.username.empty()) {
|
||||
setScreen(new UsernameScreen());
|
||||
}
|
||||
#else
|
||||
user->name = "Server";
|
||||
hostMultiplayer();
|
||||
|
||||
@@ -4,7 +4,13 @@ namespace Common {
|
||||
|
||||
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 64‑bit targets
|
||||
#if defined(ANDROID) && (defined(__aarch64__) || defined(__x86_64__))
|
||||
result += " (64-bit port)";
|
||||
#endif
|
||||
result += " alpha";
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#include "Minecraft.h"
|
||||
#include "client/player/input/IBuildInput.h"
|
||||
#include "platform/input/Keyboard.h"
|
||||
#include "world/item/Item.h"
|
||||
#include "world/item/ItemInstance.h"
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(APPLE_DEMO_PROMOTION)
|
||||
#define NO_NETWORK
|
||||
@@ -8,7 +13,6 @@
|
||||
#if defined(RPI)
|
||||
#define CREATORMODE
|
||||
#endif
|
||||
|
||||
#include "../network/RakNetInstance.h"
|
||||
#include "../network/ClientSideNetworkHandler.h"
|
||||
#include "../network/ServerSideNetworkHandler.h"
|
||||
@@ -31,6 +35,7 @@
|
||||
#include "gui/Screen.h"
|
||||
#include "gui/Font.h"
|
||||
#include "gui/screens/RenameMPLevelScreen.h"
|
||||
#include "gui/screens/ConsoleScreen.h"
|
||||
#include "sound/SoundEngine.h"
|
||||
#endif
|
||||
#include "../platform/CThread.h"
|
||||
@@ -55,6 +60,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
#include "renderer/Chunk.h"
|
||||
#include "player/input/MouseTurnInput.h"
|
||||
#include "../world/entity/MobFactory.h"
|
||||
#include "../world/level/MobSpawner.h"
|
||||
@@ -111,7 +117,7 @@ static void checkGlError(const char* tag) {
|
||||
}
|
||||
#endif /*GLDEBUG*/
|
||||
}
|
||||
|
||||
#include <fstream>
|
||||
/*static*/
|
||||
const char* Minecraft::progressMessages[] = {
|
||||
"Locating server",
|
||||
@@ -449,20 +455,21 @@ void Minecraft::update() {
|
||||
// }
|
||||
//}
|
||||
|
||||
if (pause && level != NULL) {
|
||||
float lastA = timer.a;
|
||||
timer.advanceTime();
|
||||
timer.a = lastA;
|
||||
} else {
|
||||
// If we're paused (local world / invisible server), freeze gameplay and
|
||||
// networking and only keep UI responsive.
|
||||
bool freezeGame = pause;
|
||||
|
||||
if (!freezeGame) {
|
||||
timer.advanceTime();
|
||||
}
|
||||
|
||||
if (raknetInstance) {
|
||||
if (raknetInstance && !freezeGame) {
|
||||
raknetInstance->runEvents(netCallback);
|
||||
}
|
||||
|
||||
TIMER_PUSH("tick");
|
||||
int toTick = timer.ticks;
|
||||
int toTick = freezeGame ? 1 : timer.ticks;
|
||||
if (!freezeGame) timer.ticks = 0;
|
||||
for (int i = 0; i < toTick; ++i, ++ticks)
|
||||
tick(i, toTick-1);
|
||||
|
||||
@@ -490,15 +497,14 @@ void Minecraft::update() {
|
||||
checkGlError("Update finished");
|
||||
|
||||
if (options.renderDebug) {
|
||||
#ifndef PLATFORM_DESKTOP
|
||||
if (!PerfTimer::enabled) {
|
||||
PerfTimer::reset();
|
||||
PerfTimer::enabled = true;
|
||||
}
|
||||
|
||||
//TIMER_PUSH("debugfps");
|
||||
_perfRenderer->renderFpsMeter(1);
|
||||
checkGlError("render debug");
|
||||
//TIMER_POP();
|
||||
#endif
|
||||
} else {
|
||||
PerfTimer::enabled = false;
|
||||
}
|
||||
@@ -588,7 +594,9 @@ void Minecraft::tick(int nTick, int maxTick) {
|
||||
#endif
|
||||
}
|
||||
TIMER_POP_PUSH("particles");
|
||||
particleEngine->tick();
|
||||
if (!pause) {
|
||||
particleEngine->tick();
|
||||
}
|
||||
if (screen) {
|
||||
screenMutex = true;
|
||||
screen->tick();
|
||||
@@ -722,13 +730,29 @@ void Minecraft::tickInput() {
|
||||
}
|
||||
#endif
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
if (key == Keyboard::KEY_LEFT_CTRL) {
|
||||
player->setSprinting(true);
|
||||
}
|
||||
|
||||
if (key == Keyboard::KEY_E) {
|
||||
screenChooser.setScreen(SCREEN_BLOCKSELECTION);
|
||||
}
|
||||
|
||||
if (!screen && key == Keyboard::KEY_T && level) {
|
||||
setScreen(new ConsoleScreen());
|
||||
}
|
||||
|
||||
if (!screen && key == Keyboard::KEY_O || key == 250) {
|
||||
releaseMouse();
|
||||
}
|
||||
|
||||
if (key == Keyboard::KEY_F)
|
||||
options.viewDistance = (options.viewDistance + 1) % 4;
|
||||
|
||||
if (key == Keyboard::KEY_F3) {
|
||||
options.renderDebug = !options.renderDebug;
|
||||
}
|
||||
|
||||
if (key == Keyboard::KEY_F5) {
|
||||
options.thirdPersonView = !options.thirdPersonView;
|
||||
/*
|
||||
@@ -737,31 +761,7 @@ void Minecraft::tickInput() {
|
||||
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
|
||||
#if defined(WIN32)
|
||||
if (key == Keyboard::KEY_F) {
|
||||
options.isFlying = !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)
|
||||
options.viewDistance = (options.viewDistance + 1) % 4;
|
||||
@@ -834,9 +834,6 @@ void Minecraft::tickInput() {
|
||||
if (player->inventory->getItem(i))
|
||||
player->inventory->dropSlot(i, false);
|
||||
}
|
||||
if (key == Keyboard::KEY_F3) {
|
||||
options.renderDebug = !options.renderDebug;
|
||||
}
|
||||
if (key == Keyboard::KEY_M) {
|
||||
options.difficulty = (options.difficulty == Difficulty::PEACEFUL)?
|
||||
Difficulty::NORMAL : Difficulty::PEACEFUL;
|
||||
@@ -879,31 +876,44 @@ void Minecraft::tickInput() {
|
||||
|
||||
static bool prevMouseDownLeft = false;
|
||||
|
||||
// Destroy and attack is on same button
|
||||
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
|
||||
auto baiFlags = BuildActionIntention::BAI_REMOVE | BuildActionIntention::BAI_ATTACK;
|
||||
|
||||
if (!prevMouseDownLeft) baiFlags |= BuildActionIntention::BAI_FIRSTREMOVE;
|
||||
|
||||
BuildActionIntention bai(baiFlags);
|
||||
handleBuildAction(&bai);
|
||||
if (Mouse::getButtonState(MouseAction::ACTION_LEFT) == 0) {
|
||||
gameMode->stopDestroyBlock();
|
||||
}
|
||||
|
||||
prevMouseDownLeft = Mouse::isButtonDown(MouseAction::ACTION_LEFT);
|
||||
|
||||
static int buildHoldTicks = 0;
|
||||
|
||||
// Build and use/interact is on same button
|
||||
// USPESHNO spizheno
|
||||
if (Mouse::isButtonDown(MouseAction::ACTION_RIGHT)) {
|
||||
if (buildHoldTicks >= 5) buildHoldTicks = 0;
|
||||
|
||||
if (++buildHoldTicks == 1) {
|
||||
BuildActionIntention bai(BuildActionIntention::BAI_BUILD | BuildActionIntention::BAI_INTERACT);
|
||||
if (useTouchscreen()) {
|
||||
// Touch: gesture recognizer classifies the action type (turn/destroy/build)
|
||||
BuildActionIntention bai;
|
||||
if (inputHolder && inputHolder->getBuildInput()->tickBuild(player, &bai)) {
|
||||
handleBuildAction(&bai);
|
||||
}
|
||||
} else {
|
||||
buildHoldTicks = 0;
|
||||
// Desktop: left mouse = destroy/attack
|
||||
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
|
||||
auto baiFlags = BuildActionIntention::BAI_REMOVE | BuildActionIntention::BAI_ATTACK;
|
||||
|
||||
if (!prevMouseDownLeft) baiFlags |= BuildActionIntention::BAI_FIRSTREMOVE;
|
||||
|
||||
BuildActionIntention bai(baiFlags);
|
||||
handleBuildAction(&bai);
|
||||
}
|
||||
|
||||
prevMouseDownLeft = Mouse::isButtonDown(MouseAction::ACTION_LEFT);
|
||||
|
||||
// Build and use/interact is on same button
|
||||
// USPESHNO spizheno
|
||||
static int buildHoldTicks = 0;
|
||||
if (Mouse::isButtonDown(MouseAction::ACTION_RIGHT)) {
|
||||
BuildActionIntention bai(BuildActionIntention::BAI_BUILD | BuildActionIntention::BAI_INTERACT);
|
||||
handleBuildAction(&bai);
|
||||
if (buildHoldTicks >= 5) buildHoldTicks = 0;
|
||||
|
||||
if (++buildHoldTicks == 1) {
|
||||
BuildActionIntention bai(BuildActionIntention::BAI_BUILD | BuildActionIntention::BAI_INTERACT);
|
||||
handleBuildAction(&bai);
|
||||
}
|
||||
} else {
|
||||
buildHoldTicks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lastTickTime = getTimeMs();
|
||||
@@ -1019,6 +1029,17 @@ bool Minecraft::isOnline()
|
||||
}
|
||||
|
||||
void Minecraft::pauseGame(bool isBackPaused) {
|
||||
// Only freeze gameplay when running a local server and it is not accepting
|
||||
// incoming connections (invisible server), which includes typical single-
|
||||
// player/lobby mode. If the server is visible, the game should keep ticking.
|
||||
bool canFreeze = false;
|
||||
if (raknetInstance && raknetInstance->isServer() && netCallback) {
|
||||
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) netCallback;
|
||||
if (!ss->allowsIncomingConnections())
|
||||
canFreeze = true;
|
||||
}
|
||||
pause = canFreeze;
|
||||
|
||||
#ifndef STANDALONE_SERVER
|
||||
if (screen != NULL) return;
|
||||
screenChooser.setScreen(isBackPaused? SCREEN_PAUSEPREV : SCREEN_PAUSE);
|
||||
@@ -1071,6 +1092,8 @@ void Minecraft::setScreen( Screen* screen )
|
||||
|
||||
//noRender = false;
|
||||
} else {
|
||||
// Closing a screen and returning to the game should unpause.
|
||||
pause = false;
|
||||
grabMouse();
|
||||
}
|
||||
#endif
|
||||
@@ -1113,6 +1136,7 @@ void Minecraft::init()
|
||||
{
|
||||
options.minecraft = this;
|
||||
options.initDefaultValues();
|
||||
|
||||
#ifndef STANDALONE_SERVER
|
||||
checkGlError("Init enter");
|
||||
|
||||
@@ -1150,24 +1174,37 @@ void Minecraft::setSize(int w, int h) {
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
if (width >= 1000) {
|
||||
// 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) {
|
||||
#ifdef __APPLE__
|
||||
Gui::GuiScale = (width > 2000)? 8.0f : 4.0f;
|
||||
#else
|
||||
Gui::GuiScale = 4.0f;
|
||||
#endif
|
||||
}
|
||||
else if (width >= 800) {
|
||||
else if (width >= 800) {
|
||||
#ifdef __APPLE__
|
||||
Gui::GuiScale = 4.0f;
|
||||
#else
|
||||
Gui::GuiScale = 3.0f;
|
||||
#endif
|
||||
}
|
||||
else if (width >= 400)
|
||||
Gui::GuiScale = 2.0f;
|
||||
else
|
||||
Gui::GuiScale = 1.0f;
|
||||
else if (width >= 400)
|
||||
Gui::GuiScale = 2.0f;
|
||||
else
|
||||
Gui::GuiScale = 1.0f;
|
||||
}
|
||||
|
||||
Gui::InvGuiScale = 1.0f / Gui::GuiScale;
|
||||
int screenWidth = (int)(width * Gui::InvGuiScale);
|
||||
@@ -1220,7 +1257,12 @@ void Minecraft::_reloadInput() {
|
||||
#ifndef STANDALONE_SERVER
|
||||
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);
|
||||
} else {
|
||||
#if defined(ANDROID) || defined(__APPLE__)
|
||||
@@ -1272,6 +1314,31 @@ bool Minecraft::joinMultiplayer( const PingedCompatibleServer& server )
|
||||
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) {
|
||||
// Tear down last instance
|
||||
raknetInstance->disconnect();
|
||||
@@ -1439,11 +1506,11 @@ LevelStorageSource* Minecraft::getLevelSource()
|
||||
return storageSource;
|
||||
}
|
||||
|
||||
int Minecraft::getLicenseId() {
|
||||
if (!LicenseCodes::isReady(_licenseId))
|
||||
_licenseId = platform()->checkLicense();
|
||||
return _licenseId;
|
||||
}
|
||||
// int Minecraft::getLicenseId() {
|
||||
// if (!LicenseCodes::isReady(_licenseId))
|
||||
// _licenseId = platform()->checkLicense();
|
||||
// return _licenseId;
|
||||
// }
|
||||
|
||||
void Minecraft::audioEngineOn() {
|
||||
#ifndef STANDALONE_SERVER
|
||||
@@ -1530,5 +1597,8 @@ void Minecraft::optionUpdated( const Options::Option* option, float 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
void locateMultiplayer();
|
||||
void cancelLocateMultiplayer();
|
||||
bool joinMultiplayer(const PingedCompatibleServer& server);
|
||||
bool joinMultiplayerFromString(const std::string& server);
|
||||
void hostMultiplayer(int port=19132);
|
||||
Player* respawnPlayer(int playerId);
|
||||
void respawnPlayer();
|
||||
@@ -109,7 +110,6 @@ public:
|
||||
void onGraphicsReset();
|
||||
|
||||
bool isLevelGenerated();
|
||||
int getLicenseId();
|
||||
|
||||
void audioEngineOn();
|
||||
void audioEngineOff();
|
||||
|
||||
@@ -5,12 +5,25 @@ const char* OptionStrings::Multiplayer_ServerVisible = "mp_server_visible_defa
|
||||
|
||||
const char* OptionStrings::Graphics_Fancy = "gfx_fancygraphics";
|
||||
const char* OptionStrings::Graphics_LowQuality = "gfx_lowquality";
|
||||
const char* OptionStrings::Graphics_Vsync = "gfx_vsync";
|
||||
const char* OptionStrings::Graphics_GUIScale = "gfx_guiscale";
|
||||
const char* OptionStrings::Graphics_SmoothLightning = "gfx_smoothlightning";
|
||||
const char* OptionStrings::Graphics_Anaglyph = "gfx_anaglyph";
|
||||
const char* OptionStrings::Graphics_ViewBobbing = "gfx_viewbobbing";
|
||||
|
||||
const char* OptionStrings::Controls_Sensitivity = "ctrl_sensitivity";
|
||||
const char* OptionStrings::Controls_InvertMouse = "ctrl_invertmouse";
|
||||
const char* OptionStrings::Controls_UseTouchScreen = "ctrl_usetouchscreen";
|
||||
const char* OptionStrings::Controls_UseTouchJoypad = "ctrl_usetouchjoypad";
|
||||
const char* OptionStrings::Controls_IsLefthanded = "ctrl_islefthanded";
|
||||
// why it isnt ctrl_feedback_vibration? i dont want touch it because compatibility with older versions
|
||||
const char* OptionStrings::Controls_FeedbackVibration = "feedback_vibration";
|
||||
const char* OptionStrings::Controls_AutoJump = "ctrl_autojump";
|
||||
|
||||
const char* OptionStrings::Game_DifficultyLevel = "game_difficulty";
|
||||
const char* OptionStrings::Audio_Music = "audio_music";
|
||||
const char* OptionStrings::Audio_Sound = "audio_sound";
|
||||
|
||||
const char* OptionStrings::Game_DifficultyLevel = "game_difficulty";
|
||||
|
||||
const char* OptionStrings::Tweaks_Sprint = "tweaks_sprint";
|
||||
const char* OptionStrings::Tweaks_BarOnTop = "tweaks_barontop";
|
||||
@@ -8,15 +8,29 @@ public:
|
||||
|
||||
static const char* Graphics_Fancy;
|
||||
static const char* Graphics_LowQuality;
|
||||
|
||||
static const char* Graphics_GUIScale;
|
||||
static const char* Graphics_Vsync;
|
||||
static const char* Graphics_SmoothLightning;
|
||||
static const char* Graphics_Anaglyph;
|
||||
static const char* Graphics_ViewBobbing;
|
||||
|
||||
static const char* Controls_Sensitivity;
|
||||
static const char* Controls_InvertMouse;
|
||||
static const char* Controls_UseTouchScreen;
|
||||
static const char* Controls_UseTouchJoypad;
|
||||
static const char* Controls_IsLefthanded;
|
||||
static const char* Controls_FeedbackVibration;
|
||||
static const char* Controls_AutoJump;
|
||||
|
||||
static const char* Audio_Music;
|
||||
static const char* Audio_Sound;
|
||||
|
||||
|
||||
static const char* Game_DifficultyLevel;
|
||||
|
||||
static const char* Tweaks_Sprint;
|
||||
static const char* Tweaks_BarOnTop;
|
||||
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT__OptionsStrings_H__*/
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
bool Options::debugGl = false;
|
||||
|
||||
void Options::initDefaultValues() {
|
||||
F1 = false;
|
||||
|
||||
difficulty = Difficulty::NORMAL;
|
||||
hideGui = false;
|
||||
thirdPersonView = false;
|
||||
@@ -23,9 +25,13 @@ void Options::initDefaultValues() {
|
||||
useMouseForDigging = false;
|
||||
destroyVibration = true;
|
||||
isLeftHanded = false;
|
||||
autoJump = true;
|
||||
|
||||
isJoyTouchArea = false;
|
||||
|
||||
useSprinting = true;
|
||||
barOnTop = false;
|
||||
|
||||
music = 1;
|
||||
sound = 1;
|
||||
sensitivity = 0.5f;
|
||||
@@ -34,6 +40,7 @@ void Options::initDefaultValues() {
|
||||
bobView = true;
|
||||
anaglyph3d = false;
|
||||
limitFramerate = false;
|
||||
vsync = true;
|
||||
fancyGraphics = true;//false;
|
||||
ambientOcclusion = false;
|
||||
if(minecraft->supportNonTouchScreen())
|
||||
@@ -44,7 +51,7 @@ void Options::initDefaultValues() {
|
||||
//useMouseForDigging = true;
|
||||
|
||||
//skin = "Default";
|
||||
username = "Steve";
|
||||
username = "";
|
||||
serverVisible = true;
|
||||
|
||||
keyUp = KeyMapping("key.forward", Keyboard::KEY_W);
|
||||
@@ -125,26 +132,30 @@ void Options::initDefaultValues() {
|
||||
}
|
||||
|
||||
const Options::Option
|
||||
Options::Option::MUSIC (0, "options.music", true, false),
|
||||
Options::Option::SOUND (1, "options.sound", true, false),
|
||||
Options::Option::INVERT_MOUSE (2, "options.invertMouse", false, true),
|
||||
Options::Option::SENSITIVITY (3, "options.sensitivity", true, false),
|
||||
Options::Option::RENDER_DISTANCE (4, "options.renderDistance",false, false),
|
||||
Options::Option::VIEW_BOBBING (5, "options.viewBobbing", false, true),
|
||||
Options::Option::ANAGLYPH (6, "options.anaglyph", false, true),
|
||||
Options::Option::LIMIT_FRAMERATE (7, "options.limitFramerate",false, true),
|
||||
Options::Option::DIFFICULTY (8, "options.difficulty", false, false),
|
||||
Options::Option::GRAPHICS (9, "options.graphics", false, false),
|
||||
Options::Option::AMBIENT_OCCLUSION (10, "options.ao", false, true),
|
||||
Options::Option::GUI_SCALE (11, "options.guiScale", false, false),
|
||||
Options::Option::THIRD_PERSON (12, "options.thirdperson", false, true),
|
||||
Options::Option::HIDE_GUI (13, "options.hidegui", false, true),
|
||||
Options::Option::SERVER_VISIBLE (14, "options.servervisible", false, true),
|
||||
Options::Option::LEFT_HANDED (15, "options.lefthanded", false, true),
|
||||
Options::Option::USE_TOUCHSCREEN (16, "options.usetouchscreen", false, true),
|
||||
Options::Option::USE_TOUCH_JOYPAD (17, "options.usetouchpad", false, true),
|
||||
Options::Option::DESTROY_VIBRATION (18, "options.destroyvibration", false, true),
|
||||
Options::Option::PIXELS_PER_MILLIMETER(19, "options.pixelspermilimeter", true, false);
|
||||
Options::Option::MUSIC (0, "options.music", true, false),
|
||||
Options::Option::SOUND (1, "options.sound", true, false),
|
||||
Options::Option::INVERT_MOUSE (2, "options.invertMouse", false, true),
|
||||
Options::Option::SENSITIVITY (3, "options.sensitivity", true, false),
|
||||
Options::Option::RENDER_DISTANCE (4, "options.renderDistance",false, false),
|
||||
Options::Option::VIEW_BOBBING (5, "options.viewBobbing", false, true),
|
||||
Options::Option::ANAGLYPH (6, "options.anaglyph", false, true),
|
||||
Options::Option::LIMIT_FRAMERATE (7, "options.limitFramerate",false, true),
|
||||
Options::Option::DIFFICULTY (8, "options.difficulty", false, false),
|
||||
Options::Option::GRAPHICS (9, "options.graphics", false, true),
|
||||
Options::Option::AMBIENT_OCCLUSION (10, "options.ao", false, true),
|
||||
Options::Option::GUI_SCALE (11, "options.guiScale", false, false),
|
||||
Options::Option::THIRD_PERSON (12, "options.thirdperson", false, true),
|
||||
Options::Option::HIDE_GUI (13, "options.hidegui", false, true),
|
||||
Options::Option::SERVER_VISIBLE (14, "options.servervisible", false, true),
|
||||
Options::Option::LEFT_HANDED (15, "options.lefthanded", false, true),
|
||||
Options::Option::USE_TOUCHSCREEN (16, "options.usetouchscreen", false, true),
|
||||
Options::Option::USE_TOUCH_JOYPAD (17, "options.usetouchpad", false, true),
|
||||
Options::Option::DESTROY_VIBRATION (18, "options.destroyvibration", false, true),
|
||||
Options::Option::PIXELS_PER_MILLIMETER(19, "options.pixelspermilimeter", true, false),
|
||||
Options::Option::VSYNC (20, "options.vsync", false, true),
|
||||
Options::Option::SPRINTING (21, "options.sprint", false, true),
|
||||
Options::Option::BARONTOP (22, "options.barontop", false, true),
|
||||
Options::Option::AUTOJUMP (23, "options.autojump", false, true);
|
||||
|
||||
/* private */
|
||||
const float Options::SOUND_MIN_VALUE = 0.0f;
|
||||
@@ -181,7 +192,8 @@ const char* Options::GUI_SCALE[] = {
|
||||
"options.guiScale.auto",
|
||||
"options.guiScale.small",
|
||||
"options.guiScale.normal",
|
||||
"options.guiScale.large"
|
||||
"options.guiScale.large",
|
||||
"options.guiScale.larger"
|
||||
};
|
||||
|
||||
void Options::update()
|
||||
@@ -204,7 +216,7 @@ void Options::update()
|
||||
if (readFloat(value, sens)) {
|
||||
// sens is in range [0,1] with default/center at 0.5 (for aesthetics)
|
||||
// We wanna map it to something like [0.3, 0.9] BUT keep 0.5 @ ~0.5...
|
||||
sensitivity = 0.3f + std::pow(1.1f * sens, 1.3f) * 0.42f;
|
||||
sensitivity = sens;
|
||||
}
|
||||
}
|
||||
if (key == OptionStrings::Controls_InvertMouse) {
|
||||
@@ -213,6 +225,9 @@ void Options::update()
|
||||
if (key == OptionStrings::Controls_IsLefthanded) {
|
||||
readBool(value, isLeftHanded);
|
||||
}
|
||||
if (key == OptionStrings::Controls_AutoJump) {
|
||||
readBool(value, autoJump);
|
||||
}
|
||||
if (key == OptionStrings::Controls_UseTouchJoypad) {
|
||||
readBool(value, isJoyTouchArea);
|
||||
if (!minecraft->useTouchscreen())
|
||||
@@ -235,6 +250,29 @@ void Options::update()
|
||||
fancyGraphics = false;
|
||||
}
|
||||
}
|
||||
if (key == OptionStrings::Graphics_SmoothLightning) {
|
||||
bool isLow;
|
||||
readBool(value, ambientOcclusion);
|
||||
}
|
||||
|
||||
// Graphics extras
|
||||
if (key == OptionStrings::Graphics_Vsync)
|
||||
readBool(value, vsync);
|
||||
if (key == OptionStrings::Graphics_Anaglyph)
|
||||
readBool(value, anaglyph3d);
|
||||
if (key == OptionStrings::Graphics_ViewBobbing)
|
||||
readBool(value, bobView);
|
||||
if (key == OptionStrings::Graphics_GUIScale) {
|
||||
int v;
|
||||
if (readInt(value, v)) guiScale = v % 5;
|
||||
}
|
||||
|
||||
// Audio
|
||||
if (key == OptionStrings::Audio_Music)
|
||||
readFloat(value, music);
|
||||
if (key == OptionStrings::Audio_Sound)
|
||||
readFloat(value, sound);
|
||||
|
||||
// Game
|
||||
if (key == OptionStrings::Game_DifficultyLevel) {
|
||||
readInt(value, difficulty);
|
||||
@@ -242,6 +280,14 @@ void Options::update()
|
||||
if (difficulty != Difficulty::PEACEFUL && difficulty != Difficulty::NORMAL)
|
||||
difficulty = Difficulty::NORMAL;
|
||||
}
|
||||
|
||||
// Enchancements
|
||||
if (key == OptionStrings::Tweaks_Sprint) {
|
||||
readBool(value, useSprinting);
|
||||
}
|
||||
if (key == OptionStrings::Tweaks_BarOnTop) {
|
||||
readBool(value, barOnTop);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
@@ -294,6 +340,10 @@ void Options::load()
|
||||
void Options::save()
|
||||
{
|
||||
StringVector stringVec;
|
||||
|
||||
// Login
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_Username, username);
|
||||
|
||||
// Game
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Multiplayer_ServerVisible, serverVisible);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty);
|
||||
@@ -305,6 +355,24 @@ void Options::save()
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchScreen, useTouchScreen);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_UseTouchJoypad, isJoyTouchArea);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_FeedbackVibration, destroyVibration);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Controls_AutoJump, autoJump);
|
||||
|
||||
// Graphics
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Vsync, vsync);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_GUIScale, guiScale);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Game_DifficultyLevel, difficulty);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Fancy, fancyGraphics);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_SmoothLightning, ambientOcclusion);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_Anaglyph, anaglyph3d);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Graphics_ViewBobbing, bobView);
|
||||
|
||||
// Audio
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Audio_Music, music);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Audio_Sound, sound);
|
||||
|
||||
// Tweaks
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Tweaks_Sprint, useSprinting);
|
||||
addOptionToSaveOutput(stringVec, OptionStrings::Tweaks_BarOnTop, barOnTop);
|
||||
//
|
||||
// static const Option MUSIC;
|
||||
// static const Option SOUND;
|
||||
@@ -348,6 +416,7 @@ void Options::save()
|
||||
// System.out.println("Failed to save options");
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
optionsFile.save(stringVec);
|
||||
}
|
||||
void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name, bool boolValue) {
|
||||
std::stringstream ss;
|
||||
@@ -364,6 +433,9 @@ void Options::addOptionToSaveOutput(StringVector& stringVector, std::string name
|
||||
ss << name << ":" << intValue;
|
||||
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 )
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
static const Option SOUND;
|
||||
static const Option INVERT_MOUSE;
|
||||
static const Option SENSITIVITY;
|
||||
static const Option AUTOJUMP;
|
||||
static const Option RENDER_DISTANCE;
|
||||
static const Option VIEW_BOBBING;
|
||||
static const Option ANAGLYPH;
|
||||
@@ -48,6 +49,9 @@ public:
|
||||
static const Option DESTROY_VIBRATION;
|
||||
|
||||
static const Option PIXELS_PER_MILLIMETER;
|
||||
static const Option VSYNC;
|
||||
static const Option SPRINTING;
|
||||
static const Option BARONTOP;
|
||||
|
||||
/*
|
||||
static Option* getItem(int id) {
|
||||
@@ -104,6 +108,8 @@ private:
|
||||
public:
|
||||
static bool debugGl;
|
||||
|
||||
bool F1;
|
||||
|
||||
float music;
|
||||
float sound;
|
||||
//note: sensitivity is transformed in Options::update
|
||||
@@ -113,11 +119,13 @@ public:
|
||||
bool bobView;
|
||||
bool anaglyph3d;
|
||||
bool limitFramerate;
|
||||
bool vsync;
|
||||
bool fancyGraphics;
|
||||
bool ambientOcclusion;
|
||||
bool useMouseForDigging;
|
||||
bool isLeftHanded;
|
||||
bool destroyVibration;
|
||||
bool autoJump;
|
||||
//std::string skin;
|
||||
|
||||
KeyMapping keyUp;
|
||||
@@ -161,6 +169,10 @@ public:
|
||||
bool isJoyTouchArea;
|
||||
bool useTouchScreen;
|
||||
float pixelsPerMillimeter;
|
||||
|
||||
bool useSprinting;
|
||||
bool barOnTop;
|
||||
|
||||
Options(Minecraft* minecraft, const std::string& workingDirectory)
|
||||
: minecraft(minecraft)
|
||||
{
|
||||
@@ -206,19 +218,21 @@ public:
|
||||
} else if (item == &Option::PIXELS_PER_MILLIMETER) {
|
||||
pixelsPerMillimeter = value;
|
||||
}
|
||||
notifyOptionUpdate(item, value);
|
||||
}
|
||||
notifyOptionUpdate(item, value); save(); }
|
||||
void set(const Option* item, int value) {
|
||||
if(item == &Option::DIFFICULTY) {
|
||||
difficulty = value;
|
||||
} else if(item == &Option::GUI_SCALE) {
|
||||
guiScale = value % 5;
|
||||
}
|
||||
notifyOptionUpdate(item, value);
|
||||
save();
|
||||
}
|
||||
|
||||
void toggle(const Option* option, int dir) {
|
||||
if (option == &Option::INVERT_MOUSE) invertYMouse = !invertYMouse;
|
||||
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::THIRD_PERSON) thirdPersonView = !thirdPersonView;
|
||||
if (option == &Option::HIDE_GUI) hideGui = !hideGui;
|
||||
@@ -232,6 +246,7 @@ public:
|
||||
//minecraft->textures.reloadAll();
|
||||
}
|
||||
if (option == &Option::LIMIT_FRAMERATE) limitFramerate = !limitFramerate;
|
||||
if (option == &Option::VSYNC) vsync = !vsync;
|
||||
if (option == &Option::DIFFICULTY) difficulty = (difficulty + dir) & 3;
|
||||
if (option == &Option::GRAPHICS) {
|
||||
fancyGraphics = !fancyGraphics;
|
||||
@@ -241,12 +256,17 @@ public:
|
||||
ambientOcclusion = !ambientOcclusion;
|
||||
//minecraft->levelRenderer.allChanged();
|
||||
}
|
||||
if (option == &Option::SPRINTING) useSprinting = !useSprinting;
|
||||
if (option == &Option::BARONTOP) barOnTop = !barOnTop;
|
||||
if (option == &Option::AUTOJUMP) autoJump = !autoJump;
|
||||
|
||||
notifyOptionUpdate(option, getBooleanValue(option));
|
||||
save();
|
||||
}
|
||||
|
||||
int getIntValue(const Option* item) {
|
||||
if(item == &Option::DIFFICULTY) return difficulty;
|
||||
if(item == &Option::GUI_SCALE) return guiScale;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -267,6 +287,10 @@ public:
|
||||
return anaglyph3d;
|
||||
if (item == &Option::LIMIT_FRAMERATE)
|
||||
return limitFramerate;
|
||||
if (item == &Option::VSYNC)
|
||||
return vsync;
|
||||
if (item == &Option::GRAPHICS)
|
||||
return fancyGraphics;
|
||||
if (item == &Option::AMBIENT_OCCLUSION)
|
||||
return ambientOcclusion;
|
||||
if (item == &Option::THIRD_PERSON)
|
||||
@@ -279,12 +303,18 @@ public:
|
||||
return serverVisible;
|
||||
if (item == &Option::LEFT_HANDED)
|
||||
return isLeftHanded;
|
||||
if (item == &Option::AUTOJUMP)
|
||||
return autoJump;
|
||||
if (item == &Option::USE_TOUCHSCREEN)
|
||||
return useTouchScreen;
|
||||
if (item == &Option::USE_TOUCH_JOYPAD)
|
||||
return isJoyTouchArea;
|
||||
if (item == &Option::DESTROY_VIBRATION)
|
||||
return destroyVibration;
|
||||
if (item == &Option::SPRINTING)
|
||||
return useSprinting;
|
||||
if (item == &Option::BARONTOP)
|
||||
return barOnTop;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -312,6 +342,7 @@ public:
|
||||
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, 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, float value);
|
||||
void notifyOptionUpdate(const Option* option, int value);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "OptionsFile.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <platform/log.h>
|
||||
|
||||
OptionsFile::OptionsFile() {
|
||||
#ifdef __APPLE__
|
||||
@@ -19,19 +20,32 @@ void OptionsFile::save(const StringVector& settings) {
|
||||
fprintf(pFile, "%s\n", it->c_str());
|
||||
}
|
||||
fclose(pFile);
|
||||
} else {
|
||||
LOGI("OptionsFile::save failed to open '%s' for writing: %s", settingsPath.c_str(), strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
StringVector OptionsFile::getOptionStrings() {
|
||||
StringVector returnVector;
|
||||
FILE* pFile = fopen(settingsPath.c_str(), "w");
|
||||
FILE* pFile = fopen(settingsPath.c_str(), "r");
|
||||
if(pFile != NULL) {
|
||||
char lineBuff[128];
|
||||
while(fgets(lineBuff, sizeof lineBuff, pFile)) {
|
||||
if(strlen(lineBuff) > 2)
|
||||
returnVector.push_back(std::string(lineBuff));
|
||||
// Strip trailing newline
|
||||
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);
|
||||
} else {
|
||||
LOGI("OptionsFile::getOptionStrings failed to open '%s' for reading: %s", settingsPath.c_str(), strerror(errno));
|
||||
}
|
||||
return returnVector;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Gui.h"
|
||||
#include "Font.h"
|
||||
#include "client/Options.h"
|
||||
#include "platform/input/Keyboard.h"
|
||||
#include "screens/IngameBlockSelectionScreen.h"
|
||||
#include "../Minecraft.h"
|
||||
#include "../player/LocalPlayer.h"
|
||||
@@ -21,6 +22,8 @@
|
||||
#include "../../platform/input/Mouse.h"
|
||||
#include "../../world/level/Level.h"
|
||||
#include "../../world/PosTranslator.h"
|
||||
#include "../../platform/time.h"
|
||||
#include <cmath>
|
||||
|
||||
float Gui::InvGuiScale = 1.0f / 3.0f;
|
||||
float Gui::GuiScale = 1.0f / Gui::InvGuiScale;
|
||||
@@ -85,14 +88,16 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
|
||||
// F: 3
|
||||
int ySlot = screenHeight - 16 - 3;
|
||||
|
||||
if (minecraft->gameMode->canHurtPlayer()) {
|
||||
minecraft->textures->loadAndBindTexture("gui/icons.png");
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.beginOverride();
|
||||
t.colorABGR(0xffffffff);
|
||||
renderHearts();
|
||||
renderBubbles();
|
||||
t.endOverrideAndDraw();
|
||||
if (!minecraft->options.F1) {
|
||||
if (minecraft->gameMode->canHurtPlayer()) {
|
||||
minecraft->textures->loadAndBindTexture("gui/icons.png");
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.beginOverride();
|
||||
t.colorABGR(0xffffffff);
|
||||
renderHearts();
|
||||
renderBubbles();
|
||||
t.endOverrideAndDraw();
|
||||
}
|
||||
}
|
||||
|
||||
if(minecraft->player->getSleepTimer() > 0) {
|
||||
@@ -104,7 +109,7 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
if (!minecraft->options.F1) {
|
||||
renderToolBar(a, ySlot, screenWidth);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
@@ -116,7 +121,11 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
|
||||
#endif
|
||||
#if defined(RPI)
|
||||
renderDebugInfo();
|
||||
#elif defined(PLATFORM_DESKTOP)
|
||||
if (minecraft->options.renderDebug)
|
||||
renderDebugInfo();
|
||||
#endif
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable2(GL_ALPHA_TEST);
|
||||
@@ -196,6 +205,10 @@ void Gui::handleClick(int button, int x, int y) {
|
||||
|
||||
void Gui::handleKeyPressed(int key)
|
||||
{
|
||||
if (key == Keyboard::KEY_F1) {
|
||||
minecraft->options.F1 = !minecraft->options.F1;
|
||||
}
|
||||
|
||||
if (key == 99)
|
||||
{
|
||||
if (minecraft->player->inventory->selected > 0)
|
||||
@@ -511,7 +524,7 @@ void Gui::renderProgressIndicator( const bool isTouchInterface, const int screen
|
||||
ItemInstance* currentItem = minecraft->player->inventory->getSelected();
|
||||
bool bowEquipped = currentItem != NULL ? currentItem->getItem() == Item::bow : false;
|
||||
bool itemInUse = currentItem != NULL ? currentItem->getItem() == minecraft->player->getUseItem()->getItem() : false;
|
||||
if (!isTouchInterface || minecraft->options.isJoyTouchArea || (bowEquipped && itemInUse)) {
|
||||
if ((!isTouchInterface || minecraft->options.isJoyTouchArea || (bowEquipped && itemInUse)) && !minecraft->options.F1) {
|
||||
minecraft->textures->loadAndBindTexture("gui/icons.png");
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc2(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
|
||||
@@ -580,11 +593,14 @@ void Gui::renderHearts() {
|
||||
int oh = minecraft->player->lastHealth;
|
||||
random.setSeed(tickCount * 312871);
|
||||
|
||||
int xx = 2;//screenWidth / 2 - getNumSlots() * 10;
|
||||
int screenWidth = (int)(minecraft->width * InvGuiScale);
|
||||
int screenHeight = (int)(minecraft->height * InvGuiScale);
|
||||
|
||||
int xx = (minecraft->options.barOnTop) ? screenWidth / 2 - getNumSlots() * 10 - 1 : 2;
|
||||
|
||||
int armor = minecraft->player->getArmorValue();
|
||||
for (int i = 0; i < Player::MAX_HEALTH / 2; i++) {
|
||||
int yo = 2;
|
||||
int yo = (minecraft->options.barOnTop) ? screenHeight - 32 : 2;
|
||||
int ip2 = i + i + 1;
|
||||
|
||||
if (armor > 0) {
|
||||
@@ -612,11 +628,15 @@ void Gui::renderHearts() {
|
||||
|
||||
void Gui::renderBubbles() {
|
||||
if (minecraft->player->isUnderLiquid(Material::water)) {
|
||||
int yo = 12;
|
||||
int screenWidth = (int)(minecraft->width * InvGuiScale);
|
||||
int screenHeight = (int)(minecraft->height * InvGuiScale);
|
||||
|
||||
int xx = (minecraft->options.barOnTop) ? screenWidth / 2 - getNumSlots() * 10 - 1 : 2;
|
||||
int yo = (minecraft->options.barOnTop) ? screenHeight - 42 : 12;
|
||||
int count = (int) std::ceil((minecraft->player->airSupply - 2) * 10.0f / Player::TOTAL_AIR_SUPPLY);
|
||||
int extra = (int) std::ceil((minecraft->player->airSupply) * 10.0f / Player::TOTAL_AIR_SUPPLY) - count;
|
||||
for (int i = 0; i < count + extra; i++) {
|
||||
int xo = i * 8 + 2;
|
||||
int xo = i * 8 + xx;
|
||||
if (i < count) blit(xo, yo, 16, 9 * 2, 9, 9);
|
||||
else blit(xo, yo, 16 + 9, 9 * 2, 9, 9);
|
||||
}
|
||||
@@ -632,17 +652,87 @@ void Gui::onLevelGenerated() {
|
||||
}
|
||||
|
||||
void Gui::renderDebugInfo() {
|
||||
static char buf[256];
|
||||
float xx = minecraft->player->x;
|
||||
float yy = minecraft->player->y - minecraft->player->heightOffset;
|
||||
float zz = minecraft->player->z;
|
||||
posTranslator.to(xx, yy, zz);
|
||||
sprintf(buf, "pos: %3.1f, %3.1f, %3.1f\n", xx, yy, zz);
|
||||
// FPS counter (updates once per second)
|
||||
static float fps = 0.0f;
|
||||
static float fpsLastTime = 0.0f;
|
||||
static int fpsFrames = 0;
|
||||
float now = getTimeS();
|
||||
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;
|
||||
t.beginOverride();
|
||||
t.scale2d(InvGuiScale, InvGuiScale);
|
||||
minecraft->font->draw(buf, 2, 2, 0xffffff);
|
||||
t.resetScale();
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (ln[i][0] == '\0') continue;
|
||||
float y = MGN + i * LH;
|
||||
int col = (i == 0) ? 0xffFFFF55 : 0xffffffff; // title yellow, rest white
|
||||
font->draw(ln[i], MGN, y, col);
|
||||
}
|
||||
t.endOverrideAndDraw();
|
||||
}
|
||||
|
||||
@@ -676,6 +766,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 ) {
|
||||
// if (minecraft.screen instanceof ChatScreen) {
|
||||
// max = 20;
|
||||
@@ -709,7 +863,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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,12 @@ public:
|
||||
|
||||
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 renderSleepAnimation( const int screenWidth, const int screenHeight );
|
||||
|
||||
@@ -25,6 +25,12 @@ void Screen::render( int xm, int ym, float a )
|
||||
Button* button = buttons[i];
|
||||
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 )
|
||||
@@ -72,6 +78,14 @@ void Screen::updateEvents()
|
||||
void Screen::mouseEvent()
|
||||
{
|
||||
const MouseAction& e = Mouse::getEvent();
|
||||
// forward wheel events to subclasses
|
||||
if (e.action == MouseAction::ACTION_WHEEL) {
|
||||
int xm = e.x * width / minecraft->width;
|
||||
int ym = e.y * height / minecraft->height - 1;
|
||||
mouseWheel(e.dx, e.dy, xm, ym);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!e.isButton())
|
||||
return;
|
||||
|
||||
@@ -157,6 +171,12 @@ void Screen::keyPressed( int eventKey )
|
||||
minecraft->setScreen(NULL);
|
||||
//minecraft->grabMouse();
|
||||
}
|
||||
|
||||
// pass key events to any text boxes first
|
||||
for (auto& textbox : textBoxes) {
|
||||
textbox->handleKey(eventKey);
|
||||
}
|
||||
|
||||
if (minecraft->useTouchscreen())
|
||||
return;
|
||||
|
||||
@@ -210,6 +230,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 )
|
||||
|
||||
@@ -57,6 +57,9 @@ protected:
|
||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||
virtual void mouseReleased(int x, int y, int buttonNum);
|
||||
|
||||
// mouse wheel movement (dx/dy are wheel deltas, xm/ym are GUI coords)
|
||||
virtual void mouseWheel(int dx, int dy, int xm, int ym) {}
|
||||
|
||||
virtual void keyPressed(int eventKey);
|
||||
virtual void keyboardNewChar(char inputChar) {}
|
||||
public:
|
||||
|
||||
@@ -10,7 +10,7 @@ OptionsGroup::OptionsGroup( std::string labelID ) {
|
||||
|
||||
void OptionsGroup::setupPositions() {
|
||||
// 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) {
|
||||
(*it)->width = width - 5;
|
||||
|
||||
@@ -23,7 +23,9 @@ void OptionsGroup::setupPositions() {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -45,6 +47,7 @@ void OptionsGroup::createToggle( const Options::Option* option, Minecraft* minec
|
||||
def.height = 20 * 0.7f;
|
||||
OptionButton* element = new OptionButton(option);
|
||||
element->setImageDef(def, true);
|
||||
element->updateImage(&minecraft->options);
|
||||
std::string itemLabel = I18n::get(option->getCaptionId());
|
||||
OptionsItem* item = new OptionsItem(itemLabel, element);
|
||||
addChild(item);
|
||||
@@ -58,11 +61,38 @@ void OptionsGroup::createProgressSlider( const Options::Option* option, Minecraf
|
||||
minecraft->options.getProgrssMax(option));
|
||||
element->width = 100;
|
||||
element->height = 20;
|
||||
OptionsItem* item = new OptionsItem(label, element);
|
||||
std::string itemLabel = I18n::get(option->getCaptionId());
|
||||
OptionsItem* item = new OptionsItem(itemLabel, element);
|
||||
addChild(item);
|
||||
setupPositions();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -548,6 +548,14 @@ void ScrollingPane::stepThroughDecelerationAnimation(bool noAnimation) {
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollingPane::scrollBy(float dx, float dy) {
|
||||
// adjust the translation offsets fpx/fpy by the requested amount
|
||||
float nfpx = fpx + dx;
|
||||
float nfpy = fpy + dy;
|
||||
// convert back to content offset (fpx = -contentOffset.x)
|
||||
setContentOffset(Vec3(-nfpx, -nfpy, 0));
|
||||
}
|
||||
|
||||
void ScrollingPane::setContentOffset(float x, float y) {
|
||||
this->setContentOffsetWithAnimation(Vec3(x, y, 0), false);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,10 @@ public:
|
||||
void tick();
|
||||
void render(int xm, int ym, float alpha);
|
||||
|
||||
// scroll the content by the given amount (dx horizontal, dy vertical)
|
||||
// positive values move content downward/rightward
|
||||
void scrollBy(float dx, float dy);
|
||||
|
||||
bool getGridItemFor_slow(int itemIndex, GridItem& out);
|
||||
|
||||
void setSelected(int id, bool selected);
|
||||
|
||||
@@ -25,13 +25,17 @@ Slider::Slider(Minecraft* minecraft, const Options::Option* option, const std::v
|
||||
assert(stepVec.size() > 1);
|
||||
numSteps = sliderSteps.size();
|
||||
if(option != NULL) {
|
||||
curStepValue;
|
||||
int curStep;
|
||||
// initialize slider position based on the current option value
|
||||
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()) {
|
||||
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,10 +50,15 @@ void Slider::render( Minecraft* minecraft, int xm, int ym ) {
|
||||
//fill(x, y + 8, x + (int)(width * percentage), y + height, 0xffff00ff);
|
||||
fill(xSliderStart, ySliderStart, xSliderEnd, ySliderEnd, 0xff606060);
|
||||
if(sliderType == SliderStep) {
|
||||
int stepDistance = barWidth / (numSteps -1);
|
||||
for(int a = 0; a <= numSteps - 1; ++a) {
|
||||
int renderSliderStepPosX = xSliderStart + a * stepDistance + 1;
|
||||
fill(renderSliderStepPosX - 1, ySliderStart - 2, renderSliderStepPosX + 1, ySliderEnd + 2, 0xff606060);
|
||||
// numSteps should be >=2; protect against bad input (zero division)
|
||||
if(numSteps <= 1) {
|
||||
// nothing to render
|
||||
} else {
|
||||
int stepDistance = barWidth / (numSteps -1);
|
||||
for(int a = 0; a <= numSteps - 1; ++a) {
|
||||
int renderSliderStepPosX = xSliderStart + a * stepDistance + 1;
|
||||
fill(renderSliderStepPosX - 1, ySliderStart - 2, renderSliderStepPosX + 1, ySliderEnd + 2, 0xff606060);
|
||||
}
|
||||
}
|
||||
}
|
||||
minecraft->textures->loadAndBindTexture("gui/touchgui.png");
|
||||
|
||||
@@ -1,37 +1,102 @@
|
||||
#include "TextBox.h"
|
||||
#include "../Gui.h"
|
||||
#include "../../Minecraft.h"
|
||||
#include "../../../AppPlatform.h"
|
||||
TextBox::TextBox( int id, const std::string& msg )
|
||||
: id(0), w(0), h(0), x(0), y(0), text(msg), focused(false) {
|
||||
#include "../../../platform/input/Mouse.h"
|
||||
|
||||
// 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 )
|
||||
: id(id), w(0), h(0), x(x), y(y), text(msg), focused(false) {
|
||||
|
||||
TextBox::TextBox(int id, int x, int y, const std::string& msg)
|
||||
: 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 )
|
||||
: id(id), w(w), h(h), x(x), y(y), text(msg) {
|
||||
|
||||
TextBox::TextBox(int id, int x, int y, int w, int h, const std::string& msg)
|
||||
: GuiElement(true, true, x, y, w, h),
|
||||
id(id), hint(msg), focused(false), blink(false), blinkTicks(0)
|
||||
{
|
||||
}
|
||||
|
||||
void TextBox::setFocus(Minecraft* minecraft) {
|
||||
if(!focused) {
|
||||
minecraft->platform()->showKeyboard();
|
||||
focused = true;
|
||||
}
|
||||
if (!focused) {
|
||||
minecraft->platform()->showKeyboard();
|
||||
focused = true;
|
||||
blinkTicks = 0;
|
||||
blink = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TextBox::loseFocus(Minecraft* minecraft) {
|
||||
if(focused) {
|
||||
minecraft->platform()->showKeyboard();
|
||||
focused = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (focused) {
|
||||
minecraft->platform()->hideKeyboard();
|
||||
focused = false;
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -4,31 +4,41 @@
|
||||
//package net.minecraft.client.gui;
|
||||
|
||||
#include <string>
|
||||
#include "../GuiComponent.h"
|
||||
#include "GuiElement.h"
|
||||
#include "../../Options.h"
|
||||
#include "../../../platform/input/Mouse.h"
|
||||
#include "../../../platform/input/Keyboard.h"
|
||||
|
||||
class Font;
|
||||
class Minecraft;
|
||||
|
||||
class TextBox: public GuiComponent
|
||||
class TextBox: public GuiElement
|
||||
{
|
||||
public:
|
||||
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, int w, int h, 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);
|
||||
|
||||
virtual void mouseClicked(Minecraft* minecraft, int x, int y, int buttonNum);
|
||||
|
||||
virtual void setFocus(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);
|
||||
|
||||
virtual void handleKey(int key);
|
||||
virtual void handleChar(char c);
|
||||
virtual void tick(Minecraft* minecraft);
|
||||
|
||||
public:
|
||||
int w, h;
|
||||
int x, y;
|
||||
|
||||
std::string hint;
|
||||
std::string text;
|
||||
int id;
|
||||
|
||||
int blinkTicks;
|
||||
|
||||
bool focused;
|
||||
bool blink;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__TextBox_H__*/
|
||||
|
||||
@@ -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__*/
|
||||
223
src/client/gui/screens/ConsoleScreen.cpp
Normal file
223
src/client/gui/screens/ConsoleScreen.cpp
Normal 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);
|
||||
}
|
||||
34
src/client/gui/screens/ConsoleScreen.h
Normal file
34
src/client/gui/screens/ConsoleScreen.h
Normal 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__*/
|
||||
127
src/client/gui/screens/CreditsScreen.cpp
Normal file
127
src/client/gui/screens/CreditsScreen.cpp
Normal 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);
|
||||
}
|
||||
32
src/client/gui/screens/CreditsScreen.h
Normal file
32
src/client/gui/screens/CreditsScreen.h
Normal 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__ */
|
||||
@@ -202,6 +202,25 @@ void IngameBlockSelectionScreen::keyPressed(int eventKey)
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// wheel support for creative inventory; scroll moves selection vertically
|
||||
void IngameBlockSelectionScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||
{
|
||||
if (dy == 0) return;
|
||||
// just move selection up/down one row; desktop UI doesn't have a pane
|
||||
int cols = InventoryCols;
|
||||
int maxIndex = InventorySize - 1;
|
||||
int idx = selectedItem;
|
||||
if (dy > 0) {
|
||||
// wheel up -> previous row
|
||||
if (idx >= cols) idx -= cols;
|
||||
} else {
|
||||
// wheel down -> next row
|
||||
if (idx + cols <= maxIndex) idx += cols;
|
||||
}
|
||||
selectedItem = idx;
|
||||
}
|
||||
|
||||
int IngameBlockSelectionScreen::getSelectedSlot(int x, int y)
|
||||
{
|
||||
int left = width / 2 - InventoryCols * 10;
|
||||
|
||||
@@ -23,6 +23,9 @@ protected:
|
||||
|
||||
virtual void buttonClicked(Button* button);
|
||||
|
||||
// wheel input for creative inventory scrolling
|
||||
virtual void mouseWheel(int dx, int dy, int xm, int ym) override;
|
||||
|
||||
virtual void keyPressed(int eventKey);
|
||||
private:
|
||||
void renderSlots();
|
||||
|
||||
@@ -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__*/
|
||||
140
src/client/gui/screens/JoinByIPScreen.cpp
Normal file
140
src/client/gui/screens/JoinByIPScreen.cpp
Normal 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);
|
||||
}
|
||||
30
src/client/gui/screens/JoinByIPScreen.h
Normal file
30
src/client/gui/screens/JoinByIPScreen.h
Normal 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;
|
||||
};
|
||||
@@ -1,46 +1,69 @@
|
||||
#include "OptionsScreen.h"
|
||||
|
||||
#include "StartMenuScreen.h"
|
||||
#include "UsernameScreen.h"
|
||||
#include "DialogDefinitions.h"
|
||||
#include "../../Minecraft.h"
|
||||
#include "../../../AppPlatform.h"
|
||||
#include "CreditsScreen.h"
|
||||
|
||||
#include "../components/OptionsPane.h"
|
||||
#include "../components/ImageButton.h"
|
||||
#include "../components/OptionsGroup.h"
|
||||
|
||||
OptionsScreen::OptionsScreen()
|
||||
: btnClose(NULL),
|
||||
bHeader(NULL),
|
||||
selectedCategory(0) {
|
||||
: btnClose(NULL),
|
||||
bHeader(NULL),
|
||||
btnChangeUsername(NULL),
|
||||
btnCredits(NULL),
|
||||
selectedCategory(0) {
|
||||
}
|
||||
|
||||
OptionsScreen::~OptionsScreen() {
|
||||
if(btnClose != NULL) {
|
||||
|
||||
if (btnClose != NULL) {
|
||||
delete btnClose;
|
||||
btnClose = NULL;
|
||||
}
|
||||
if(bHeader != NULL) {
|
||||
delete bHeader,
|
||||
|
||||
if (bHeader != NULL) {
|
||||
delete bHeader;
|
||||
bHeader = NULL;
|
||||
}
|
||||
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
|
||||
if(*it != NULL) {
|
||||
delete *it;
|
||||
|
||||
if (btnChangeUsername != NULL) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
for(std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
|
||||
if(*it != NULL) {
|
||||
delete *it;
|
||||
|
||||
for (std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
|
||||
if (*it != NULL) {
|
||||
delete* it;
|
||||
*it = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
categoryButtons.clear();
|
||||
}
|
||||
|
||||
void OptionsScreen::init() {
|
||||
|
||||
bHeader = new Touch::THeader(0, "Options");
|
||||
|
||||
btnClose = new ImageButton(1, "");
|
||||
|
||||
ImageDef def;
|
||||
def.name = "gui/touchgui.png";
|
||||
def.width = 34;
|
||||
@@ -53,129 +76,206 @@ void OptionsScreen::init() {
|
||||
categoryButtons.push_back(new Touch::TButton(3, "Game"));
|
||||
categoryButtons.push_back(new Touch::TButton(4, "Controls"));
|
||||
categoryButtons.push_back(new Touch::TButton(5, "Graphics"));
|
||||
categoryButtons.push_back(new Touch::TButton(6, "Tweaks"));
|
||||
|
||||
btnChangeUsername = new Touch::TButton(10, "Username");
|
||||
btnCredits = new Touch::TButton(11, "Credits");
|
||||
|
||||
buttons.push_back(bHeader);
|
||||
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);
|
||||
tabButtons.push_back(*it);
|
||||
}
|
||||
generateOptionScreens();
|
||||
|
||||
generateOptionScreens();
|
||||
// start with first category selected
|
||||
selectCategory(0);
|
||||
}
|
||||
|
||||
void OptionsScreen::setupPositions() {
|
||||
|
||||
int buttonHeight = btnClose->height;
|
||||
|
||||
btnClose->x = width - btnClose->width;
|
||||
btnClose->y = 0;
|
||||
|
||||
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)->y = offsetNum * buttonHeight;
|
||||
(*it)->selected = false;
|
||||
|
||||
offsetNum++;
|
||||
}
|
||||
|
||||
bHeader->x = 0;
|
||||
bHeader->y = 0;
|
||||
bHeader->width = width - btnClose->width;
|
||||
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)->y = bHeader->height;
|
||||
(*it)->width = width - categoryButtons[0]->width;
|
||||
|
||||
(*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();
|
||||
|
||||
super::render(xm, ym, a);
|
||||
|
||||
int xmm = xm * width / minecraft->width;
|
||||
int ymm = ym * height / minecraft->height - 1;
|
||||
if(currentOptionPane != NULL)
|
||||
|
||||
if (currentOptionPane != NULL)
|
||||
currentOptionPane->render(minecraft, xmm, ymm);
|
||||
}
|
||||
|
||||
void OptionsScreen::removed()
|
||||
{
|
||||
void OptionsScreen::removed() {
|
||||
}
|
||||
void OptionsScreen::buttonClicked( Button* button ) {
|
||||
if(button == btnClose) {
|
||||
minecraft->reloadOptions();
|
||||
|
||||
void OptionsScreen::buttonClicked(Button* button) {
|
||||
|
||||
if (button == btnClose) {
|
||||
|
||||
minecraft->options.save();
|
||||
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;
|
||||
selectCategory(categoryButton);
|
||||
|
||||
}
|
||||
else if (button == btnCredits) {
|
||||
|
||||
minecraft->setScreen(new CreditsScreen());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsScreen::selectCategory( int index ) {
|
||||
void OptionsScreen::selectCategory(int index) {
|
||||
|
||||
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;
|
||||
} else {
|
||||
else
|
||||
(*it)->selected = false;
|
||||
}
|
||||
|
||||
currentIndex++;
|
||||
}
|
||||
if(index < (int)optionPanes.size())
|
||||
|
||||
if (index < (int)optionPanes.size())
|
||||
currentOptionPane = optionPanes[index];
|
||||
}
|
||||
|
||||
void OptionsScreen::generateOptionScreens() {
|
||||
|
||||
optionPanes.push_back(new OptionsPane());
|
||||
optionPanes.push_back(new OptionsPane());
|
||||
optionPanes.push_back(new OptionsPane());
|
||||
optionPanes.push_back(new OptionsPane());
|
||||
// Mojang Pane
|
||||
optionPanes.push_back(new OptionsPane());
|
||||
|
||||
// Login Pane
|
||||
optionPanes[0]->createOptionsGroup("options.group.mojang")
|
||||
//.addOptionItem(&Options::Option::THIRD_PERSON, minecraft);
|
||||
.addOptionItem(&Options::Option::SENSITIVITY, minecraft);
|
||||
// int mojangGroup = optionPanes[0]->createOptionsGroup("Mojang");
|
||||
// static const int arr[] = {5,4,3,15};
|
||||
// std::vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
|
||||
// optionPanes[0]->createStepSlider(minecraft, mojangGroup, "This works?", &Options::Option::DIFFICULTY, vec);
|
||||
//
|
||||
// // Game Pane
|
||||
// int gameGroup = optionPanes[1]->createOptionsGroup("Game");
|
||||
// optionPanes[1]->createToggle(gameGroup, "Third person camera", &Options::Option::THIRD_PERSON);
|
||||
// optionPanes[1]->createToggle(gameGroup, "Server visible", &Options::Option::SERVER_VISIBLE);
|
||||
//
|
||||
// // Input Pane
|
||||
// int controlsGroup = optionPanes[2]->createOptionsGroup("Controls");
|
||||
// optionPanes[2]->createToggle(controlsGroup, "Invert X-axis", &Options::Option::INVERT_MOUSE);
|
||||
// optionPanes[2]->createToggle(controlsGroup, "Lefty", &Options::Option::LEFT_HANDED);
|
||||
// optionPanes[2]->createToggle(controlsGroup, "Use touch screen", &Options::Option::USE_TOUCHSCREEN);
|
||||
// optionPanes[2]->createToggle(controlsGroup, "Split touch controls", &Options::Option::USE_TOUCH_JOYPAD);
|
||||
// int feedBackGroup = optionPanes[2]->createOptionsGroup("Feedback");
|
||||
// optionPanes[2]->createToggle(feedBackGroup, "Vibrate on destroy", &Options::Option::DESTROY_VIBRATION);
|
||||
//
|
||||
// int graphicsGroup = optionPanes[3]->createOptionsGroup("Graphics");
|
||||
// optionPanes[3]->createProgressSlider(minecraft, graphicsGroup, "Gui Scale", &Options::Option::PIXELS_PER_MILLIMETER, 3, 4);
|
||||
// optionPanes[3]->createToggle(graphicsGroup, "Fancy Graphics", &Options::Option::INVERT_MOUSE);
|
||||
// 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);
|
||||
|
||||
// Game Pane
|
||||
optionPanes[1]->createOptionsGroup("options.group.game")
|
||||
.addOptionItem(&Options::Option::DIFFICULTY, minecraft)
|
||||
.addOptionItem(&Options::Option::SERVER_VISIBLE, minecraft)
|
||||
.addOptionItem(&Options::Option::THIRD_PERSON, minecraft)
|
||||
.addOptionItem(&Options::Option::GUI_SCALE, minecraft);
|
||||
|
||||
// Controls Pane
|
||||
optionPanes[2]->createOptionsGroup("options.group.controls")
|
||||
.addOptionItem(&Options::Option::INVERT_MOUSE, minecraft)
|
||||
.addOptionItem(&Options::Option::AUTOJUMP, minecraft);
|
||||
|
||||
// Graphics Pane
|
||||
optionPanes[3]->createOptionsGroup("options.group.graphics")
|
||||
.addOptionItem(&Options::Option::GRAPHICS, minecraft)
|
||||
.addOptionItem(&Options::Option::VIEW_BOBBING, minecraft)
|
||||
.addOptionItem(&Options::Option::AMBIENT_OCCLUSION, minecraft)
|
||||
.addOptionItem(&Options::Option::ANAGLYPH, minecraft)
|
||||
.addOptionItem(&Options::Option::VSYNC, minecraft)
|
||||
.addOptionItem(&Options::Option::MUSIC, minecraft)
|
||||
.addOptionItem(&Options::Option::SOUND, minecraft);
|
||||
|
||||
// Tweaks Pane
|
||||
optionPanes[4]->createOptionsGroup("options.group.tweaks")
|
||||
.addOptionItem(&Options::Option::SPRINTING, minecraft)
|
||||
.addOptionItem(&Options::Option::BARONTOP, minecraft);
|
||||
}
|
||||
|
||||
void OptionsScreen::mouseClicked( int x, int y, int buttonNum ) {
|
||||
if(currentOptionPane != NULL)
|
||||
void OptionsScreen::mouseClicked(int x, int y, int buttonNum) {
|
||||
|
||||
if (currentOptionPane != NULL)
|
||||
currentOptionPane->mouseClicked(minecraft, x, y, buttonNum);
|
||||
|
||||
super::mouseClicked(x, y, buttonNum);
|
||||
}
|
||||
|
||||
void OptionsScreen::mouseReleased( int x, int y, int buttonNum ) {
|
||||
if(currentOptionPane != NULL)
|
||||
void OptionsScreen::mouseReleased(int x, int y, int buttonNum) {
|
||||
|
||||
if (currentOptionPane != NULL)
|
||||
currentOptionPane->mouseReleased(minecraft, x, y, buttonNum);
|
||||
|
||||
super::mouseReleased(x, y, buttonNum);
|
||||
}
|
||||
|
||||
void OptionsScreen::tick() {
|
||||
if(currentOptionPane != NULL)
|
||||
|
||||
if (currentOptionPane != NULL)
|
||||
currentOptionPane->tick(minecraft);
|
||||
|
||||
super::tick();
|
||||
}
|
||||
}
|
||||
@@ -10,29 +10,37 @@ class OptionsPane;
|
||||
class OptionsScreen: public Screen
|
||||
{
|
||||
typedef Screen super;
|
||||
void init();
|
||||
|
||||
void init();
|
||||
void generateOptionScreens();
|
||||
|
||||
public:
|
||||
OptionsScreen();
|
||||
~OptionsScreen();
|
||||
|
||||
void setupPositions();
|
||||
void buttonClicked( Button* button );
|
||||
void buttonClicked(Button* button);
|
||||
void render(int xm, int ym, float a);
|
||||
void removed();
|
||||
void selectCategory(int index);
|
||||
|
||||
virtual void mouseClicked( int x, int y, int buttonNum );
|
||||
virtual void mouseReleased( 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 tick();
|
||||
|
||||
private:
|
||||
Touch::THeader* bHeader;
|
||||
ImageButton* btnClose;
|
||||
|
||||
Button* btnChangeUsername;
|
||||
Button* btnCredits; // <-- ADD THIS
|
||||
|
||||
std::vector<Touch::TButton*> categoryButtons;
|
||||
std::vector<OptionsPane*> optionPanes;
|
||||
|
||||
OptionsPane* currentOptionPane;
|
||||
|
||||
int selectedCategory;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__OptionsScreen_H__*/
|
||||
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__OptionsScreen_H__*/
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "PauseScreen.h"
|
||||
#include "RenameMPLevelScreen.h"
|
||||
#include "IngameBlockSelectionScreen.h"
|
||||
#include "JoinByIPScreen.h"
|
||||
#include "touch/TouchStartMenuScreen.h"
|
||||
#include "touch/TouchSelectWorldScreen.h"
|
||||
#include "touch/TouchJoinGameScreen.h"
|
||||
@@ -18,13 +19,13 @@ Screen* ScreenChooser::createScreen( ScreenId id )
|
||||
|
||||
if (_mc->useTouchscreen()) {
|
||||
switch (id) {
|
||||
case SCREEN_STARTMENU: screen = new Touch::StartMenuScreen(); break;
|
||||
case SCREEN_SELECTWORLD:screen = new Touch::SelectWorldScreen();break;
|
||||
case SCREEN_JOINGAME: screen = new Touch::JoinGameScreen(); break;
|
||||
case SCREEN_PAUSE: screen = new PauseScreen(false); break;
|
||||
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
|
||||
case SCREEN_BLOCKSELECTION: screen = new Touch::IngameBlockSelectionScreen(); break;
|
||||
|
||||
case SCREEN_STARTMENU: screen = new Touch::StartMenuScreen(); break;
|
||||
case SCREEN_SELECTWORLD: screen = new Touch::SelectWorldScreen();break;
|
||||
case SCREEN_JOINGAME: screen = new Touch::JoinGameScreen(); break;
|
||||
case SCREEN_PAUSE: screen = new PauseScreen(false); break;
|
||||
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
|
||||
case SCREEN_BLOCKSELECTION: screen = new Touch::IngameBlockSelectionScreen(); break;
|
||||
case SCREEN_JOINBYIP: screen = new JoinByIPScreen(); break;
|
||||
case SCREEN_NONE:
|
||||
default:
|
||||
// Do nothing
|
||||
@@ -32,12 +33,13 @@ Screen* ScreenChooser::createScreen( ScreenId id )
|
||||
}
|
||||
} else {
|
||||
switch (id) {
|
||||
case SCREEN_STARTMENU: screen = new StartMenuScreen(); break;
|
||||
case SCREEN_SELECTWORLD:screen = new SelectWorldScreen();break;
|
||||
case SCREEN_JOINGAME: screen = new JoinGameScreen(); break;
|
||||
case SCREEN_PAUSE: screen = new PauseScreen(false); break;
|
||||
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
|
||||
case SCREEN_BLOCKSELECTION: screen = new IngameBlockSelectionScreen(); break;
|
||||
case SCREEN_STARTMENU: screen = new StartMenuScreen(); break;
|
||||
case SCREEN_SELECTWORLD: screen = new SelectWorldScreen();break;
|
||||
case SCREEN_JOINGAME: screen = new JoinGameScreen(); break;
|
||||
case SCREEN_PAUSE: screen = new PauseScreen(false); break;
|
||||
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
|
||||
case SCREEN_BLOCKSELECTION: screen = new IngameBlockSelectionScreen(); break;
|
||||
case SCREEN_JOINBYIP: screen = new JoinByIPScreen(); break;
|
||||
|
||||
case SCREEN_NONE:
|
||||
default:
|
||||
|
||||
@@ -8,7 +8,8 @@ enum ScreenId {
|
||||
SCREEN_PAUSE,
|
||||
SCREEN_PAUSEPREV,
|
||||
SCREEN_SELECTWORLD,
|
||||
SCREEN_BLOCKSELECTION
|
||||
SCREEN_BLOCKSELECTION,
|
||||
SCREEN_JOINBYIP
|
||||
};
|
||||
|
||||
class Screen;
|
||||
|
||||
@@ -230,7 +230,6 @@ SelectWorldScreen::SelectWorldScreen()
|
||||
bBack (3, "Back"),
|
||||
bWorldView(4, ""),
|
||||
worldsList(NULL),
|
||||
_state(_STATE_DEFAULT),
|
||||
_hasStartedLevel(false)
|
||||
{
|
||||
bDelete.active = false;
|
||||
@@ -244,17 +243,11 @@ SelectWorldScreen::~SelectWorldScreen()
|
||||
void SelectWorldScreen::buttonClicked(Button* button)
|
||||
{
|
||||
if (button->id == bCreate.id) {
|
||||
//minecraft->setScreen( new CreateWorldScreen() );
|
||||
//minecraft->locateMultiplayer();
|
||||
//minecraft->setScreen(new JoinGameScreen());
|
||||
|
||||
//minecraft->hostMultiplayer();
|
||||
//minecraft->setScreen(new ProgressScreen());
|
||||
|
||||
if (_state == _STATE_DEFAULT && !_hasStartedLevel) {
|
||||
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_CREATE_NEW_WORLD);
|
||||
_state = _STATE_CREATEWORLD;
|
||||
}
|
||||
// open in-game world-creation screen instead of using platform dialog
|
||||
if (!_hasStartedLevel) {
|
||||
std::string name = getUniqueLevelName("world");
|
||||
minecraft->setScreen(new SimpleChooseLevelScreen(name));
|
||||
}
|
||||
}
|
||||
if (button->id == bDelete.id) {
|
||||
if (isIndexValid(worldsList->selectedItem)) {
|
||||
@@ -294,70 +287,6 @@ static char ILLEGAL_FILE_CHARACTERS[] = {
|
||||
|
||||
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();
|
||||
|
||||
if (worldsList->hasPickedLevel) {
|
||||
@@ -427,7 +356,7 @@ void SelectWorldScreen::render( int xm, int ym, float a )
|
||||
worldsList->setComponentSelected(bWorldView.selected);
|
||||
// #ifdef PLATFORM_DESKTOP
|
||||
|
||||
// We should add scrolling with mouse wheel but currently i dont know how to implement it
|
||||
// desktop: render the list normally (mouse wheel handled separately below)
|
||||
if (_mouseHasBeenUp)
|
||||
worldsList->render(xm, ym, a);
|
||||
else {
|
||||
@@ -483,6 +412,28 @@ std::string SelectWorldScreen::getUniqueLevelName( const std::string& level )
|
||||
|
||||
bool SelectWorldScreen::isInGameScreen() { return true; }
|
||||
|
||||
void SelectWorldScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||
{
|
||||
if (!worldsList)
|
||||
return;
|
||||
if (dy == 0)
|
||||
return;
|
||||
int num = worldsList->getNumberOfItems();
|
||||
int idx = worldsList->selectedItem;
|
||||
if (dy > 0) {
|
||||
if (idx > 0) {
|
||||
idx--;
|
||||
worldsList->stepLeft();
|
||||
}
|
||||
} else {
|
||||
if (idx < num - 1) {
|
||||
idx++;
|
||||
worldsList->stepRight();
|
||||
}
|
||||
}
|
||||
worldsList->selectedItem = idx;
|
||||
}
|
||||
|
||||
void SelectWorldScreen::keyPressed( int eventKey )
|
||||
{
|
||||
if (bWorldView.selected) {
|
||||
|
||||
@@ -90,6 +90,9 @@ public:
|
||||
|
||||
void render(int xm, int ym, float a);
|
||||
|
||||
// mouse wheel scroll (new in desktop implementation)
|
||||
virtual void mouseWheel(int dx, int dy, int xm, int ym);
|
||||
|
||||
bool isInGameScreen();
|
||||
private:
|
||||
void loadLevelSource();
|
||||
@@ -104,9 +107,6 @@ private:
|
||||
|
||||
bool _mouseHasBeenUp;
|
||||
bool _hasStartedLevel;
|
||||
int _state;
|
||||
static const int _STATE_DEFAULT = 0;
|
||||
static const int _STATE_CREATEWORLD = 1;
|
||||
//LevelStorageSource* levels;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,96 +2,265 @@
|
||||
#include "ProgressScreen.h"
|
||||
#include "ScreenChooser.h"
|
||||
#include "../components/Button.h"
|
||||
#include "../components/ImageButton.h"
|
||||
#include "../../Minecraft.h"
|
||||
#include "../../../world/level/LevelSettings.h"
|
||||
#include "../../../platform/time.h"
|
||||
#include "../../../platform/input/Keyboard.h"
|
||||
#include "../../../platform/log.h"
|
||||
|
||||
SimpleChooseLevelScreen::SimpleChooseLevelScreen(const std::string& levelName)
|
||||
: bCreative(0),
|
||||
bSurvival(0),
|
||||
bBack(0),
|
||||
levelName(levelName),
|
||||
hasChosen(false)
|
||||
: bHeader(0),
|
||||
bGamemode(0),
|
||||
bCheats(0),
|
||||
bBack(0),
|
||||
bCreate(0),
|
||||
levelName(levelName),
|
||||
hasChosen(false),
|
||||
gamemode(GameType::Survival),
|
||||
cheatsEnabled(false),
|
||||
tLevelName(0, "World name"),
|
||||
tSeed(1, "World seed")
|
||||
{
|
||||
}
|
||||
|
||||
SimpleChooseLevelScreen::~SimpleChooseLevelScreen()
|
||||
{
|
||||
delete bCreative;
|
||||
delete bSurvival;
|
||||
delete bBack;
|
||||
if (bHeader) delete bHeader;
|
||||
delete bGamemode;
|
||||
delete bCheats;
|
||||
delete bBack;
|
||||
delete bCreate;
|
||||
}
|
||||
|
||||
void SimpleChooseLevelScreen::init()
|
||||
{
|
||||
if (minecraft->useTouchscreen()) {
|
||||
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);
|
||||
// make sure the base class loads the existing level list; the
|
||||
// derived screen uses ChooseLevelScreen::getUniqueLevelName(), which
|
||||
// depends on `levels` being populated. omitting this used to result
|
||||
// in duplicate IDs ("creating the second world would load the
|
||||
// first") when the name already existed.
|
||||
ChooseLevelScreen::init();
|
||||
|
||||
tabButtons.push_back(bCreative);
|
||||
tabButtons.push_back(bSurvival);
|
||||
tabButtons.push_back(bBack);
|
||||
tLevelName.text = "New world";
|
||||
|
||||
// header + close button
|
||||
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");
|
||||
bCheats = new Touch::TButton(4, "Cheats: Off");
|
||||
bCreate = new Touch::TButton(3, "Create");
|
||||
} else {
|
||||
bGamemode = new Button(1, "Survival mode");
|
||||
bCheats = new Button(4, "Cheats: Off");
|
||||
bCreate = new Button(3, "Create");
|
||||
}
|
||||
|
||||
buttons.push_back(bHeader);
|
||||
buttons.push_back(bBack);
|
||||
buttons.push_back(bGamemode);
|
||||
buttons.push_back(bCheats);
|
||||
buttons.push_back(bCreate);
|
||||
|
||||
tabButtons.push_back(bGamemode);
|
||||
tabButtons.push_back(bCheats);
|
||||
tabButtons.push_back(bBack);
|
||||
tabButtons.push_back(bCreate);
|
||||
|
||||
textBoxes.push_back(&tLevelName);
|
||||
textBoxes.push_back(&tSeed);
|
||||
}
|
||||
|
||||
void SimpleChooseLevelScreen::setupPositions()
|
||||
{
|
||||
bCreative->width = bSurvival->width = bBack->width = 120;
|
||||
bCreative->x = (width - bCreative->width) / 2;
|
||||
bCreative->y = height/3 - 40;
|
||||
bSurvival->x = (width - bSurvival->width) / 2;
|
||||
bSurvival->y = 2*height/3 - 40;
|
||||
bBack->x = bSurvival->x + bSurvival->width - bBack->width;
|
||||
bBack->y = height - 40;
|
||||
int buttonHeight = bBack->height;
|
||||
|
||||
// position back button in upper-right
|
||||
bBack->x = width - bBack->width;
|
||||
bBack->y = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
const int buttonWidth = 120;
|
||||
const int buttonSpacing = 10;
|
||||
const int totalButtonWidth = buttonWidth * 2 + buttonSpacing;
|
||||
|
||||
bGamemode->width = buttonWidth;
|
||||
bCheats->width = buttonWidth;
|
||||
|
||||
bGamemode->x = centerX - totalButtonWidth / 2;
|
||||
bCheats->x = bGamemode->x + buttonWidth + buttonSpacing;
|
||||
|
||||
// compute vertical centre for buttons 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;
|
||||
int y = availTop + (availHeight - bGamemode->height) / 2;
|
||||
bGamemode->y = y;
|
||||
bCheats->y = y;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
renderDirtBackground(0);
|
||||
renderDirtBackground(0);
|
||||
glEnable2(GL_BLEND);
|
||||
|
||||
drawCenteredString(minecraft->font, "Mobs, health and gather resources", width/2, bSurvival->y + bSurvival->height + 4, 0xffcccccc);
|
||||
drawCenteredString(minecraft->font, "Unlimited resources and flying", width/2, bCreative->y + bCreative->height + 4, 0xffcccccc);
|
||||
const char* modeDesc = NULL;
|
||||
if (gamemode == GameType::Survival) {
|
||||
modeDesc = "Mobs, health and gather resources";
|
||||
} else if (gamemode == GameType::Creative) {
|
||||
modeDesc = "Unlimited resources and flying";
|
||||
}
|
||||
if (modeDesc) {
|
||||
drawCenteredString(minecraft->font, modeDesc, width / 2, bGamemode->y + bGamemode->height + 4, 0xffcccccc);
|
||||
}
|
||||
|
||||
Screen::render(xm, ym, a);
|
||||
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);
|
||||
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 )
|
||||
{
|
||||
if (button == bBack) {
|
||||
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
|
||||
return;
|
||||
}
|
||||
if (hasChosen)
|
||||
return;
|
||||
if (hasChosen)
|
||||
return;
|
||||
|
||||
int gameType;
|
||||
if (button == bGamemode) {
|
||||
gamemode ^= 1;
|
||||
bGamemode->msg = (gamemode == GameType::Survival) ? "Survival mode" : "Creative mode";
|
||||
return;
|
||||
}
|
||||
|
||||
if (button == bCreative)
|
||||
gameType = GameType::Creative;
|
||||
if (button == bCheats) {
|
||||
cheatsEnabled = !cheatsEnabled;
|
||||
bCheats->msg = cheatsEnabled ? "Cheats: On" : "Cheats: Off";
|
||||
return;
|
||||
}
|
||||
|
||||
if (button == bSurvival)
|
||||
gameType = GameType::Survival;
|
||||
if (button == bCreate && !tLevelName.text.empty()) {
|
||||
int seed = getEpochTimeS();
|
||||
if (!tSeed.text.empty()) {
|
||||
std::string seedString = Util::stringTrim(tSeed.text);
|
||||
int tmpSeed;
|
||||
if (sscanf(seedString.c_str(), "%d", &tmpSeed) > 0) {
|
||||
seed = tmpSeed;
|
||||
} else {
|
||||
seed = Util::hashCode(seedString);
|
||||
}
|
||||
}
|
||||
std::string levelId = getUniqueLevelName(tLevelName.text);
|
||||
LevelSettings settings(seed, gamemode, cheatsEnabled);
|
||||
minecraft->selectLevel(levelId, levelId, settings);
|
||||
minecraft->hostMultiplayer();
|
||||
minecraft->setScreen(new ProgressScreen());
|
||||
hasChosen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string levelId = getUniqueLevelName(levelName);
|
||||
LevelSettings settings(getEpochTimeS(), gameType);
|
||||
minecraft->selectLevel(levelId, levelId, settings);
|
||||
minecraft->hostMultiplayer();
|
||||
minecraft->setScreen(new ProgressScreen());
|
||||
hasChosen = true;
|
||||
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) {
|
||||
if (!isDown)
|
||||
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__
|
||||
|
||||
#include "ChooseLevelScreen.h"
|
||||
#include "../components/TextBox.h"
|
||||
#include "../components/Button.h" // for Touch::THeader
|
||||
class Button;
|
||||
class ImageButton;
|
||||
|
||||
class SimpleChooseLevelScreen: public ChooseLevelScreen
|
||||
{
|
||||
@@ -12,21 +15,31 @@ public:
|
||||
virtual ~SimpleChooseLevelScreen();
|
||||
|
||||
void init();
|
||||
|
||||
void setupPositions();
|
||||
void tick();
|
||||
|
||||
void render(int xm, int ym, float a);
|
||||
|
||||
void buttonClicked(Button* button);
|
||||
bool handleBackEvent(bool isDown);
|
||||
virtual void keyPressed(int eventKey);
|
||||
virtual void keyboardNewChar(char inputChar);
|
||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||
|
||||
private:
|
||||
Button* bCreative;
|
||||
Button* bSurvival;
|
||||
Button* bBack;
|
||||
Touch::THeader* bHeader;
|
||||
Button* bGamemode;
|
||||
Button* bCheats;
|
||||
ImageButton* bBack;
|
||||
Button* bCreate;
|
||||
bool hasChosen;
|
||||
|
||||
std::string levelName;
|
||||
int gamemode;
|
||||
bool cheatsEnabled;
|
||||
|
||||
TextBox tLevelName;
|
||||
TextBox tSeed;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__*/
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "StartMenuScreen.h"
|
||||
#include "UsernameScreen.h"
|
||||
#include "SelectWorldScreen.h"
|
||||
#include "ProgressScreen.h"
|
||||
#include "JoinGameScreen.h"
|
||||
#include "OptionsScreen.h"
|
||||
#include "PauseScreen.h"
|
||||
#include "InvalidLicenseScreen.h"
|
||||
#include "PrerenderTilesScreen.h" // test button
|
||||
//#include "BuyGameScreen.h"
|
||||
#include "../components/ImageButton.h"
|
||||
|
||||
#include "../../../util/Mth.h"
|
||||
|
||||
@@ -27,8 +27,7 @@ StartMenuScreen::StartMenuScreen()
|
||||
: bHost( 2, 0, 0, 160, 24, "Start Game"),
|
||||
bJoin( 3, 0, 0, 160, 24, "Join Game"),
|
||||
bOptions( 4, 0, 0, 78, 22, "Options"),
|
||||
bBuy( 5, 0, 0, 78, 22, "Buy"),
|
||||
bTest( 999, 0, 0, 78, 22, "Create")
|
||||
bQuit( 5, "")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -38,6 +37,13 @@ StartMenuScreen::~StartMenuScreen()
|
||||
|
||||
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(&bJoin);
|
||||
//buttons.push_back(&bTest);
|
||||
@@ -50,18 +56,23 @@ void StartMenuScreen::init()
|
||||
tabButtons.push_back(&bOptions);
|
||||
#endif
|
||||
|
||||
#ifdef DEMO_MODE
|
||||
buttons.push_back(&bBuy);
|
||||
tabButtons.push_back(&bBuy);
|
||||
#endif
|
||||
// add quit button (top right X icon) – match OptionsScreen style
|
||||
{
|
||||
ImageDef def;
|
||||
def.name = "gui/touchgui.png";
|
||||
def.width = 34;
|
||||
def.height = 26;
|
||||
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
|
||||
bQuit.setImageDef(def, true);
|
||||
bQuit.scaleWhenPressed = false;
|
||||
buttons.push_back(&bQuit);
|
||||
// don't include in tab navigation
|
||||
}
|
||||
|
||||
copyright = "\xffMojang AB";//. Do not distribute!";
|
||||
|
||||
#ifdef PRE_ANDROID23
|
||||
std::string versionString = Common::getGameVersionString("j");
|
||||
#else
|
||||
std::string versionString = Common::getGameVersionString();
|
||||
#endif
|
||||
// always show base version string, suffix was previously added for Android builds
|
||||
std::string versionString = Common::getGameVersionString();
|
||||
|
||||
#ifdef DEMO_MODE
|
||||
#ifdef __APPLE__
|
||||
@@ -92,21 +103,23 @@ void StartMenuScreen::setupPositions() {
|
||||
#endif
|
||||
|
||||
bOptions.y = yBase + 28 + 2;
|
||||
bTest.y = bBuy.y = bOptions.y;
|
||||
//#endif
|
||||
|
||||
// Center buttons
|
||||
bHost.x = (width - bHost.width) / 2;
|
||||
bJoin.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;
|
||||
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
|
||||
// position quit icon at top-right (use image-defined size)
|
||||
bQuit.x = width - bQuit.width;
|
||||
bQuit.y = 0;
|
||||
}
|
||||
|
||||
void StartMenuScreen::tick() {
|
||||
_updateLicense();
|
||||
if (minecraft->options.username.empty()) {
|
||||
minecraft->setScreen(new UsernameScreen());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void StartMenuScreen::buttonClicked(Button* button) {
|
||||
@@ -128,15 +141,9 @@ void StartMenuScreen::buttonClicked(Button* button) {
|
||||
{
|
||||
minecraft->setScreen(new OptionsScreen());
|
||||
}
|
||||
if (button->id == bTest.id)
|
||||
if (button == &bQuit)
|
||||
{
|
||||
//minecraft->setScreen(new PauseScreen());
|
||||
//minecraft->setScreen(new PrerenderTilesScreen());
|
||||
}
|
||||
if (button->id == bBuy.id)
|
||||
{
|
||||
minecraft->platform()->buyGame();
|
||||
//minecraft->setScreen(new BuyGameScreen());
|
||||
minecraft->quit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +153,10 @@ void StartMenuScreen::render( int xm, int ym, float a )
|
||||
{
|
||||
renderBackground();
|
||||
|
||||
// Show current username in the top-left corner
|
||||
std::string username = minecraft->options.username.empty() ? "unknown" : minecraft->options.username;
|
||||
drawString(font, std::string("Username: ") + username, 2, 2, 0xffffffff);
|
||||
|
||||
#if defined(RPI)
|
||||
TextureId id = minecraft->textures->loadTexture("gui/pi_title.png");
|
||||
#else
|
||||
@@ -181,25 +192,30 @@ void StartMenuScreen::render( int xm, int ym, float a )
|
||||
|
||||
drawString(font, version, versionPosX, 62, /*50,*/ 0xffcccccc);//0x666666);
|
||||
drawString(font, copyright, copyrightPosX, height - 10, 0xffffff);
|
||||
|
||||
Screen::render(xm, ym, a);
|
||||
glEnable2(GL_BLEND);
|
||||
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()
|
||||
{
|
||||
int id = minecraft->getLicenseId();
|
||||
if (LicenseCodes::isReady(id))
|
||||
{
|
||||
if (LicenseCodes::isOk(id))
|
||||
bJoin.active = bHost.active = bOptions.active = true;
|
||||
else
|
||||
{
|
||||
bool hasBuyButton = minecraft->platform()->hasBuyButtonWhenInvalidLicense();
|
||||
minecraft->setScreen(new InvalidLicenseScreen(id, hasBuyButton));
|
||||
}
|
||||
} else {
|
||||
bJoin.active = bHost.active = bOptions.active = false;
|
||||
}
|
||||
void StartMenuScreen::mouseClicked(int x, int y, int buttonNum) {
|
||||
const int logoX = 2;
|
||||
const int logoW = 8 + 2 + font->width("Kolyah35/minecraft-pe-0.6.1");
|
||||
const int logoY = height - 10;
|
||||
const int logoH = 10;
|
||||
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
|
||||
Screen::mouseClicked(x, y, buttonNum);
|
||||
}
|
||||
|
||||
bool StartMenuScreen::handleBackEvent( bool isDown ) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "../Screen.h"
|
||||
#include "../components/Button.h"
|
||||
#include "../components/ImageButton.h"
|
||||
|
||||
class StartMenuScreen: public Screen
|
||||
{
|
||||
@@ -17,16 +18,15 @@ public:
|
||||
void render(int xm, int ym, float a);
|
||||
|
||||
void buttonClicked(Button* button);
|
||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||
bool handleBackEvent(bool isDown);
|
||||
bool isInGameScreen();
|
||||
private:
|
||||
void _updateLicense();
|
||||
|
||||
Button bHost;
|
||||
Button bJoin;
|
||||
Button bOptions;
|
||||
Button bTest;
|
||||
Button bBuy;
|
||||
ImageButton bQuit; // X button in top-right corner
|
||||
|
||||
std::string copyright;
|
||||
int copyrightPosX;
|
||||
|
||||
133
src/client/gui/screens/UsernameScreen.cpp
Normal file
133
src/client/gui/screens/UsernameScreen.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#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;
|
||||
|
||||
// Make the done button match the touch-style option tabs
|
||||
_btnDone.width = 66;
|
||||
_btnDone.height = 26;
|
||||
_btnDone.x = (width - _btnDone.width) / 2;
|
||||
_btnDone.y = height / 2 + 52;
|
||||
|
||||
tUsername.width = 120;
|
||||
tUsername.height = 20;
|
||||
tUsername.x = (width - tUsername.width) / 2;
|
||||
tUsername.y = _btnDone.y - 60;
|
||||
}
|
||||
|
||||
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
|
||||
Screen::keyPressed(eventKey);
|
||||
|
||||
// enable the Done button only when there is some text (and ensure it updates after backspace)
|
||||
_btnDone.active = !tUsername.text.empty();
|
||||
}
|
||||
|
||||
void UsernameScreen::keyboardNewChar(char inputChar)
|
||||
{
|
||||
// limit username length to 12 characters
|
||||
if (tUsername.text.size() < 12) {
|
||||
for (auto* tb : textBoxes) tb->handleChar(inputChar);
|
||||
}
|
||||
|
||||
_btnDone.active = !tUsername.text.empty();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
39
src/client/gui/screens/UsernameScreen.h
Normal file
39
src/client/gui/screens/UsernameScreen.h
Normal 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:
|
||||
Touch::TButton _btnDone;
|
||||
TextBox tUsername;
|
||||
std::string _input;
|
||||
int _cursorBlink;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__UsernameScreen_H__*/
|
||||
@@ -153,6 +153,11 @@ int IngameBlockSelectionScreen::getSlotPosY(int slotY) {
|
||||
return height - 16 - 3 - 22 * 2 - 22 * slotY;
|
||||
}
|
||||
|
||||
int IngameBlockSelectionScreen::getSlotHeight() {
|
||||
// same as non-touch implementation
|
||||
return 22;
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::mouseClicked(int x, int y, int buttonNum) {
|
||||
_pendingClose = _blockList->_clickArea->isInside((float)x, (float)y);
|
||||
if (!_pendingClose)
|
||||
@@ -166,6 +171,24 @@ void IngameBlockSelectionScreen::mouseReleased(int x, int y, int buttonNum) {
|
||||
super::mouseReleased(x, y, buttonNum);
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||
{
|
||||
if (dy == 0) return;
|
||||
if (_blockList) {
|
||||
float amount = -dy * getSlotHeight();
|
||||
_blockList->scrollBy(0, amount);
|
||||
}
|
||||
int cols = InventoryColumns;
|
||||
int maxIndex = InventorySize - 1;
|
||||
int idx = selectedItem;
|
||||
if (dy > 0) {
|
||||
if (idx >= cols) idx -= cols;
|
||||
} else {
|
||||
if (idx + cols <= maxIndex) idx += cols;
|
||||
}
|
||||
selectedItem = idx;
|
||||
}
|
||||
|
||||
bool IngameBlockSelectionScreen::addItem(const InventoryPane* pane, int itemId)
|
||||
{
|
||||
Inventory* inventory = minecraft->player->inventory;
|
||||
|
||||
@@ -39,12 +39,16 @@ public:
|
||||
protected:
|
||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||
virtual void mouseReleased(int x, int y, int buttonNum);
|
||||
|
||||
// also support wheel scrolling
|
||||
virtual void mouseWheel(int dx, int dy, int xm, int ym) override;
|
||||
private:
|
||||
void renderDemoOverlay();
|
||||
|
||||
//int getLinearSlotId(int x, int y);
|
||||
int getSlotPosX(int slotX);
|
||||
int getSlotPosY(int slotY);
|
||||
int getSlotHeight();
|
||||
|
||||
private:
|
||||
int selectedItem;
|
||||
|
||||
@@ -64,6 +64,7 @@ void AvailableGamesList::renderItem( int i, int x, int y, int h, Tesselator& t )
|
||||
JoinGameScreen::JoinGameScreen()
|
||||
: bJoin( 2, "Join Game"),
|
||||
bBack( 3, "Back"),
|
||||
bJoinByIp(4, "Join By IP"),
|
||||
bHeader(0, ""),
|
||||
gamesList(NULL)
|
||||
{
|
||||
@@ -80,6 +81,7 @@ void JoinGameScreen::init()
|
||||
{
|
||||
//buttons.push_back(&bJoin);
|
||||
buttons.push_back(&bBack);
|
||||
buttons.push_back(&bJoinByIp);
|
||||
buttons.push_back(&bHeader);
|
||||
|
||||
minecraft->raknetInstance->clearServerList();
|
||||
@@ -88,6 +90,7 @@ void JoinGameScreen::init()
|
||||
#ifdef ANDROID
|
||||
//tabButtons.push_back(&bJoin);
|
||||
tabButtons.push_back(&bBack);
|
||||
tabButtons.push_back(&bJoinByIp);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -95,16 +98,18 @@ void JoinGameScreen::setupPositions() {
|
||||
//int yBase = height - 26;
|
||||
|
||||
//#ifdef ANDROID
|
||||
bJoin.y = 0;
|
||||
bBack.y = 0;
|
||||
bHeader.y = 0;
|
||||
bJoin.y = 0;
|
||||
bBack.y = 0;
|
||||
bJoinByIp.y = 0;
|
||||
bHeader.y = 0;
|
||||
//#endif
|
||||
|
||||
// Center buttons
|
||||
//bJoin.x = width / 2 - 4 - bJoin.w;
|
||||
bBack.x = 0;//width / 2 + 4;
|
||||
bHeader.x = bBack.width;
|
||||
bHeader.width = width - bHeader.x;
|
||||
bJoinByIp.x = width - bJoinByIp.width;;
|
||||
bHeader.x = bJoinByIp.width;
|
||||
bHeader.width = width - (bBack.width + bJoinByIp.width);
|
||||
}
|
||||
|
||||
void JoinGameScreen::buttonClicked(Button* button)
|
||||
@@ -124,6 +129,11 @@ void JoinGameScreen::buttonClicked(Button* button)
|
||||
//minecraft->locateMultiplayer();
|
||||
//minecraft->setScreen(new JoinGameScreen());
|
||||
}
|
||||
if(button->id == bJoinByIp.id) {
|
||||
minecraft->cancelLocateMultiplayer();
|
||||
minecraft->screenChooser.setScreen(SCREEN_JOINBYIP);
|
||||
}
|
||||
|
||||
if (button->id == bBack.id)
|
||||
{
|
||||
minecraft->cancelLocateMultiplayer();
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
private:
|
||||
Button bJoin;
|
||||
TButton bBack;
|
||||
TButton bJoinByIp;
|
||||
THeader bHeader;
|
||||
AvailableGamesList* gamesList;
|
||||
};
|
||||
|
||||
@@ -283,8 +283,7 @@ SelectWorldScreen::SelectWorldScreen()
|
||||
bHeader (0, "Select world"),
|
||||
bWorldView(4, ""),
|
||||
worldsList(NULL),
|
||||
_hasStartedLevel(false),
|
||||
_state(_STATE_DEFAULT)
|
||||
_hasStartedLevel(false)
|
||||
{
|
||||
bDelete.active = false;
|
||||
|
||||
@@ -349,9 +348,9 @@ void SelectWorldScreen::setupPositions() {
|
||||
void SelectWorldScreen::buttonClicked(Button* button)
|
||||
{
|
||||
if (button->id == bCreate.id) {
|
||||
if (_state == _STATE_DEFAULT && !_hasStartedLevel) {
|
||||
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_CREATE_NEW_WORLD);
|
||||
_state = _STATE_CREATEWORLD;
|
||||
if (!_hasStartedLevel) {
|
||||
std::string name = getUniqueLevelName("World");
|
||||
minecraft->setScreen(new SimpleChooseLevelScreen(name));
|
||||
}
|
||||
}
|
||||
if (button->id == bDelete.id) {
|
||||
@@ -390,11 +389,32 @@ static char ILLEGAL_FILE_CHARACTERS[] = {
|
||||
'/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':'
|
||||
};
|
||||
|
||||
void SelectWorldScreen::mouseWheel(int dx, int dy, int xm, int ym)
|
||||
{
|
||||
if (!worldsList) return;
|
||||
if (dy == 0) return;
|
||||
int num = worldsList->getNumberOfItems();
|
||||
int idx = worldsList->selectedItem;
|
||||
if (dy > 0) {
|
||||
if (idx > 0) {
|
||||
idx--;
|
||||
worldsList->stepLeft();
|
||||
}
|
||||
} else {
|
||||
if (idx < num - 1) {
|
||||
idx++;
|
||||
worldsList->stepRight();
|
||||
}
|
||||
}
|
||||
worldsList->selectedItem = idx;
|
||||
}
|
||||
|
||||
void SelectWorldScreen::tick()
|
||||
{
|
||||
#if 0
|
||||
if (_state == _STATE_CREATEWORLD) {
|
||||
#if defined(RPI)
|
||||
std::string levelId = getUniqueLevelName("perf");
|
||||
std::string levelId = getUniqueLevelName("World");
|
||||
//int seed = Util::hashCode("/r/Minecraft");
|
||||
LevelSettings settings(getEpochTimeS(), GameType::Creative);
|
||||
minecraft->selectLevel(levelId, levelId, settings);
|
||||
@@ -402,7 +422,7 @@ void SelectWorldScreen::tick()
|
||||
minecraft->setScreen(new ProgressScreen());
|
||||
_hasStartedLevel = true;
|
||||
#elif defined(PLATFORM_DESKTOP)
|
||||
std::string name = getUniqueLevelName("perf");
|
||||
std::string name = getUniqueLevelName("World");
|
||||
minecraft->setScreen(new SimpleChooseLevelScreen(name));
|
||||
#else
|
||||
int status = minecraft->platform()->getUserInputStatus();
|
||||
@@ -461,14 +481,15 @@ void SelectWorldScreen::tick()
|
||||
worldsList->hasPickedLevel = false;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
worldsList->tick();
|
||||
|
||||
if (worldsList->hasPickedLevel) {
|
||||
if (worldsList->pickedIndex == worldsList->levels.size()) {
|
||||
worldsList->hasPickedLevel = false;
|
||||
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_CREATE_NEW_WORLD);
|
||||
_state = _STATE_CREATEWORLD;
|
||||
std::string name = getUniqueLevelName("World");
|
||||
minecraft->setScreen(new SimpleChooseLevelScreen(name));
|
||||
} else {
|
||||
minecraft->selectLevel(worldsList->pickedLevel.id, worldsList->pickedLevel.name, LevelSettings::None());
|
||||
minecraft->hostMultiplayer();
|
||||
|
||||
@@ -97,6 +97,9 @@ public:
|
||||
virtual void buttonClicked(Button* button);
|
||||
virtual void keyPressed(int eventKey);
|
||||
|
||||
// support for mouse wheel when desktop code uses touch variant
|
||||
virtual void mouseWheel(int dx, int dy, int xm, int ym) override;
|
||||
|
||||
bool isInGameScreen();
|
||||
private:
|
||||
void loadLevelSource();
|
||||
@@ -112,9 +115,6 @@ private:
|
||||
|
||||
bool _mouseHasBeenUp;
|
||||
bool _hasStartedLevel;
|
||||
int _state;
|
||||
static const int _STATE_DEFAULT = 0;
|
||||
static const int _STATE_CREATEWORLD = 1;
|
||||
//LevelStorageSource* levels;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#include "../ProgressScreen.h"
|
||||
#include "../OptionsScreen.h"
|
||||
#include "../PauseScreen.h"
|
||||
#include "../InvalidLicenseScreen.h"
|
||||
//#include "BuyGameScreen.h"
|
||||
|
||||
#include "../../Font.h"
|
||||
#include "../../components/SmallButton.h"
|
||||
@@ -22,62 +20,6 @@
|
||||
#include "../DialogDefinitions.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 {
|
||||
|
||||
//
|
||||
@@ -89,8 +31,7 @@ StartMenuScreen::StartMenuScreen()
|
||||
: bHost( 2, "Start Game"),
|
||||
bJoin( 3, "Join Game"),
|
||||
bOptions( 4, "Options"),
|
||||
bBuy( 5),
|
||||
bTest( 9, "Create")
|
||||
bQuit( 5, "")
|
||||
{
|
||||
ImageDef def;
|
||||
bJoin.width = 75;
|
||||
@@ -118,8 +59,18 @@ void StartMenuScreen::init()
|
||||
buttons.push_back(&bHost);
|
||||
buttons.push_back(&bJoin);
|
||||
buttons.push_back(&bOptions);
|
||||
|
||||
//buttons.push_back(&bTest);
|
||||
|
||||
// add quit icon (same look as options header)
|
||||
{
|
||||
ImageDef def;
|
||||
def.name = "gui/touchgui.png";
|
||||
def.width = 34;
|
||||
def.height = 26;
|
||||
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
|
||||
bQuit.setImageDef(def, true);
|
||||
bQuit.scaleWhenPressed = false;
|
||||
buttons.push_back(&bQuit);
|
||||
}
|
||||
|
||||
tabButtons.push_back(&bHost);
|
||||
tabButtons.push_back(&bJoin);
|
||||
@@ -132,11 +83,8 @@ void StartMenuScreen::init()
|
||||
|
||||
copyright = "\xffMojang AB";//. Do not distribute!";
|
||||
|
||||
#ifdef PRE_ANDROID23
|
||||
std::string versionString = Common::getGameVersionString("j");
|
||||
#else
|
||||
std::string versionString = Common::getGameVersionString();
|
||||
#endif
|
||||
// always show base version string
|
||||
std::string versionString = Common::getGameVersionString();
|
||||
|
||||
#ifdef DEMO_MODE
|
||||
#ifdef __APPLE__
|
||||
@@ -152,7 +100,7 @@ void StartMenuScreen::init()
|
||||
version = versionString + " (Demo)";
|
||||
#endif
|
||||
|
||||
bJoin.active = bHost.active = bOptions.active = false;
|
||||
bJoin.active = bHost.active = bOptions.active = true;
|
||||
}
|
||||
|
||||
void StartMenuScreen::setupPositions() {
|
||||
@@ -166,37 +114,21 @@ void StartMenuScreen::setupPositions() {
|
||||
bOptions.y = yBase;
|
||||
//#endif
|
||||
|
||||
//bTest.x = 0; //width - bTest.w;
|
||||
//bTest.y = height - bTest.h;
|
||||
|
||||
// Center buttons
|
||||
bJoin.x = 0*buttonWidth + (int)(1*spacing);
|
||||
bHost.x = 1*buttonWidth + (int)(2*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;
|
||||
// quit icon top-right (use size assigned in init)
|
||||
bQuit.x = width - bQuit.width;
|
||||
bQuit.y = 0;
|
||||
|
||||
copyrightPosX = width - minecraft->font->width(copyright) - 1;
|
||||
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
|
||||
}
|
||||
|
||||
void StartMenuScreen::tick() {
|
||||
_updateLicense();
|
||||
}
|
||||
|
||||
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 defined(DEMO_MODE) || defined(APPLE_DEMO_PROMOTION)
|
||||
@@ -218,10 +150,9 @@ void StartMenuScreen::buttonClicked(::Button* button) {
|
||||
{
|
||||
minecraft->setScreen(new OptionsScreen());
|
||||
}
|
||||
if (button->id == bBuy.id)
|
||||
if (button == &bQuit)
|
||||
{
|
||||
minecraft->platform()->buyGame();
|
||||
//minecraft->setScreen(new BuyGameScreen());
|
||||
minecraft->quit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +161,10 @@ bool StartMenuScreen::isInGameScreen() { return false; }
|
||||
void StartMenuScreen::render( int xm, int ym, float a )
|
||||
{
|
||||
renderBackground();
|
||||
|
||||
// Show current username in the top-left corner
|
||||
std::string username = minecraft->options.username.empty() ? "unknown" : minecraft->options.username;
|
||||
drawString(font, std::string("Username: ") + username, 2, 2, 0xffffffff);
|
||||
|
||||
glEnable2(GL_BLEND);
|
||||
|
||||
@@ -261,27 +196,26 @@ void StartMenuScreen::render( int xm, int ym, float a )
|
||||
|
||||
drawString(font, version, versionPosX, (int)(y+h)+2, /*50,*/ 0xffcccccc);//0x666666);
|
||||
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);
|
||||
}
|
||||
Screen::render(xm, ym, a);
|
||||
glDisable2(GL_BLEND);
|
||||
}
|
||||
|
||||
void StartMenuScreen::_updateLicense()
|
||||
{
|
||||
int id = minecraft->getLicenseId();
|
||||
if (LicenseCodes::isReady(id))
|
||||
{
|
||||
if (LicenseCodes::isOk(id))
|
||||
bJoin.active = bHost.active = bOptions.active = true;
|
||||
else
|
||||
{
|
||||
bool hasBuyButton = minecraft->platform()->hasBuyButtonWhenInvalidLicense();
|
||||
minecraft->setScreen(new InvalidLicenseScreen(id, hasBuyButton));
|
||||
}
|
||||
} else {
|
||||
bJoin.active = bHost.active = bOptions.active = false;
|
||||
}
|
||||
|
||||
void StartMenuScreen::mouseClicked(int x, int y, int buttonNum) {
|
||||
const int logoX = 2;
|
||||
const int logoW = 8 + 2 + font->width("Kolyah35/minecraft-pe-0.6.1");
|
||||
const int logoY = height - 10;
|
||||
const int logoH = 10;
|
||||
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
|
||||
Screen::mouseClicked(x, y, buttonNum);
|
||||
}
|
||||
|
||||
bool StartMenuScreen::handleBackEvent( bool isDown ) {
|
||||
@@ -289,4 +223,5 @@ bool StartMenuScreen::handleBackEvent( bool isDown ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace Touch
|
||||
|
||||
|
||||
@@ -3,15 +3,8 @@
|
||||
|
||||
#include "../../Screen.h"
|
||||
#include "../../components/LargeImageButton.h"
|
||||
|
||||
|
||||
class BuyButton: public ImageButton {
|
||||
typedef ImageButton super;
|
||||
public:
|
||||
BuyButton(int id);
|
||||
void render(Minecraft* minecraft, int xm, int ym);
|
||||
};
|
||||
|
||||
#include "../../components/ImageButton.h"
|
||||
#include "../../components/TextBox.h"
|
||||
|
||||
namespace Touch {
|
||||
|
||||
@@ -23,21 +16,19 @@ public:
|
||||
|
||||
void init();
|
||||
void setupPositions();
|
||||
|
||||
void tick();
|
||||
|
||||
void render(int xm, int ym, float a);
|
||||
|
||||
void buttonClicked(Button* button);
|
||||
virtual void mouseClicked(int x, int y, int buttonNum);
|
||||
bool handleBackEvent(bool isDown);
|
||||
bool isInGameScreen();
|
||||
private:
|
||||
void _updateLicense();
|
||||
|
||||
LargeImageButton bHost;
|
||||
LargeImageButton bJoin;
|
||||
LargeImageButton bOptions;
|
||||
TButton bTest;
|
||||
BuyButton bBuy;
|
||||
ImageButton bQuit; // X close icon
|
||||
|
||||
std::string copyright;
|
||||
int copyrightPosX;
|
||||
|
||||
@@ -4,34 +4,46 @@
|
||||
#include "../../world/entity/player/Player.h"
|
||||
#include "../../world/entity/player/Inventory.h"
|
||||
|
||||
HumanoidModel::HumanoidModel( float g /*= 0*/, float yOffset /*= 0*/ )
|
||||
: holdingLeftHand(false),
|
||||
HumanoidModel::HumanoidModel( float g /*= 0*/, float yOffset /*= 0*/, int texW /*= 64*/, int texH /*= 32*/ )
|
||||
: holdingLeftHand(false),
|
||||
holdingRightHand(false),
|
||||
sneaking(false),
|
||||
bowAndArrow(false),
|
||||
head(0, 0),
|
||||
hair(32, 0),
|
||||
//ear (24, 0),
|
||||
//hair(32, 0),
|
||||
body(16, 16),
|
||||
arm0(24 + 16, 16),
|
||||
arm1(24 + 16, 16),
|
||||
leg0(0, 16),
|
||||
leg1(0, 16)
|
||||
{
|
||||
texWidth = texW;
|
||||
texHeight = texH;
|
||||
|
||||
head.setModel(this);
|
||||
hair.setModel(this);
|
||||
body.setModel(this);
|
||||
arm0.setModel(this);
|
||||
arm1.setModel(this);
|
||||
leg0.setModel(this);
|
||||
leg1.setModel(this);
|
||||
|
||||
// If the texture is 64x64, use the modern skin layout for arms/legs and add overlay layers.
|
||||
bool modernSkin = (texWidth == 64 && texHeight == 64);
|
||||
if (modernSkin) {
|
||||
// Left arm and left leg are located in the bottom half of a 64x64 skin.
|
||||
arm1.texOffs(32, 48);
|
||||
leg1.texOffs(16, 48);
|
||||
}
|
||||
|
||||
head.addBox(-4, -8, -4, 8, 8, 8, g); // Head
|
||||
head.setPos(0, 0 + yOffset, 0);
|
||||
|
||||
//ear.addBox(-3, -6, -1, 6, 6, 1, g); // Ear
|
||||
|
||||
//hair.addBox(-4, -8, -4, 8, 8, 8, g + 0.5f); // Head
|
||||
// hair.setPos(0, 0 + yOffset, 0);
|
||||
if (modernSkin) {
|
||||
hair.addBox(-4, -8, -4, 8, 8, 8, g + 0.5f); // Outer head layer (hat)
|
||||
hair.setPos(0, 0 + yOffset, 0);
|
||||
}
|
||||
|
||||
body.addBox(-4, 0, -2, 8, 12, 4, g); // Body
|
||||
body.setPos(0, 0 + yOffset, 0);
|
||||
@@ -49,6 +61,24 @@ HumanoidModel::HumanoidModel( float g /*= 0*/, float yOffset /*= 0*/ )
|
||||
leg1.mirror = true;
|
||||
leg1.addBox(-2, 0, -2, 4, 12, 4, g); // Leg1
|
||||
leg1.setPos(2, 12 + yOffset, 0);
|
||||
|
||||
if (modernSkin) {
|
||||
// Overlay layers for 64x64 skins (same geometry, different texture regions)
|
||||
body.texOffs(16, 32);
|
||||
body.addBox(-4, 0, -2, 8, 12, 4, g + 0.5f);
|
||||
|
||||
arm0.texOffs(40, 32);
|
||||
arm0.addBox(-3, -2, -2, 4, 12, 4, g + 0.5f);
|
||||
|
||||
arm1.texOffs(48, 48);
|
||||
arm1.addBox(-1, -2, -2, 4, 12, 4, g + 0.5f);
|
||||
|
||||
leg0.texOffs(0, 32);
|
||||
leg0.addBox(-2, 0, -2, 4, 12, 4, g + 0.5f);
|
||||
|
||||
leg1.texOffs(0, 48);
|
||||
leg1.addBox(-2, 0, -2, 4, 12, 4, g + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
void HumanoidModel::render(Entity* e, float time, float r, float bob, float yRot, float xRot, float scale )
|
||||
@@ -68,14 +98,24 @@ void HumanoidModel::render(Entity* e, float time, float r, float bob, float yRot
|
||||
|
||||
setupAnim(time, r, bob, yRot, xRot, scale);
|
||||
|
||||
// Sync overlay with head rotation/position
|
||||
if (texWidth == 64 && texHeight == 64) {
|
||||
hair.xRot = head.xRot;
|
||||
hair.yRot = head.yRot;
|
||||
hair.zRot = head.zRot;
|
||||
hair.y = head.y;
|
||||
}
|
||||
|
||||
head.render(scale);
|
||||
if (texWidth == 64 && texHeight == 64) {
|
||||
hair.render(scale);
|
||||
}
|
||||
body.render(scale);
|
||||
arm0.render(scale);
|
||||
arm1.render(scale);
|
||||
leg0.render(scale);
|
||||
leg1.render(scale);
|
||||
bowAndArrow = false;
|
||||
//hair.render(scale);
|
||||
}
|
||||
|
||||
void HumanoidModel::render( HumanoidModel* model, float scale )
|
||||
@@ -83,8 +123,12 @@ void HumanoidModel::render( HumanoidModel* model, float scale )
|
||||
head.yRot = model->head.yRot;
|
||||
head.y = model->head.y;
|
||||
head.xRot = model->head.xRot;
|
||||
//hair.yRot = head.yRot;
|
||||
//hair.xRot = head.xRot;
|
||||
if (texWidth == 64 && texHeight == 64) {
|
||||
hair.yRot = head.yRot;
|
||||
hair.xRot = head.xRot;
|
||||
hair.zRot = head.zRot;
|
||||
hair.y = head.y;
|
||||
}
|
||||
|
||||
arm0.xRot = model->arm0.xRot;
|
||||
arm0.zRot = model->arm0.zRot;
|
||||
@@ -96,12 +140,14 @@ void HumanoidModel::render( HumanoidModel* model, float scale )
|
||||
leg1.xRot = model->leg1.xRot;
|
||||
|
||||
head.render(scale);
|
||||
if (texWidth == 64 && texHeight == 64) {
|
||||
hair.render(scale);
|
||||
}
|
||||
body.render(scale);
|
||||
arm0.render(scale);
|
||||
arm1.render(scale);
|
||||
leg0.render(scale);
|
||||
leg1.render(scale);
|
||||
//hair.render(scale);
|
||||
}
|
||||
|
||||
void HumanoidModel::renderHorrible( float time, float r, float bob, float yRot, float xRot, float scale )
|
||||
|
||||
@@ -9,7 +9,7 @@ class ItemInstance;
|
||||
class HumanoidModel: public Model
|
||||
{
|
||||
public:
|
||||
HumanoidModel(float g = 0, float yOffset = 0);
|
||||
HumanoidModel(float g = 0, float yOffset = 0, int texW = 64, int texH = 32);
|
||||
|
||||
void setupAnim(float time, float r, float bob, float yRot, float xRot, float scale);
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
void renderHorrible(float time, float r, float bob, float yRot, float xRot, float scale);
|
||||
void onGraphicsReset();
|
||||
|
||||
ModelPart head, /*hair,*/ body, arm0, arm1, leg0, leg1;//, ear;
|
||||
ModelPart head, hair, body, arm0, arm1, leg0, leg1;//, ear;
|
||||
bool holdingLeftHand;
|
||||
bool holdingRightHand;
|
||||
bool sneaking;
|
||||
|
||||
@@ -50,12 +50,12 @@ Cube::Cube(ModelPart* modelPart, int xTexOffs, int yTexOffs, float x0, float y0,
|
||||
VertexPT* l2 = ++ptr;
|
||||
VertexPT* l3 = ++ptr;
|
||||
|
||||
polygons[0] = PolygonQuad(l1, u1, u2, l2, xTexOffs + d + w, yTexOffs + d, xTexOffs + d + w + d, yTexOffs + d + h); // Right
|
||||
polygons[1] = PolygonQuad(u0, l0, l3, u3, xTexOffs + 0, yTexOffs + d, xTexOffs + d, yTexOffs + d + h); // Left
|
||||
polygons[2] = PolygonQuad(l1, l0, u0, u1, xTexOffs + d, yTexOffs + 0, xTexOffs + d + w, yTexOffs + d); // Up
|
||||
polygons[3] = PolygonQuad(u2, u3, l3, l2, xTexOffs + d + w, yTexOffs + d, xTexOffs + d + w + w, yTexOffs); // Down
|
||||
polygons[4] = PolygonQuad(u1, u0, u3, u2, xTexOffs + d, yTexOffs + d, xTexOffs + d + w, yTexOffs + d + h); // Front
|
||||
polygons[5] = PolygonQuad(l0, l1, l2, l3, xTexOffs + d + w + d, yTexOffs + d, xTexOffs + d + w + d + w, yTexOffs + d + h); // Back
|
||||
polygons[0] = PolygonQuad(l1, u1, u2, l2, xTexOffs + d + w, yTexOffs + d, xTexOffs + d + w + d, yTexOffs + d + h, modelPart->xTexSize, modelPart->yTexSize); // Right
|
||||
polygons[1] = PolygonQuad(u0, l0, l3, u3, xTexOffs + 0, yTexOffs + d, xTexOffs + d, yTexOffs + d + h, modelPart->xTexSize, modelPart->yTexSize); // Left
|
||||
polygons[2] = PolygonQuad(l1, l0, u0, u1, xTexOffs + d, yTexOffs + 0, xTexOffs + d + w, yTexOffs + d, modelPart->xTexSize, modelPart->yTexSize); // Up
|
||||
polygons[3] = PolygonQuad(u2, u3, l3, l2, xTexOffs + d + w, yTexOffs + d, xTexOffs + d + w + w, yTexOffs, modelPart->xTexSize, modelPart->yTexSize); // Down
|
||||
polygons[4] = PolygonQuad(u1, u0, u3, u2, xTexOffs + d, yTexOffs + d, xTexOffs + d + w, yTexOffs + d + h, modelPart->xTexSize, modelPart->yTexSize); // Front
|
||||
polygons[5] = PolygonQuad(l0, l1, l2, l3, xTexOffs + d + w + d, yTexOffs + d, xTexOffs + d + w + d + w, yTexOffs + d + h, modelPart->xTexSize, modelPart->yTexSize); // Back
|
||||
|
||||
if (modelPart->mirror) {
|
||||
for (int i = 0; i < 6; i++)
|
||||
|
||||
@@ -12,15 +12,15 @@ PolygonQuad::PolygonQuad(VertexPT* v0, VertexPT* v1, VertexPT* v2, VertexPT* v3)
|
||||
}
|
||||
|
||||
PolygonQuad::PolygonQuad( VertexPT* v0, VertexPT* v1, VertexPT* v2, VertexPT* v3,
|
||||
int uu0, int vv0, int uu1, int vv1)
|
||||
: _flipNormal(false)
|
||||
int uu0, int vv0, int uu1, int vv1, float texW, float texH)
|
||||
: _flipNormal(false)
|
||||
{
|
||||
const float us = -0.002f / 64.0f;//0.1f / 64.0f;
|
||||
const float vs = -0.002f / 32.0f;//0.1f / 32.0f;
|
||||
vertices[0] = v0->remap(uu1 / 64.0f - us, vv0 / 32.0f + vs);
|
||||
vertices[1] = v1->remap(uu0 / 64.0f + us, vv0 / 32.0f + vs);
|
||||
vertices[2] = v2->remap(uu0 / 64.0f + us, vv1 / 32.0f - vs);
|
||||
vertices[3] = v3->remap(uu1 / 64.0f - us, vv1 / 32.0f - vs);
|
||||
const float us = -0.002f / texW;
|
||||
const float vs = -0.002f / texH;
|
||||
vertices[0] = v0->remap(uu1 / texW - us, vv0 / texH + vs);
|
||||
vertices[1] = v1->remap(uu0 / texW + us, vv0 / texH + vs);
|
||||
vertices[2] = v2->remap(uu0 / texW + us, vv1 / texH - vs);
|
||||
vertices[3] = v3->remap(uu1 / texW - us, vv1 / texH - vs);
|
||||
}
|
||||
|
||||
PolygonQuad::PolygonQuad( VertexPT* v0, VertexPT* v1, VertexPT* v2, VertexPT* v3,
|
||||
|
||||
@@ -11,7 +11,7 @@ class PolygonQuad
|
||||
public:
|
||||
PolygonQuad() {}
|
||||
PolygonQuad(VertexPT*,VertexPT*,VertexPT*,VertexPT*);
|
||||
PolygonQuad(VertexPT*,VertexPT*,VertexPT*,VertexPT*, int u0, int v0, int u1, int v1);
|
||||
PolygonQuad(VertexPT*,VertexPT*,VertexPT*,VertexPT*, int u0, int v0, int u1, int v1, float texW = 64.0f, float texH = 32.0f);
|
||||
PolygonQuad(VertexPT*,VertexPT*,VertexPT*,VertexPT*, float u0, float v0, float u1, float v1);
|
||||
|
||||
void mirror();
|
||||
|
||||
@@ -18,6 +18,20 @@
|
||||
#include "../../network/packet/SendInventoryPacket.h"
|
||||
#include "../../network/packet/EntityEventPacket.h"
|
||||
#include "../../network/packet/PlayerActionPacket.h"
|
||||
#include <vector>
|
||||
#include <cctype>
|
||||
#include "../../platform/log.h"
|
||||
#include "../../platform/HttpClient.h"
|
||||
#include "../../platform/CThread.h"
|
||||
#include "../../util/StringUtils.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifndef STANDALONE_SERVER
|
||||
#include "../gui/Screen.h"
|
||||
#include "../gui/screens/FurnaceScreen.h"
|
||||
@@ -32,6 +46,195 @@
|
||||
#include "../../world/item/ArmorItem.h"
|
||||
#include "../../network/packet/PlayerArmorEquipmentPacket.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static bool isBase64(unsigned char c) {
|
||||
return (std::isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
static std::string base64Decode(const std::string& encoded) {
|
||||
static const std::string base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
std::string out;
|
||||
int in_len = (int)encoded.size();
|
||||
int i = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
|
||||
while (in_len-- && (encoded[in_] != '=') && isBase64(encoded[in_])) {
|
||||
char_array_4[i++] = encoded[in_]; in_++;
|
||||
if (i == 4) {
|
||||
for (i = 0; i < 4; i++)
|
||||
char_array_4[i] = (unsigned char)base64Chars.find(char_array_4[i]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
out += char_array_3[i];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (int j = i; j < 4; j++)
|
||||
char_array_4[j] = 0;
|
||||
for (int j = 0; j < 4; j++)
|
||||
char_array_4[j] = (unsigned char)base64Chars.find(char_array_4[j]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (int j = 0; (j < i - 1); j++)
|
||||
out += char_array_3[j];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::string extractJsonString(const std::string& json, const std::string& key) {
|
||||
std::string search = "\"" + key + "\"";
|
||||
size_t pos = json.find(search);
|
||||
if (pos == std::string::npos) return "";
|
||||
pos = json.find(':', pos + search.size());
|
||||
if (pos == std::string::npos) return "";
|
||||
pos++;
|
||||
while (pos < json.size() && std::isspace((unsigned char)json[pos])) pos++;
|
||||
if (pos >= json.size() || json[pos] != '"') return "";
|
||||
pos++;
|
||||
size_t end = json.find('"', pos);
|
||||
if (end == std::string::npos) return "";
|
||||
return json.substr(pos, end - pos);
|
||||
}
|
||||
|
||||
static std::string getSkinUrlForUsername(const std::string& username) {
|
||||
if (username.empty()) {
|
||||
LOGI("[Skin] username empty\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
LOGI("[Skin] resolving UUID for user '%s'...\n", username.c_str());
|
||||
std::vector<unsigned char> body;
|
||||
std::string apiUrl = "http://api.mojang.com/users/profiles/minecraft/" + username;
|
||||
if (!HttpClient::download(apiUrl, body)) {
|
||||
LOGW("[Skin] failed to download UUID for %s\n", username.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string response(body.begin(), body.end());
|
||||
std::string uuid = extractJsonString(response, "id");
|
||||
if (uuid.empty()) {
|
||||
LOGW("[Skin] no UUID found in Mojang response for %s\n", username.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
LOGI("[Skin] UUID=%s for user %s\n", uuid.c_str(), username.c_str());
|
||||
|
||||
std::string profileUrl = "http://sessionserver.mojang.com/session/minecraft/profile/" + uuid;
|
||||
if (!HttpClient::download(profileUrl, body)) {
|
||||
LOGW("[Skin] failed to download profile for UUID %s\n", uuid.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
response.assign(body.begin(), body.end());
|
||||
std::string encoded = extractJsonString(response, "value");
|
||||
if (encoded.empty()) {
|
||||
LOGW("[Skin] no value field in profile response for UUID %s\n", uuid.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string decoded = base64Decode(encoded);
|
||||
size_t skinPos = decoded.find("\"SKIN\"");
|
||||
if (skinPos == std::string::npos) {
|
||||
LOGW("[Skin] no SKIN entry in decoded profile for UUID %s\n", uuid.c_str());
|
||||
return "";
|
||||
}
|
||||
size_t urlPos = decoded.find("\"url\"", skinPos);
|
||||
if (urlPos == std::string::npos) {
|
||||
LOGW("[Skin] no url field under SKIN for UUID %s\n", uuid.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
// extract the URL value from the substring starting at urlPos
|
||||
std::string urlFragment = decoded.substr(urlPos);
|
||||
std::string skinUrl = extractJsonString(urlFragment, "url");
|
||||
if (skinUrl.empty()) {
|
||||
LOGW("[Skin] failed to parse skin URL for UUID %s\n", uuid.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
LOGI("[Skin] skin URL for %s: %s\n", username.c_str(), skinUrl.c_str());
|
||||
return skinUrl;
|
||||
}
|
||||
|
||||
static bool ensureDirectoryExists(const std::string& path) {
|
||||
#if defined(_WIN32)
|
||||
return _mkdir(path.c_str()) == 0 || errno == EEXIST;
|
||||
#else
|
||||
struct stat st;
|
||||
if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode))
|
||||
return true;
|
||||
return mkdir(path.c_str(), 0755) == 0 || errno == EEXIST;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool fileExists(const std::string& path) {
|
||||
struct stat st;
|
||||
if (stat(path.c_str(), &st) != 0)
|
||||
return false;
|
||||
|
||||
#if defined(_WIN32)
|
||||
return (st.st_mode & _S_IFREG) != 0;
|
||||
#else
|
||||
return S_ISREG(st.st_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void* fetchSkinForPlayer(void* param) {
|
||||
LocalPlayer* player = (LocalPlayer*)param;
|
||||
if (!player) return NULL;
|
||||
|
||||
LOGI("[Skin] starting skin download for %s\n", player->name.c_str());
|
||||
|
||||
const std::string cacheDir = "data/images/skins";
|
||||
if (!ensureDirectoryExists(cacheDir)) {
|
||||
LOGW("[Skin] failed to create cache directory %s\n", cacheDir.c_str());
|
||||
}
|
||||
|
||||
std::string cacheFile = cacheDir + "/" + player->name + ".png";
|
||||
if (fileExists(cacheFile)) {
|
||||
LOGI("[Skin] using cached skin for %s\n", player->name.c_str());
|
||||
player->setTextureName("skins/" + player->name + ".png");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::string skinUrl = getSkinUrlForUsername(player->name);
|
||||
if (skinUrl.empty()) {
|
||||
LOGW("[Skin] skin URL lookup failed for %s\n", player->name.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOGI("[Skin] downloading skin from %s\n", skinUrl.c_str());
|
||||
std::vector<unsigned char> skinData;
|
||||
if (!HttpClient::download(skinUrl, skinData) || skinData.empty()) {
|
||||
LOGW("[Skin] download failed for %s\n", skinUrl.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Save to cache
|
||||
FILE* fp = fopen(cacheFile.c_str(), "wb");
|
||||
if (fp) {
|
||||
fwrite(skinData.data(), 1, skinData.size(), fp);
|
||||
fclose(fp);
|
||||
LOGI("[Skin] cached skin to %s\n", cacheFile.c_str());
|
||||
} else {
|
||||
LOGW("[Skin] failed to write skin cache %s\n", cacheFile.c_str());
|
||||
}
|
||||
|
||||
player->setTextureName("skins/" + player->name + ".png");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//@note: doesn't work completely, since it doesn't care about stairs rotation
|
||||
static bool isJumpable(int tileId) {
|
||||
return tileId != Tile::fence->id
|
||||
@@ -43,6 +246,8 @@ static bool isJumpable(int tileId) {
|
||||
&& (Tile::tiles[tileId] != NULL && Tile::tiles[tileId]->getRenderShape() != Tile::SHAPE_STAIRS);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
LocalPlayer::LocalPlayer(Minecraft* minecraft, Level* level, User* user, int dimension, bool isCreative)
|
||||
: Player(level, isCreative),
|
||||
minecraft(minecraft),
|
||||
@@ -50,15 +255,18 @@ LocalPlayer::LocalPlayer(Minecraft* minecraft, Level* level, User* user, int dim
|
||||
sentInventoryItemId(-1),
|
||||
sentInventoryItemData(-1),
|
||||
autoJumpEnabled(true),
|
||||
armorTypeHash(0)
|
||||
armorTypeHash(0),
|
||||
sprinting(false),
|
||||
sprintDoubleTapTimer(0),
|
||||
prevForwardHeld(false)
|
||||
{
|
||||
this->dimension = dimension;
|
||||
_init();
|
||||
|
||||
if (user != NULL) {
|
||||
if (user->name.length() > 0)
|
||||
//customTextureUrl = "http://s3.amazonaws.com/MinecraftSkins/" + user.name + ".png";
|
||||
this->name = user->name;
|
||||
if (user != NULL && !user->name.empty()) {
|
||||
this->name = user->name;
|
||||
// Fetch user skin from Mojang servers in the background (avoids blocking the main thread)
|
||||
new CThread(fetchSkinForPlayer, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +384,25 @@ void LocalPlayer::aiStep() {
|
||||
if (!screenCovering)
|
||||
input->tick(this);
|
||||
|
||||
// Sprint: detect W double-tap
|
||||
{
|
||||
bool forwardHeld = (input->ya > 0);
|
||||
if (forwardHeld && !prevForwardHeld && minecraft->options.useSprinting) {
|
||||
// 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 (ySlideOffset < 0.2f) ySlideOffset = 0.2f;
|
||||
}
|
||||
@@ -249,7 +476,7 @@ void LocalPlayer::move(float xa, float ya, float za) {
|
||||
|
||||
float newX = x, newZ = z;
|
||||
|
||||
if (autoJumpTime <= 0 && autoJumpEnabled)
|
||||
if (autoJumpTime <= 0 && minecraft->options.autoJump)
|
||||
{
|
||||
// auto-jump when crossing the middle of a tile, and the tile in the front is blocked
|
||||
bool jump = false;
|
||||
@@ -296,6 +523,10 @@ void LocalPlayer::releaseAllKeys()
|
||||
if (input) input->releaseAllKeys();
|
||||
}
|
||||
|
||||
float LocalPlayer::getWalkingSpeedModifier() {
|
||||
return sprinting ? 1.3f : 1.0f;
|
||||
}
|
||||
|
||||
float LocalPlayer::getFieldOfViewModifier() {
|
||||
float targetFov = 1.0f;
|
||||
if(abilities.flying) targetFov *= 1.1f;
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
|
||||
void swing();
|
||||
virtual void openTextEdit( TileEntity* tileEntity );
|
||||
virtual float getWalkingSpeedModifier();
|
||||
private:
|
||||
void calculateFlight(float xa, float ya, float za);
|
||||
bool isSolidTile(int x, int y, int z);
|
||||
@@ -99,6 +100,13 @@ private:
|
||||
int sentInventoryItemData;
|
||||
|
||||
int armorTypeHash;
|
||||
|
||||
// sprinting
|
||||
bool sprinting;
|
||||
int sprintDoubleTapTimer;
|
||||
bool prevForwardHeld;
|
||||
public:
|
||||
void setSprinting(bool sprint) { sprinting = sprint; }
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_CLIENT_PLAYER__LocalPlayer_H__*/
|
||||
|
||||
@@ -52,7 +52,7 @@ void KeyboardInput::tick( Player* player )
|
||||
ya *= 0.3f;
|
||||
}
|
||||
|
||||
#ifdef RPI
|
||||
#if defined(RPI) || defined(PLATFORM_DESKTOP)
|
||||
wantUp = jumping;
|
||||
wantDown = sneaking;
|
||||
#endif
|
||||
|
||||
@@ -137,12 +137,6 @@ void Chunk::rebuild()
|
||||
Tile* tile = Tile::tiles[tileId];
|
||||
int renderLayer = tile->getRenderLayer();
|
||||
|
||||
// if (renderLayer == l)
|
||||
// rendered |= tileRenderer.tesselateInWorld(tile, x, y, z);
|
||||
// else {
|
||||
// _layerChunks[_layerChunkCount[renderLayer]++] = cindex;
|
||||
// }
|
||||
|
||||
if (renderLayer > l) {
|
||||
renderNextLayer = true;
|
||||
doRenderLayer[renderLayer] = true;
|
||||
|
||||
@@ -270,15 +270,15 @@ void GameRenderer::renderLevel(float a) {
|
||||
screenScissorArea.w, screenScissorArea.h);
|
||||
}
|
||||
|
||||
// if(mc->options.fancyGraphics) {
|
||||
// setupFog(-1);
|
||||
// TIMER_POP_PUSH("sky");
|
||||
// glFogf(GL_FOG_START, renderDistance * 0.2f);
|
||||
// glFogf(GL_FOG_END, renderDistance *0.75);
|
||||
// levelRenderer->renderSky(a);
|
||||
// glFogf(GL_FOG_START, renderDistance * 0.6f);
|
||||
// glFogf(GL_FOG_END, renderDistance);
|
||||
// }
|
||||
if(mc->options.fancyGraphics) {
|
||||
setupFog(-1);
|
||||
TIMER_POP_PUSH("sky");
|
||||
glFogf(GL_FOG_START, renderDistance * 0.2f);
|
||||
glFogf(GL_FOG_END, renderDistance *0.75);
|
||||
levelRenderer->renderSky(a);
|
||||
glFogf(GL_FOG_START, renderDistance * 0.6f);
|
||||
glFogf(GL_FOG_END, renderDistance);
|
||||
}
|
||||
glEnable2(GL_FOG);
|
||||
setupFog(1);
|
||||
|
||||
@@ -373,7 +373,7 @@ void GameRenderer::renderLevel(float a) {
|
||||
// glDisable2(GL_FOG);
|
||||
setupFog(1);
|
||||
|
||||
if (zoom == 1) {
|
||||
if (zoom == 1 && !mc->options.F1) {
|
||||
TIMER_POP_PUSH("hand");
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
renderItemInHand(a, i);
|
||||
|
||||
@@ -354,7 +354,7 @@ void ItemInHandRenderer::render( float a )
|
||||
glRotatef2(-swing3 * 20, 0, 0, 1);
|
||||
// glRotatef2(-swing2 * 80, 1, 0, 0);
|
||||
|
||||
mc->textures->loadAndBindTexture("mob/char.png");
|
||||
mc->textures->loadAndBindTexture(player->getTexture());
|
||||
glTranslatef2(-1.0f, +3.6f, +3.5f);
|
||||
glRotatef2(120, 0, 0, 1);
|
||||
glRotatef2(180 + 20, 1, 0, 0);
|
||||
|
||||
@@ -16,7 +16,7 @@ typedef struct TextureData {
|
||||
TextureData()
|
||||
: w(0),
|
||||
h(0),
|
||||
data(NULL),
|
||||
data(nullptr),
|
||||
numBytes(0),
|
||||
transparent(true),
|
||||
memoryHandledExternally(false),
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../Options.h"
|
||||
#include "../../platform/time.h"
|
||||
#include "../../AppPlatform.h"
|
||||
#include "../../util/StringUtils.h"
|
||||
|
||||
/*static*/ int Textures::textureChanges = 0;
|
||||
/*static*/ bool Textures::MIPMAP = false;
|
||||
@@ -64,7 +65,8 @@ TextureId Textures::loadTexture( const std::string& resourceName, bool inTexture
|
||||
if (it != idMap.end())
|
||||
return it->second;
|
||||
|
||||
TextureData texdata = platform->loadTexture(resourceName, inTextureFolder);
|
||||
bool isUrl = Util::startsWith(resourceName, "http://") || Util::startsWith(resourceName, "https://");
|
||||
TextureData texdata = platform->loadTexture(resourceName, isUrl ? false : inTextureFolder);
|
||||
if (texdata.data)
|
||||
return assignTexture(resourceName, texdata);
|
||||
else if (texdata.identifier != InvalidId) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "TileRenderer.h"
|
||||
#include "Chunk.h"
|
||||
#include "../Minecraft.h"
|
||||
#include "Tesselator.h"
|
||||
|
||||
@@ -56,6 +57,7 @@ bool TileRenderer::tesselateBlockInWorld( Tile* tt, int x, int y, int z, float r
|
||||
float c2 = 0.8f;
|
||||
float c3 = 0.6f;
|
||||
|
||||
|
||||
float r11 = c11 * r;
|
||||
float g11 = c11 * g;
|
||||
float b11 = c11 * b;
|
||||
@@ -128,6 +130,7 @@ bool TileRenderer::tesselateBlockInWorld( Tile* tt, int x, int y, int z, float r
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
void TileRenderer::tesselateInWorld( Tile* tile, int x, int y, int z, int fixedTexture )
|
||||
{
|
||||
this->fixedTexture = fixedTexture;
|
||||
|
||||
@@ -51,7 +51,7 @@ EntityRenderDispatcher::EntityRenderDispatcher()
|
||||
assign( ER_SPIDER_RENDERER, new SpiderRenderer());
|
||||
assign( ER_TNT_RENDERER, new TntRenderer());
|
||||
assign( ER_ARROW_RENDERER, new ArrowRenderer());
|
||||
assign( ER_PLAYER_RENDERER, new PlayerRenderer(new HumanoidModel(), 0));
|
||||
assign( ER_PLAYER_RENDERER, new PlayerRenderer(new HumanoidModel(0, 0, 64, 64), 0));
|
||||
assign( ER_THROWNEGG_RENDERER, new ItemSpriteRenderer(Item::egg->getIcon(0)));
|
||||
assign( ER_SNOWBALL_RENDERER, new ItemSpriteRenderer(Item::snowBall->getIcon(0)));
|
||||
assign( ER_PAINTING_RENDERER, new PaintingRenderer());
|
||||
|
||||
@@ -14,8 +14,8 @@ static const std::string armorFilenames[10] = {
|
||||
|
||||
PlayerRenderer::PlayerRenderer( HumanoidModel* humanoidModel, float shadow )
|
||||
: super(humanoidModel, shadow),
|
||||
armorParts1(new HumanoidModel(1.0f)),
|
||||
armorParts2(new HumanoidModel(0.5f))
|
||||
armorParts1(new HumanoidModel(1.0f, 0, 64, 64)),
|
||||
armorParts2(new HumanoidModel(0.5f, 0, 64, 64))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
#if defined(__APPLE__)
|
||||
#import <OpenGLES/ES1/gl.height>
|
||||
#import <OpenGLES/ES1/glext.height>
|
||||
#elif defined(ANDROID)
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/glext.h>
|
||||
#else
|
||||
#include <glad/glad.h>
|
||||
#if defined(ANDROID)
|
||||
#include<GLES/glext.h>
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
// Uglyness to fix redeclaration issues
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
|
||||
void destroy() const {
|
||||
if (isValid()) {
|
||||
delete buffer;
|
||||
buffer = 0;
|
||||
}
|
||||
}
|
||||
@@ -60,7 +61,7 @@ private:
|
||||
mutable char* buffer;
|
||||
};
|
||||
|
||||
#if !defined(PRE_ANDROID23) && !defined(__APPLE__) && !defined(RPI)
|
||||
#if !defined(PRE_ANDROID23) && !defined(__APPLE__) && !defined(RPI)
|
||||
|
||||
extern SoundDesc SA_cloth1;
|
||||
extern SoundDesc SA_cloth2;
|
||||
|
||||
@@ -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) {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#if defined(ANDROID) && !defined(PRE_ANDROID23)
|
||||
#include "../../platform/audio/SoundSystemSL.h"
|
||||
#elif defined(__APPLE__) || defined (PLATFORM_DESKTOP)
|
||||
#elif defined(__APPLE__) || defined(PLATFORM_DESKTOP)
|
||||
#include "../../platform/audio/SoundSystemAL.h"
|
||||
#else
|
||||
#include "../../platform/audio/SoundSystem.h"
|
||||
@@ -23,7 +23,7 @@ class SoundEngine
|
||||
|
||||
#if defined(ANDROID) && !defined(PRE_ANDROID23) && !defined(RPI)
|
||||
SoundSystemSL soundSystem;
|
||||
#elif defined(__APPLE__) || defined (PLATFORM_DESKTOP)
|
||||
#elif defined(__APPLE__) || defined(PLATFORM_DESKTOP)
|
||||
SoundSystemAL soundSystem;
|
||||
#else
|
||||
SoundSystem soundSystem;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "App.h"
|
||||
#include "AppPlatform_android.h"
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
// Horrible, I know. / A
|
||||
#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);
|
||||
app->externalStoragePath = 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);
|
||||
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
#include "App.h"
|
||||
#include "AppPlatform_android.h"
|
||||
|
||||
// JNI keycode constants
|
||||
#include <android/keycodes.h>
|
||||
|
||||
//#include "main_android_java.h"
|
||||
#include "platform/input/Multitouch.h"
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#define gettid() ((int)syscall(SYS_gettid))
|
||||
|
||||
// Horrible, I know. / A
|
||||
#ifndef MAIN_CLASS
|
||||
@@ -39,7 +45,12 @@ static void setupExternalPath(JNIEnv* env, MAIN_CLASS* app)
|
||||
const char* str = env->GetStringUTFChars((jstring) pathString, NULL);
|
||||
app->externalStoragePath = 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);
|
||||
}
|
||||
@@ -57,6 +68,7 @@ static void pointerMove(int pointerId, int x, int y) {
|
||||
|
||||
static App* gApp = 0;
|
||||
static AppContext gContext;
|
||||
static bool g_inNativeOnCreate = false;
|
||||
|
||||
extern "C" {
|
||||
JNIEXPORT jint JNICALL
|
||||
@@ -81,34 +93,53 @@ Java_com_mojang_minecraftpe_MainActivity_nativeUnregisterThis(JNIEnv* env, jobje
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_mojang_minecraftpe_MainActivity_nativeOnCreate(JNIEnv* env) {
|
||||
LOGI("@nativeOnCreate\n");
|
||||
Java_com_mojang_minecraftpe_MainActivity_nativeOnCreate(JNIEnv* env, jobject thiz, jint screenWidth, jint screenHeight) {
|
||||
LOGI("@nativeOnCreate w=%d h=%d\n", (int)screenWidth, (int)screenHeight);
|
||||
g_inNativeOnCreate = true;
|
||||
|
||||
appPlatform.instance = g_pActivity;
|
||||
appPlatform.initConsts();
|
||||
appPlatform.setScreenDimensions((int)screenWidth, (int)screenHeight);
|
||||
LOGI("nativeOnCreate: screen set, no initConsts needed\n");
|
||||
gContext.doRender = false;
|
||||
gContext.platform = &appPlatform;
|
||||
|
||||
LOGI("nativeOnCreate: creating gApp\n");
|
||||
gApp = new MAIN_CLASS();
|
||||
LOGI("nativeOnCreate: gApp=%p\n", 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);
|
||||
}
|
||||
|
||||
static int s_surfaceCreatedCount = 0;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
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) {
|
||||
// gApp->setSize( gContext.platform->getScreenWidth(),
|
||||
// gContext.platform->getScreenHeight(),
|
||||
// gContext.platform->isTouchscreen());
|
||||
|
||||
// Don't call onGraphicsReset the first time
|
||||
if (gApp->isInited())
|
||||
if (gApp->isInited()) {
|
||||
LOGI("nativeOnSurfaceCreated: calling onGraphicsReset\n");
|
||||
gApp->onGraphicsReset(gContext);
|
||||
}
|
||||
|
||||
if (!gApp->isInited())
|
||||
if (!gApp->isInited()) {
|
||||
LOGI("nativeOnSurfaceCreated: calling init\n");
|
||||
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
|
||||
//
|
||||
// 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
|
||||
Java_com_mojang_minecraftpe_MainActivity_nativeOnKeyDown(JNIEnv* env, jclass cls, jint 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
|
||||
Java_com_mojang_minecraftpe_MainActivity_nativeOnKeyUp(JNIEnv* env, jclass cls, jint keyCode) {
|
||||
LOGI("@nativeOnKeyUp: %d\n", (int)keyCode);
|
||||
Keyboard::feed(keyCode, false);
|
||||
int mapped = androidKeyToInternal(keyCode);
|
||||
Keyboard::feed(mapped, false);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "SharedConstants.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "platform/input/Keyboard.h"
|
||||
#include "platform/input/Mouse.h"
|
||||
#include "platform/input/Multitouch.h"
|
||||
@@ -25,6 +27,7 @@ int transformKey(int glfwkey) {
|
||||
case GLFW_KEY_BACKSPACE: return Keyboard::KEY_BACKSPACE;
|
||||
case GLFW_KEY_LEFT_SHIFT: return Keyboard::KEY_LSHIFT;
|
||||
case GLFW_KEY_ENTER: return Keyboard::KEY_RETURN;
|
||||
case GLFW_KEY_LEFT_CONTROL: return Keyboard::KEY_LEFT_CTRL;
|
||||
default: return glfwkey;
|
||||
}
|
||||
}
|
||||
@@ -32,6 +35,20 @@ int transformKey(int glfwkey) {
|
||||
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -126,8 +143,9 @@ int main(void) {
|
||||
glfwSetWindowSizeCallback(window, window_size_callback);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLES1Loader((GLADloadproc)glfwGetProcAddress);
|
||||
glfwSwapInterval(1);
|
||||
gladLoadGLES1Loader((GLADloadproc)winGLLoader);
|
||||
glfwSwapInterval(0);
|
||||
glPatchDesktopCompat();
|
||||
#endif
|
||||
|
||||
App* app = new MAIN_CLASS();
|
||||
@@ -139,11 +157,23 @@ int main(void) {
|
||||
g_app->setSize(appContext.platform->getScreenWidth(), appContext.platform->getScreenHeight());
|
||||
|
||||
// Main event loop
|
||||
using clock = std::chrono::steady_clock;
|
||||
while(!glfwWindowShouldClose(window) && !app->wantToQuit()) {
|
||||
auto frameStart = clock::now();
|
||||
|
||||
app->update();
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
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;
|
||||
|
||||
@@ -113,6 +113,14 @@ LRESULT WINAPI windowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
||||
Multitouch::feed(0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0);
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEWHEEL: {
|
||||
// wheel delta is multiples of WHEEL_DELTA (120); convert to +/-1
|
||||
int delta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
|
||||
short x = GET_X_LPARAM(lParam);
|
||||
short y = GET_Y_LPARAM(lParam);
|
||||
Mouse::feed(MouseAction::ACTION_WHEEL, 0, x, y, 0, delta);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (uMsg == WM_NCDESTROY) g_running = false;
|
||||
else {
|
||||
|
||||
@@ -134,6 +134,11 @@ void ServerSideNetworkHandler::displayGameMessage(const std::string& message)
|
||||
raknetInstance->send(packet);
|
||||
}
|
||||
|
||||
void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPacket* packet)
|
||||
{
|
||||
displayGameMessage(packet->message);
|
||||
}
|
||||
|
||||
void ServerSideNetworkHandler::onNewClient(const RakNet::RakNetGUID& clientGuid)
|
||||
{
|
||||
LOGI("onNewClient, client guid: %s\n", clientGuid.ToString());
|
||||
@@ -256,6 +261,11 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID
|
||||
SetTimePacket(level->getTime()).write(&bitStream);
|
||||
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
|
||||
const PlayerList& players = level->players;
|
||||
for (unsigned int i = 0; i < players.size(); i++) {
|
||||
|
||||
@@ -57,18 +57,18 @@ public:
|
||||
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, SignUpdatePacket* packet);
|
||||
virtual void handle(const RakNet::RakNetGUID& source, ChatPacket* packet);
|
||||
|
||||
bool allowsIncomingConnections() { return _allowIncoming; }
|
||||
void allowIncomingConnections(bool doAllow);
|
||||
|
||||
Player* popPendingPlayer(const RakNet::RakNetGUID& source);
|
||||
|
||||
void displayGameMessage(const std::string& message);
|
||||
private:
|
||||
|
||||
void redistributePacket(Packet* packet, const RakNet::RakNetGUID& fromPlayer);
|
||||
void displayGameMessage(const std::string& message);
|
||||
|
||||
Player* getPlayer(const RakNet::RakNetGUID& source);
|
||||
private:
|
||||
|
||||
Minecraft* minecraft;
|
||||
Level* level;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user