diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2ad9186a4..1b65eb467 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,16 +18,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Install Dependencies run: | sudo apt-get update - sudo apt-get install --no-install-recommends -y build-essential cmake ninja-build libopenal-dev libsdl2-dev zlib1g-dev + sudo apt-get install --no-install-recommends -y \ + build-essential \ + cmake ninja-build \ + libopenal-dev \ + libsdl2-dev zlib1g-dev - name: Build run: | - cd platforms/sdl mkdir build cd build cmake -GNinja ${{ matrix.flags }} .. @@ -37,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Install Dependencies @@ -51,7 +54,7 @@ jobs: runs-on: macos-latest steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Install MacPorts @@ -62,6 +65,7 @@ jobs: sudo port install libpng +universal - name: Build macOS Archive run: | + ln -s sound/openal platforms/openal # Please someone fix this properly later. cd platforms/macos/projects/Minecraft xcodebuild -scheme "MinecraftClient.SDL2" \ -archivePath $RUNNER_TEMP/GitHubActions_MacOS_SDL2.xcarchive \ @@ -103,11 +107,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Setup JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' @@ -116,3 +120,32 @@ jobs: run: | cd ${{ matrix.directory }} ./gradlew build + mingw: + strategy: + fail-fast: false + matrix: + include: + - name: Win32 + flags: "-DREMCPE_PLATFORM=windows" + - name: SDL + flags: "-DREMCPE_PLATFORM=sdl" + name: MinGW-w64 (${{ matrix.name }}) + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + submodules: true + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends -y \ + build-essential \ + cmake ninja-build \ + mingw-w64 + - name: Build + run: | + mkdir build + cd build + cmake -GNinja -DCMAKE_TOOLCHAIN_FILE=../cmake/mingw-w64-toolchain.cmake ${{ matrix.flags }} .. + cmake --build . \ No newline at end of file diff --git a/.gitignore b/.gitignore index 22c107a57..c3708db6d 100644 --- a/.gitignore +++ b/.gitignore @@ -123,7 +123,7 @@ xcuserdata/ /sound_data # Ignore linux/mingw build artifacts. -/build +/build* /minecraftcpp /minecraftcpp.exe @@ -187,9 +187,7 @@ xcuserdata/ /game/assets/gui/startmenu/sm_play.png /game/assets/gui/startmenu/sm_multi.png /game/assets/gui/startmenu/sm_options.png -/game/assets/gui/touchgui.png -/game/assets/gui/feedback_fill.png -/game/assets/gui/feedback_outer.png + /game/assets/snow.png # Ignore all native iOS UI assets. /game/assets/app/ios/ @@ -242,3 +240,12 @@ xcuserdata/ # Ignore options.txt - where your configuration will be saved /game/options.txt /game/assetsO + +# CLion +/.idea +/cmake-build-* + +# Sound +/tools/__pycache__ +/tools/venv +/game/assets/sound diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..63d18d425 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 3.16.0) +project(reminecraftpe) + +# Store Output In Top-Level Build Directory +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") + +# WASM +if(EMSCRIPTEN) + function(add_compile_and_link_options) + add_compile_options(${ARGV}) + add_link_options(${ARGV}) + endfunction() + set(CMAKE_EXECUTABLE_SUFFIX ".js") + add_link_options("$<$:-gsource-map>") + add_link_options(-Wno-pthreads-mem-growth -sALLOW_MEMORY_GROWTH=1) +endif() + +# Clang +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + add_compile_options(-Wno-inconsistent-missing-override -Wno-enum-compare-switch -Wno-register) +endif() + +# Windows Linking +if(WIN32) + add_link_options( + -static-libgcc + -static-libstdc++ + ) +endif() + +# HaikuOS Network Library +if(HAIKU) + link_libraries(network) +endif() + +# Threading +if(EMSCRIPTEN) + add_compile_and_link_options(-pthread) +else() + find_package(Threads) + link_libraries(Threads::Threads) +endif() + +# Android Logging +if(ANDROID) + link_libraries(log) +endif() + +# Load Common Code +add_subdirectory(source) + +# Load Platform-Specific Code +add_subdirectory(platforms) + +# Assets +if(EMSCRIPTEN) + target_link_options(reminecraftpe PRIVATE --use-preload-plugins --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/game@/") +else() + file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/game/assets" "${CMAKE_CURRENT_BINARY_DIR}/assets" SYMBOLIC) +endif() \ No newline at end of file diff --git a/README.md b/README.md index ebb4e7b9e..d72711ee5 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,12 @@ based on Minecraft PE v0.1.3. * To keep the source code layout similar to the original Minecraft PE (reconstructed from clues hidden within certain versions of the game, such as the 0.1.0 touch prototype/debug build) * To port the game to more platforms, such as Windows (including older versions), Xbox 360, Wii, and more. - Currently there are ports for: + Currently, there are ports for: * Windows XP-11 * Android (thanks to [Stom](https://github.com/Stommm) for the help) * Linux * WebGL - * Mac OS (port by [BrentDaMage](https://github.com/BrentDaMage)) + * macOS (port by [BrentDaMage](https://github.com/BrentDaMage)) * iOS (3.0 and above; port by [BrentDaMage](https://github.com/BrentDaMage)) * HaikuOS (thanks to [SanyaSho](https://github.com/SanyaSho)) * Xbox 360 (work in progress; port by [BrentDaMage](https://github.com/BrentDaMage)) @@ -36,7 +36,7 @@ Note: While the original Minecraft PE v0.1.3 may not work on newer devices, ReMi ## License information -This project is licensed under the [BSD 1 clause license](LICENSE.md). However, it contains third party +This project is licensed under the [BSD 1 clause license](LICENSE.txt). However, it contains third party software with different but compatible licenses: - [RakNet](https://github.com/facebookarchive/RakNet): [Licensed under the BSD 2 clause license](thirdparty/raknet/LICENSE) @@ -142,7 +142,6 @@ This project uses CMake on Linux. Just like WebAssembly, the game assets must be #### How To Build ```sh -cd platforms/sdl mkdir build && cd build cmake -GNinja .. cmake --build . diff --git a/build-wasm.sh b/build-wasm.sh index bc1265706..033140ec2 100755 --- a/build-wasm.sh +++ b/build-wasm.sh @@ -31,7 +31,7 @@ mkdir -p build cd build # Configure Build -emcmake cmake -GNinja "$@" ../../platforms/sdl +emcmake cmake -GNinja "$@" ../../ # Build cmake --build . diff --git a/cmake/mingw-w64-toolchain.cmake b/cmake/mingw-w64-toolchain.cmake new file mode 100644 index 000000000..9610577a5 --- /dev/null +++ b/cmake/mingw-w64-toolchain.cmake @@ -0,0 +1,11 @@ +# https://gist.github.com/peterspackman/8cf73f7f12ba270aa8192d6911972fe8 +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) +set(CMAKE_C_COMPILER "${TOOLCHAIN_PREFIX}-gcc") +set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PREFIX}-g++") +set(CMAKE_Fortran_COMPILER "${TOOLCHAIN_PREFIX}-gfortran") +set(CMAKE_RC_COMPILER "${TOOLCHAIN_PREFIX}-windres") +set(CMAKE_FIND_ROOT_PATH "/usr/${TOOLCHAIN_PREFIX}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) \ No newline at end of file diff --git a/compat/KeyCodes.hpp b/compat/KeyCodes.hpp index 783a04595..f2316c5f1 100644 --- a/compat/KeyCodes.hpp +++ b/compat/KeyCodes.hpp @@ -23,7 +23,7 @@ enum eSDLVirtualKeys #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN - #include + #include #elif __APPLE__ // https://i.stack.imgur.com/LD8pT.png #define AKEYCODE_FORWARD_DEL 0x75 diff --git a/platforms/CMakeLists.txt b/platforms/CMakeLists.txt new file mode 100644 index 000000000..daf641034 --- /dev/null +++ b/platforms/CMakeLists.txt @@ -0,0 +1,12 @@ +project(reminecraftpe-platforms) + +# Select & Build +set(DEFAULT_PLATFORM "sdl") +if(WIN32) + set(DEFAULT_PLATFORM "windows") +endif() +set(REMCPE_PLATFORM "${DEFAULT_PLATFORM}" CACHE STRING "ReMCPE Platform (Check /platforms)") +add_subdirectory("${REMCPE_PLATFORM}") + +# Load Sound +add_subdirectory(sound) \ No newline at end of file diff --git a/platforms/android/AppPlatform_android.cpp b/platforms/android/AppPlatform_android.cpp index 117f68b13..1f9493cec 100644 --- a/platforms/android/AppPlatform_android.cpp +++ b/platforms/android/AppPlatform_android.cpp @@ -9,7 +9,7 @@ #include #include "AppPlatform_android.hpp" -#include "SoundSystemSL.hpp" +#include "CustomSoundSystem.hpp" #include "client/player/input/Mouse.hpp" #include "stb_image.h" @@ -174,7 +174,7 @@ SoundSystem* const AppPlatform_android::getSoundSystem() const void AppPlatform_android::initSoundSystem() { if (!m_pSoundSystem) - m_pSoundSystem = new SoundSystemSL(); + m_pSoundSystem = new SOUND_SYSTEM(); else LOG_E("Trying to initialize SoundSystem more than once!"); } @@ -357,3 +357,22 @@ int AppPlatform_android::getKeyboardUpOffset() // For now we'll just return 1/2 of the screen height. That ought to cover most cases. return m_ScreenHeight / 2; } + +AssetFile AppPlatform_android::readAssetFile(const std::string& str) const +{ + std::string realPath = str; + if (realPath.size() && realPath[0] == '/') + // trim it off + realPath = realPath.substr(1); + + AAsset* asset = AAssetManager_open(m_app->activity->assetManager, str.c_str(), AASSET_MODE_BUFFER); + if (!asset) { + LOG_E("File %s couldn't be opened", realPath.c_str()); + return AssetFile(); + } + size_t cnt = AAsset_getLength(asset); + unsigned char* buffer = new unsigned char[cnt]; + AAsset_read(asset, (void*)buffer, cnt); + AAsset_close(asset); + return AssetFile(ssize_t(cnt), buffer); +} \ No newline at end of file diff --git a/platforms/android/AppPlatform_android.hpp b/platforms/android/AppPlatform_android.hpp index 3e6de84f6..e67f85ec3 100644 --- a/platforms/android/AppPlatform_android.hpp +++ b/platforms/android/AppPlatform_android.hpp @@ -62,6 +62,8 @@ class AppPlatform_android : public AppPlatform void initAndroidApp(android_app* ptr); void setExternalStoragePath(const std::string& path); + AssetFile readAssetFile(const std::string&) const override; + private: void changeKeyboardVisibility(bool bShown); diff --git a/platforms/android/project/app/src/main/cpp/CMakeLists.txt b/platforms/android/CMakeLists.txt similarity index 63% rename from platforms/android/project/app/src/main/cpp/CMakeLists.txt rename to platforms/android/CMakeLists.txt index 6a03a611f..634657cae 100644 --- a/platforms/android/project/app/src/main/cpp/CMakeLists.txt +++ b/platforms/android/CMakeLists.txt @@ -1,31 +1,28 @@ cmake_minimum_required(VERSION 3.16.0) project(reminecraftpe-android) -# Project Root -set(MC_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../..") - # Native Android Build -add_compile_definitions(USE_NATIVE_ANDROID) -set(USE_NATIVE_ANDROID TRUE) +target_compile_definitions(reminecraftpe-core PUBLIC USE_NATIVE_ANDROID) # Build add_library(reminecraftpe SHARED - "${MC_ROOT}/platforms/android/android_native_app_glue.c" - "${MC_ROOT}/platforms/android/AppPlatform_android.cpp" - "${MC_ROOT}/platforms/android/SoundSystemSL.cpp" - "${MC_ROOT}/platforms/android/main.cpp" + android_native_app_glue.c + AppPlatform_android.cpp + main.cpp ) # Core -add_subdirectory("${MC_ROOT}/source" source) target_link_libraries(reminecraftpe reminecraftpe-core) +# OpenGL +target_link_libraries(reminecraftpe-core PUBLIC EGL GLESv1_CM) + # stb_image -add_subdirectory("${MC_ROOT}/thirdparty/stb_image" stb_image) +add_subdirectory(../../thirdparty/stb_image stb_image) target_link_libraries(reminecraftpe stb_image) # Extra Dependencies -target_link_libraries(reminecraftpe android OpenSLES) +target_link_libraries(reminecraftpe android) # Check for the presence of some optional asset based features. if(EXISTS "${MC_ROOT}/game/assets/gui/background/panorama_0.png") diff --git a/platforms/android/project/app/build.gradle b/platforms/android/project/app/build.gradle index 84b308c56..7743e2ab1 100644 --- a/platforms/android/project/app/build.gradle +++ b/platforms/android/project/app/build.gradle @@ -29,7 +29,7 @@ android { // testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { - arguments '-DANDROID_PLATFORM=android-21', '-DANDROID_STL=c++_static' + arguments '-DANDROID_PLATFORM=android-21', '-DANDROID_STL=c++_static', '-DREMCPE_PLATFORM=android', '-DREMCPE_SOUND_PLATFORM=opensl' abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } @@ -47,7 +47,7 @@ android { } externalNativeBuild { cmake { - path file('src/main/cpp/CMakeLists.txt') + path '../../../../CMakeLists.txt' version '3.22.1' } } diff --git a/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj b/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj index 344ee6386..f852eac8f 100644 --- a/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj +++ b/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj @@ -2173,7 +2173,7 @@ 84EAE8E12AF1EAB5000894E8 /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; 84EAE8E32AF1EABE000894E8 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 84EAE8E62AF1EAFA000894E8 /* SoundSystemAL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SoundSystemAL.cpp; sourceTree = ""; }; - 84EAE8E72AF1EAFA000894E8 /* SoundSystemAL.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SoundSystemAL.hpp; sourceTree = ""; }; + 84EAE8E72AF1EAFA000894E8 /* CustomSoundSystem.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CustomSoundSystem.hpp; sourceTree = ""; }; 84EAE8F02AF1EAFA000894E8 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; 84EAE8F12AF1EAFA000894E8 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; 84ED99D42AFF12D1003B6AF0 /* minecraftpe.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = minecraftpe.entitlements; sourceTree = ""; }; @@ -3946,7 +3946,7 @@ isa = PBXGroup; children = ( 84EAE8E62AF1EAFA000894E8 /* SoundSystemAL.cpp */, - 84EAE8E72AF1EAFA000894E8 /* SoundSystemAL.hpp */, + 84EAE8E72AF1EAFA000894E8 /* CustomSoundSystem.hpp */, ); path = openal; sourceTree = ""; diff --git a/platforms/openal/CMakeLists.txt b/platforms/openal/CMakeLists.txt deleted file mode 100644 index 36450e0fe..000000000 --- a/platforms/openal/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -cmake_minimum_required(VERSION 3.16.0) -project(reminecraftpe-openal) - -# Build -add_library(reminecraftpe-openal STATIC - SoundSystemAL.cpp -) - -# Core -target_link_libraries(reminecraftpe-openal PUBLIC reminecraftpe-core) - -# OpenAL -if(ANDROID) - # Use Vendored OpenAL - set(ALSOFT_UTILS FALSE CACHE BOOL "" FORCE) - set(ALSOFT_EXAMPLES FALSE CACHE BOOL "" FORCE) - set(ALSOFT_TESTS FALSE CACHE BOOL "" FORCE) - set(ALSOFT_REQUIRE_OPENSL TRUE CACHE BOOL "" FORCE) - add_subdirectory(../../thirdparty/OpenAL openal EXCLUDE_FROM_ALL) - target_link_libraries(reminecraftpe-openal PUBLIC OpenAL::OpenAL) -elseif(EMSCRIPTEN) - # Use Emscripten's OpenAL - target_link_libraries(reminecraftpe-openal PUBLIC openal) -else() - # Use System ZLib - find_library(OPENAL_LIBRARY NAMES openal REQUIRED) - target_link_libraries(reminecraftpe-openal PUBLIC "${OPENAL_LIBRARY}") -endif() - -# Headers -target_include_directories(reminecraftpe-openal PUBLIC .) diff --git a/platforms/sdl/CMakeLists.txt b/platforms/sdl/CMakeLists.txt index b5cff20c9..ddfe18b54 100644 --- a/platforms/sdl/CMakeLists.txt +++ b/platforms/sdl/CMakeLists.txt @@ -2,36 +2,10 @@ cmake_minimum_required(VERSION 3.16.0) project(reminecraftpe-sdl) # SDL Build -add_compile_definitions(USE_SDL USE_OPENAL HANDLE_CHARS_SEPARATELY) -set(USE_SDL TRUE) - -# WASM -if(EMSCRIPTEN) - function(add_compile_and_link_options) - add_compile_options(${ARGV}) - add_link_options(${ARGV}) - endfunction() - set(CMAKE_EXECUTABLE_SUFFIX ".js") - add_link_options("$<$:-gsource-map>") -endif() - -# Clang -if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - add_compile_options(-Wno-inconsistent-missing-override -Wno-enum-compare-switch -Wno-register) -endif() - -# Network library -if(HAIKU) - link_libraries(network) -endif() - -# Threads -if(EMSCRIPTEN) - add_compile_and_link_options(-pthread) -else() - find_package(Threads) - link_libraries(Threads::Threads) -endif() +target_compile_definitions(reminecraftpe-core + PUBLIC USE_SDL + PUBLIC HANDLE_CHARS_SEPARATELY +) # Build set(SOURCES @@ -51,13 +25,8 @@ else() endif() # Core -add_subdirectory(../../source source) target_link_libraries(reminecraftpe reminecraftpe-core) -# OpenAL -add_subdirectory(../openal openal) -target_link_libraries(reminecraftpe reminecraftpe-openal) - # stb_image (If Needed) if(NOT EMSCRIPTEN) add_subdirectory(../../thirdparty/stb_image stb_image) @@ -65,21 +34,47 @@ if(NOT EMSCRIPTEN) endif() # SDL +add_library(SDL INTERFACE) +if(ANDROID OR WIN32) + # Use Vendored SDL2 (Only For Android) + add_subdirectory(../../thirdparty/SDL2/src SDL EXCLUDE_FROM_ALL) + target_link_libraries(SDL INTERFACE SDL2::SDL2) +elseif(EMSCRIPTEN) + # Use Emscripten's SDL2 + set(SDL_FLAG -sUSE_SDL=2) + target_compile_options(SDL INTERFACE "${SDL_FLAG}") + target_link_options(SDL INTERFACE "${SDL_FLAG}") +else() + # Use System SDL2 + find_package(SDL2 REQUIRED) + target_link_libraries(SDL INTERFACE SDL2::SDL2) +endif() +target_link_libraries(reminecraftpe-core PUBLIC SDL) if(TARGET SDL2::SDL2main) target_link_libraries(reminecraftpe SDL2::SDL2main) endif() +# OpenGL +if(NOT EMSCRIPTEN AND NOT ANDROID AND NOT WIN32) + option(USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" TRUE) +else() + set(USE_GLES1_COMPATIBILITY_LAYER TRUE CACHE BOOL "" FORCE) +endif() +if(USE_GLES1_COMPATIBILITY_LAYER) + add_subdirectory(../../thirdparty/gles-compatibility-layer gles-compatibility-layer) + target_link_libraries(reminecraftpe-core PUBLIC gles-compatibility-layer) + target_compile_definitions(reminecraftpe-core PUBLIC USE_GLES1_COMPATIBILITY_LAYER) + if(EMSCRIPTEN) + # Use WebGL 2 + target_link_options(reminecraftpe-core PUBLIC -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2) + endif() +else() + find_package(OpenGL REQUIRED) + target_link_libraries(reminecraftpe-core PUBLIC OpenGL::GL) +endif() + # WASM if(EMSCRIPTEN) - target_link_options(reminecraftpe PRIVATE -Wno-pthreads-mem-growth) - target_link_options(reminecraftpe PRIVATE -sALLOW_MEMORY_GROWTH=1) # Export Resize Function target_link_options(reminecraftpe PRIVATE -sEXPORTED_FUNCTIONS=_main,_resize_from_js -sEXPORTED_RUNTIME_METHODS=ccall) endif() - -# Assets -if(EMSCRIPTEN) - target_link_options(reminecraftpe PRIVATE --use-preload-plugins --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/../../game@/") -elseif(NOT ANDROID) - file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/../../game/assets" "${CMAKE_CURRENT_BINARY_DIR}/assets" SYMBOLIC) -endif() diff --git a/platforms/sdl/android/app/build.gradle b/platforms/sdl/android/app/build.gradle index dddb581b7..f08bc84ae 100644 --- a/platforms/sdl/android/app/build.gradle +++ b/platforms/sdl/android/app/build.gradle @@ -33,7 +33,7 @@ android { } externalNativeBuild { cmake { - path '../../CMakeLists.txt' + path '../../../../CMakeLists.txt' version '3.22.1' } } diff --git a/platforms/sdl/android/app/src/main/AndroidManifest.xml b/platforms/sdl/android/app/src/main/AndroidManifest.xml index 99abe3faf..db14630f1 100644 --- a/platforms/sdl/android/app/src/main/AndroidManifest.xml +++ b/platforms/sdl/android/app/src/main/AndroidManifest.xml @@ -5,8 +5,8 @@ android:versionName="1.0" android:installLocation="auto"> - - + + size(io); - if (size == -1) - { - LOG_E("Error determining the size of the patch data file!"); - } - - char *buf = new char[size]; - SDL_RWread(io, buf, size, 1); - - SDL_RWclose(io); - - return std::string(buf); -} diff --git a/platforms/sdl/desktop/AppPlatform_sdl.hpp b/platforms/sdl/desktop/AppPlatform_sdl.hpp index cf7f761b6..e139b57f0 100644 --- a/platforms/sdl/desktop/AppPlatform_sdl.hpp +++ b/platforms/sdl/desktop/AppPlatform_sdl.hpp @@ -18,7 +18,6 @@ class AppPlatform_sdl : public AppPlatform_sdl_base bool doesTextureExist(const std::string& path) const override; bool hasFileSystemAccess() override; - std::string getPatchData() override; protected: void ensureDirectoryExists(const char* path) override; diff --git a/platforms/sdl/main.cpp b/platforms/sdl/main.cpp index 6643ffc74..cf7b1a3de 100644 --- a/platforms/sdl/main.cpp +++ b/platforms/sdl/main.cpp @@ -111,6 +111,17 @@ extern "C" void resize_from_js(int new_width, int new_height) } #endif +// DirectSound Support +#ifdef _WIN32 +HWND GetHWND() +{ + SDL_SysWMinfo wmInfo; + SDL_VERSION(&wmInfo.version); + SDL_GetWindowWMInfo(window, &wmInfo); + return wmInfo.info.win.window; +} +#endif + // Handle Events static bool window_resized = false; static void handle_events() @@ -298,6 +309,10 @@ static EM_BOOL main_loop(double time, void *user_data) // Main int main(int argc, char *argv[]) { + // Setup Logging + Logger::setSingleton(new Logger); + + // Setup SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) { //LOG_E("Unable To Initialize SDL: %s", SDL_GetError()); @@ -331,7 +346,7 @@ int main(int argc, char *argv[]) window = SDL_CreateWindow("ReMinecraftPE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Minecraft::width, Minecraft::height, flags); if (!window) { - //LOG_E("Unable to create SDL window"); + LOG_E("Unable to create SDL window: %s", SDL_GetError()); exit(EXIT_FAILURE); } @@ -357,7 +372,7 @@ int main(int argc, char *argv[]) } } -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USE_GLES1_COMPATIBILITY_LAYER) xglInit(); if (!xglInitted()) @@ -371,7 +386,7 @@ int main(int argc, char *argv[]) // Setup Compatibility Layer If Needed #ifdef USE_GLES1_COMPATIBILITY_LAYER - init_gles_compatibility_layer(); + init_gles_compatibility_layer(SDL_GL_GetProcAddress); #endif // Setup Teardown diff --git a/platforms/sound/CMakeLists.txt b/platforms/sound/CMakeLists.txt new file mode 100644 index 000000000..886b3f6b4 --- /dev/null +++ b/platforms/sound/CMakeLists.txt @@ -0,0 +1,10 @@ +project(reminecraftpe-sound) + +# Select & Build +set(DEFAULT_SOUND_PLATFORM "openal") +if(WIN32) + set(DEFAULT_SOUND_PLATFORM "directsound") +endif() +set(REMCPE_SOUND_PLATFORM "${DEFAULT_SOUND_PLATFORM}" CACHE STRING "ReMCPE Sound Platform (Check /platforms/sound)") +add_subdirectory("${REMCPE_SOUND_PLATFORM}") +target_link_libraries(reminecraftpe reminecraftpe-sound) \ No newline at end of file diff --git a/platforms/sound/directsound/CMakeLists.txt b/platforms/sound/directsound/CMakeLists.txt new file mode 100644 index 000000000..24daf6bbf --- /dev/null +++ b/platforms/sound/directsound/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.16.0) +project(reminecraftpe-directsound) + +# Build +add_library(reminecraftpe-sound STATIC + SoundSystemDS.cpp +) + +# Libraries +target_link_libraries(reminecraftpe-sound + reminecraftpe-core + dsound + dxguid +) + +# Headers +target_include_directories(reminecraftpe-sound PUBLIC .) diff --git a/platforms/windows/SoundSystemDS.hpp b/platforms/sound/directsound/CustomSoundSystem.hpp similarity index 95% rename from platforms/windows/SoundSystemDS.hpp rename to platforms/sound/directsound/CustomSoundSystem.hpp index 7543c4a55..de50e210c 100644 --- a/platforms/windows/SoundSystemDS.hpp +++ b/platforms/sound/directsound/CustomSoundSystem.hpp @@ -8,7 +8,7 @@ #pragma once #include -#include +#include #include #include #include @@ -49,4 +49,6 @@ class SoundSystemDS : public SoundSystem IDirectSound* m_directsound; LPDIRECTSOUND3DLISTENER m_listener; std::vector m_buffers; -}; \ No newline at end of file +}; + +#define SOUND_SYSTEM SoundSystemDS diff --git a/platforms/windows/SoundSystemDS.cpp b/platforms/sound/directsound/SoundSystemDS.cpp similarity index 95% rename from platforms/windows/SoundSystemDS.cpp rename to platforms/sound/directsound/SoundSystemDS.cpp index 34ca8efd3..c032c6b8b 100644 --- a/platforms/windows/SoundSystemDS.cpp +++ b/platforms/sound/directsound/SoundSystemDS.cpp @@ -7,7 +7,7 @@ ********************************************************************/ #define WIN32_LEAN_AND_MEAN -#include "SoundSystemDS.hpp" +#include "CustomSoundSystem.hpp" #include "common/Utils.hpp" // @TODO: fix crash in playAt when Asan is active @@ -160,7 +160,7 @@ void SoundSystemDS::playAt(const SoundDesc& sound, float x, float y, float z, fl unsigned char* bufferPtr; unsigned long bufferSize; - int length = sound.m_pHeader->m_length * sound.m_pHeader->m_bytes_per_sample; + int length = sound.m_header.m_length * sound.m_header.m_bytes_per_sample; bool is2D = sqrtf(x * x + y * y + z * z) == 0.f; //For some reason mojang made 3D sounds are REALLY quiet, with some of their volumes literally going below 0.1 @@ -173,9 +173,9 @@ void SoundSystemDS::playAt(const SoundDesc& sound, float x, float y, float z, fl WAVEFORMATEX waveFormat; waveFormat.wFormatTag = WAVE_FORMAT_PCM; - waveFormat.nSamplesPerSec = DWORD(float(sound.m_pHeader->m_sample_rate) * pitch); - waveFormat.wBitsPerSample = 8 * sound.m_pHeader->m_bytes_per_sample; - waveFormat.nChannels = sound.m_pHeader->m_channels; + waveFormat.nSamplesPerSec = DWORD(float(sound.m_header.m_sample_rate) * pitch); + waveFormat.wBitsPerSample = 8 * sound.m_header.m_bytes_per_sample; + waveFormat.nChannels = sound.m_header.m_channels; waveFormat.nBlockAlign = (waveFormat.wBitsPerSample / 8) * waveFormat.nChannels; waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; waveFormat.cbSize = 0; @@ -268,7 +268,7 @@ void SoundSystemDS::playAt(const SoundDesc& sound, float x, float y, float z, fl info.object3d = NULL; //Check if position is not 0,0,0 and for mono to play 3D sound - if (!is2D && sound.m_pHeader->m_channels == 1) + if (!is2D && sound.m_header.m_channels == 1) { LPDIRECTSOUND3DBUFFER object3d; diff --git a/platforms/sound/openal/CMakeLists.txt b/platforms/sound/openal/CMakeLists.txt new file mode 100644 index 000000000..101c05f28 --- /dev/null +++ b/platforms/sound/openal/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.16.0) +project(reminecraftpe-openal) + +# Build +add_library(reminecraftpe-sound STATIC + SoundSystemAL.cpp +) + +# Core +target_link_libraries(reminecraftpe-sound PUBLIC reminecraftpe-core) + +# OpenAL +if(ANDROID) + # Use Vendored OpenAL + set(ALSOFT_UTILS FALSE CACHE BOOL "" FORCE) + set(ALSOFT_EXAMPLES FALSE CACHE BOOL "" FORCE) + set(ALSOFT_TESTS FALSE CACHE BOOL "" FORCE) + set(ALSOFT_REQUIRE_OPENSL TRUE CACHE BOOL "" FORCE) + add_subdirectory(../../../thirdparty/OpenAL openal EXCLUDE_FROM_ALL) + target_link_libraries(reminecraftpe-sound PUBLIC OpenAL::OpenAL) +elseif(EMSCRIPTEN) + # Use Emscripten's OpenAL + target_link_libraries(reminecraftpe-sound PUBLIC openal) +else() + # Use System OpenAL + find_package(OpenAL REQUIRED) + target_link_libraries(reminecraftpe-sound PUBLIC "${OPENAL_LIBRARY}") + target_include_directories(reminecraftpe-sound PUBLIC "${OPENAL_INCLUDE_DIR}") +endif() + +# Headers +target_include_directories(reminecraftpe-sound PUBLIC .) diff --git a/platforms/openal/SoundSystemAL.hpp b/platforms/sound/openal/CustomSoundSystem.hpp similarity index 87% rename from platforms/openal/SoundSystemAL.hpp rename to platforms/sound/openal/CustomSoundSystem.hpp index bc04737bf..7cf74eb32 100644 --- a/platforms/openal/SoundSystemAL.hpp +++ b/platforms/sound/openal/CustomSoundSystem.hpp @@ -1,17 +1,18 @@ #pragma once -#ifdef USE_OPENAL -#ifdef _WIN32 -#include -#include -#pragma comment( lib, "OpenAl32.lib" ) -#elif defined(__APPLE__) +#ifdef __APPLE__ #include #include -#else +#elif defined(__EMSCRIPTEN__) #include #include +#else +#include "al.h" +#include "alc.h" +#ifdef _WIN32 +#pragma comment( lib, "OpenAL32.lib" ) +#endif #endif #include @@ -24,6 +25,8 @@ #define MAX_IDLE_SOURCES 50 #define MAX_DISTANCE 16.0f +#define SOUND_SYSTEM SoundSystemAL + class SoundSystemAL : public SoundSystem { public: @@ -54,5 +57,3 @@ class SoundSystemAL : public SoundSystem Vec3 _lastListenerPos; float _listenerVolume; }; - -#endif diff --git a/platforms/openal/SoundSystemAL.cpp b/platforms/sound/openal/SoundSystemAL.cpp similarity index 99% rename from platforms/openal/SoundSystemAL.cpp rename to platforms/sound/openal/SoundSystemAL.cpp index 2130532c6..b1bbcabb7 100644 --- a/platforms/openal/SoundSystemAL.cpp +++ b/platforms/sound/openal/SoundSystemAL.cpp @@ -1,5 +1,4 @@ -#ifdef USE_OPENAL -#include "SoundSystemAL.hpp" +#include "CustomSoundSystem.hpp" #include "common/Utils.hpp" @@ -343,6 +342,4 @@ void SoundSystemAL::stopEngine() // Mark as unloaded _initialized = false; -} - -#endif +} \ No newline at end of file diff --git a/platforms/sound/opensl/CMakeLists.txt b/platforms/sound/opensl/CMakeLists.txt new file mode 100644 index 000000000..89eeabc98 --- /dev/null +++ b/platforms/sound/opensl/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.16.0) +project(reminecraftpe-opensl) + +# Build +add_library(reminecraftpe-sound STATIC + SoundSystemSL.cpp +) + +# Core +target_link_libraries(reminecraftpe-sound PUBLIC reminecraftpe-core) + +# OpenSL +target_link_libraries(reminecraftpe-sound PUBLIC OpenSLES) + +# Headers +target_include_directories(reminecraftpe-sound PUBLIC .) diff --git a/platforms/android/SoundSystemSL.hpp b/platforms/sound/opensl/CustomSoundSystem.hpp similarity index 97% rename from platforms/android/SoundSystemSL.hpp rename to platforms/sound/opensl/CustomSoundSystem.hpp index 121625bc1..f9e37e3da 100644 --- a/platforms/android/SoundSystemSL.hpp +++ b/platforms/sound/opensl/CustomSoundSystem.hpp @@ -30,6 +30,8 @@ typedef std::list SLSoundList; +#define SOUND_SYSTEM SoundSystemSL + class SoundSystemSL : public SoundSystem { public: @@ -62,4 +64,4 @@ class SoundSystemSL : public SoundSystem static std::vector toRemove; static SLObjectItf objEngine; static pthread_mutex_t toRemoveMutex; -}; \ No newline at end of file +}; diff --git a/platforms/android/SoundSystemSL.cpp b/platforms/sound/opensl/SoundSystemSL.cpp similarity index 99% rename from platforms/android/SoundSystemSL.cpp rename to platforms/sound/opensl/SoundSystemSL.cpp index 65649cd94..fcfca14da 100644 --- a/platforms/android/SoundSystemSL.cpp +++ b/platforms/sound/opensl/SoundSystemSL.cpp @@ -5,7 +5,7 @@ The following code is licensed under the BSD 1 clause license. SPDX-License-Identifier: BSD-1-Clause ********************************************************************/ -#include "SoundSystemSL.hpp" +#include "CustomSoundSystem.hpp" #include "common/Utils.hpp" #define C_MAX_SOUNDS 4 diff --git a/platforms/windows/AppPlatform_win32.cpp b/platforms/windows/AppPlatform_win32.cpp index e5daf9d67..467ae3f71 100644 --- a/platforms/windows/AppPlatform_win32.cpp +++ b/platforms/windows/AppPlatform_win32.cpp @@ -14,7 +14,6 @@ #include "GameMods.hpp" #include "AppPlatform_win32.hpp" -#include "LoggerWin32.hpp" #include "thirdparty/GL/GL.hpp" @@ -37,24 +36,18 @@ AppPlatform_win32::AppPlatform_win32() m_MouseDiffX = 0, m_MouseDiffY = 0; - // This initializes the Logger singleton to use the Windows-specific variant - // If we didn't initialize it here, the Minecraft class would have our back - m_pLogger = new LoggerWin32(); m_pSoundSystem = nullptr; } AppPlatform_win32::~AppPlatform_win32() { SAFE_DELETE(m_pSoundSystem); - - // DELETE THIS LAST - SAFE_DELETE(m_pLogger); } void AppPlatform_win32::initSoundSystem() { if (!m_pSoundSystem) - m_pSoundSystem = new SoundSystemDS(); + m_pSoundSystem = new SOUND_SYSTEM(); else LOG_E("Trying to initialize SoundSystem more than once!"); } @@ -214,16 +207,20 @@ bool AppPlatform_win32::hasFileSystemAccess() return true; } -std::string AppPlatform_win32::getPatchData() +AssetFile AppPlatform_win32::readAssetFile(const std::string& str) const { - std::ifstream ifs("assets/patches/patch_data.txt"); + std::string path = getAssetPath(str); + std::ifstream ifs(path, std::ios::binary | std::ios::ate); if (!ifs.is_open()) - return ""; + return AssetFile(); + + std::streamsize size = ifs.tellg(); + ifs.seekg(0, std::ios::beg); - std::stringstream ss; - ss << ifs.rdbuf(); + unsigned char* buffer = new unsigned char[size]; + ifs.read((char*) buffer, size); - return ss.str(); + return AssetFile(size, buffer); } void AppPlatform_win32::setScreenSize(int width, int height) diff --git a/platforms/windows/AppPlatform_win32.hpp b/platforms/windows/AppPlatform_win32.hpp index 772e4cfc2..caba74644 100644 --- a/platforms/windows/AppPlatform_win32.hpp +++ b/platforms/windows/AppPlatform_win32.hpp @@ -15,7 +15,7 @@ #include "client/player/input/Keyboard.hpp" #include "common/Utils.hpp" #include "LoggerWin32.hpp" -#include "SoundSystemDS.hpp" +#include "CustomSoundSystem.hpp" class AppPlatform_win32 : public AppPlatform { @@ -55,7 +55,7 @@ class AppPlatform_win32 : public AppPlatform bool hasFileSystemAccess() override; // Also add this to allow dynamic texture patching. - std::string getPatchData() override; + AssetFile readAssetFile(const std::string&) const override; void setScreenSize(int width, int height); const char* const getWindowTitle() const { return m_WindowTitle; } @@ -83,7 +83,6 @@ class AppPlatform_win32 : public AppPlatform int m_MouseDiffX, m_MouseDiffY; - LoggerWin32 *m_pLogger; - SoundSystemDS* m_pSoundSystem; + SOUND_SYSTEM* m_pSoundSystem; }; diff --git a/platforms/windows/CMakeLists.txt b/platforms/windows/CMakeLists.txt new file mode 100644 index 000000000..ff391c178 --- /dev/null +++ b/platforms/windows/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.16.0) +project(reminecraftpe-windows) + +# Win32 Build +target_compile_definitions(reminecraftpe-core + PUBLIC HANDLE_CHARS_SEPARATELY +) + +# Libraries +target_link_libraries(reminecraftpe-core + PUBLIC opengl32 + PUBLIC glu32 + PUBLIC gdi32 + PUBLIC uuid +) + +# Build +add_executable(reminecraftpe WIN32 + LoggerWin32.cpp + AppPlatform_win32.cpp + main.cpp + ../../thirdparty/GL/GLExt.cpp +) + +# Core +target_link_libraries(reminecraftpe reminecraftpe-core) + +# stb_image (If Needed) +add_subdirectory(../../thirdparty/stb_image stb_image) +target_link_libraries(reminecraftpe stb_image) \ No newline at end of file diff --git a/platforms/windows/LoggerWin32.hpp b/platforms/windows/LoggerWin32.hpp index 22bd0da1d..ac7f4a55b 100644 --- a/platforms/windows/LoggerWin32.hpp +++ b/platforms/windows/LoggerWin32.hpp @@ -3,7 +3,7 @@ #include #include "common/Logger.hpp" -class LoggerWin32 : Logger +class LoggerWin32 : public Logger { void print(eLogLevel, const char* const str) override; void print(eLogLevel, std::string str) override; diff --git a/platforms/windows/main.cpp b/platforms/windows/main.cpp index 2279f7954..ffc66ad8a 100644 --- a/platforms/windows/main.cpp +++ b/platforms/windows/main.cpp @@ -7,7 +7,7 @@ ********************************************************************/ #include -#include +#include #include "thirdparty/GL/GL.hpp" #include "compat/KeyCodes.hpp" @@ -18,6 +18,7 @@ #include "client/player/input/Multitouch.hpp" #include "AppPlatform_win32.hpp" +#include "LoggerWin32.hpp" #include "resource.h" LPCTSTR g_WindowClassName = TEXT("MCPEClass"); @@ -128,6 +129,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine SetInstance(hInstance); + // This initializes the Logger singleton to use the Windows-specific variant + // If we didn't initialize it here, the Minecraft class would have our back + Logger::setSingleton(new LoggerWin32); + // register the window class: WNDCLASS wc; wc.style = CS_OWNDC; diff --git a/platforms/windows/projects/Client/Client.vcxproj b/platforms/windows/projects/Client/Client.vcxproj index cdfbbd235..148326044 100644 --- a/platforms/windows/projects/Client/Client.vcxproj +++ b/platforms/windows/projects/Client/Client.vcxproj @@ -176,6 +176,7 @@ + diff --git a/platforms/windows/projects/Client/Client.vcxproj.filters b/platforms/windows/projects/Client/Client.vcxproj.filters index e234a075c..37cf018ef 100644 --- a/platforms/windows/projects/Client/Client.vcxproj.filters +++ b/platforms/windows/projects/Client/Client.vcxproj.filters @@ -455,6 +455,9 @@ Header Files\Player\Input + + Header Files\Sound + diff --git a/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj b/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj index 46f98edb0..2763b5aeb 100644 --- a/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj +++ b/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj @@ -37,7 +37,7 @@ - $(MC_ROOT)\platforms\openal;$(MC_ROOT)\thirdparty\stb_image\include;$(SDL2_PATH)\include;$(LIBPNG_PATH);$(OPENAL_PATH)\include;%(AdditionalIncludeDirectories) + $(MC_ROOT)\platforms\sound\openal;$(MC_ROOT)\thirdparty\stb_image\include;$(SDL2_PATH)\include;$(LIBPNG_PATH);$(OPENAL_PATH)\include;%(AdditionalIncludeDirectories) Console @@ -61,7 +61,7 @@ - + @@ -70,7 +70,7 @@ - + diff --git a/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj.filters b/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj.filters index 0c2cb9f2a..c0512ae8f 100644 --- a/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj.filters +++ b/platforms/windows/projects/MinecraftClient.SDL2/MinecraftClient.SDL2.vcxproj.filters @@ -24,15 +24,15 @@ Source Files - - Source Files - Source Files Source Files + + Source Files + @@ -41,14 +41,14 @@ Header Files\Compatibility - - Header Files - Header Files\Compatibility Header Files + + Header Files + \ No newline at end of file diff --git a/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj b/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj index 3e71dab03..f502d9abd 100644 --- a/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj +++ b/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj @@ -37,7 +37,7 @@ - $(DXSDK_DIR)\Include;$(MC_ROOT)\thirdparty\stb_image\include;%(AdditionalIncludeDirectories) + $(DXSDK_DIR)\Include;$(MC_ROOT)\platforms\sound\directsound;$(MC_ROOT)\thirdparty\stb_image\include;%(AdditionalIncludeDirectories) Windows @@ -56,7 +56,7 @@ - + @@ -64,7 +64,7 @@ - + diff --git a/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj.filters b/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj.filters index c76c4fdab..5991da251 100644 --- a/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj.filters +++ b/platforms/windows/projects/MinecraftClient.Win32/MinecraftClient.Win32.vcxproj.filters @@ -24,7 +24,7 @@ Header Files - + Header Files @@ -44,7 +44,7 @@ Source Files - + Source Files diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index acf65732e..d9f947e7a 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -306,74 +306,19 @@ add_subdirectory(../thirdparty/raknet raknet) target_link_libraries(reminecraftpe-core PUBLIC raknet) # zlib -add_library(zlib INTERFACE) -if(EMSCRIPTEN) +add_library(zlib-interface INTERFACE) +if(WIN32) + # Compile Vendored ZLib + add_subdirectory(../thirdparty/zlib zlib) + target_link_libraries(zlib-interface INTERFACE zlib) +elseif(EMSCRIPTEN) # Use Emscripten's ZLib set(ZLIB_FLAG -sUSE_ZLIB=1) - target_compile_options(zlib INTERFACE "${ZLIB_FLAG}") - target_link_options(zlib INTERFACE "${ZLIB_FLAG}") + target_compile_options(zlib-interface INTERFACE "${ZLIB_FLAG}") + target_link_options(zlib-interface INTERFACE "${ZLIB_FLAG}") else() # Use System ZLib find_package(ZLIB REQUIRED) - target_link_libraries(zlib INTERFACE ZLIB::ZLIB) -endif() -target_link_libraries(reminecraftpe-core PUBLIC zlib) - -# Platform Dependencies -if(USE_SDL) - # SDL - add_library(SDL INTERFACE) - if(ANDROID) - # Use Vendored SDL2 (Only For Android) - add_subdirectory(../thirdparty/SDL2/src SDL EXCLUDE_FROM_ALL) - target_link_libraries(SDL INTERFACE SDL2::SDL2) - elseif(EMSCRIPTEN) - # Use Emscripten's SDL2 - set(SDL_FLAG -sUSE_SDL=2) - target_compile_options(SDL INTERFACE "${SDL_FLAG}") - target_link_options(SDL INTERFACE "${SDL_FLAG}") - else() - # Use System SDL2 - find_package(SDL2 REQUIRED) - target_link_libraries(SDL INTERFACE SDL2::SDL2) - endif() - target_link_libraries(reminecraftpe-core PUBLIC SDL) - - # OpenGL - if(NOT EMSCRIPTEN AND NOT ANDROID) - option(USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" TRUE) - else() - set(USE_GLES1_COMPATIBILITY_LAYER TRUE CACHE BOOL "" FORCE) - endif() - if(USE_GLES1_COMPATIBILITY_LAYER) - set(GLES_COMPATIBILITY_LAYER_USE_SDL TRUE CACHE BOOL "" FORCE) - set(GLES_COMPATIBILITY_LAYER_DEPENDENCY SDL CACHE STRING "" FORCE) - set(GLES_COMPATIBILITY_LAYER_USE_ES3 FALSE CACHE BOOL "" FORCE) - add_subdirectory(../thirdparty/gles-compatibility-layer gles-compatibility-layer) - target_link_libraries(reminecraftpe-core PUBLIC gles-compatibility-layer) - target_compile_definitions(reminecraftpe-core PUBLIC USE_GLES1_COMPATIBILITY_LAYER) - if(EMSCRIPTEN) - # Use WebGL 2 - target_link_options(reminecraftpe-core PUBLIC -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2) - endif() - else() - find_package(OpenGL REQUIRED) - target_link_libraries(reminecraftpe-core PUBLIC OpenGL::GL) - endif() -elseif(USE_NATIVE_ANDROID) - # OpenGL - target_link_libraries(reminecraftpe-core PUBLIC EGL GLESv1_CM) -endif() - -# Android Logging -if(ANDROID) - target_link_libraries(reminecraftpe-core PUBLIC log) -endif() - -# Sound Data -if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../sound_data/sounds.h") - if(NOT DEFINED ENV{CI}) - message(WARNING "Missing sound data! Did you run tools/grabsounds.py?") - endif() - target_compile_definitions(reminecraftpe-core PRIVATE MISSING_SOUND_DATA) + target_link_libraries(zlib-interface INTERFACE ZLIB::ZLIB) endif() +target_link_libraries(reminecraftpe-core PUBLIC zlib-interface) \ No newline at end of file diff --git a/source/client/app/AppPlatform.cpp b/source/client/app/AppPlatform.cpp index b90592c86..52515af85 100644 --- a/source/client/app/AppPlatform.cpp +++ b/source/client/app/AppPlatform.cpp @@ -226,7 +226,15 @@ bool AppPlatform::hasFileSystemAccess() std::string AppPlatform::getPatchData() { - return ""; + const AssetFile file = readAssetFile("patches/patch_data.txt"); + std::string out = std::string(file.data, file.data + file.size); + delete file.data; + return out; +} + +AssetFile AppPlatform::readAssetFile(const std::string& path) const +{ + return AssetFile(); } void AppPlatform::initSoundSystem() diff --git a/source/client/app/AppPlatform.hpp b/source/client/app/AppPlatform.hpp index 082552140..581c0f306 100644 --- a/source/client/app/AppPlatform.hpp +++ b/source/client/app/AppPlatform.hpp @@ -13,6 +13,7 @@ #include "client/renderer/Texture.hpp" #include "client/sound/SoundSystem.hpp" +#include "AssetFile.hpp" class AppPlatform { @@ -85,6 +86,8 @@ class AppPlatform virtual std::string getPatchData(); virtual void initSoundSystem(); virtual SoundSystem* const getSoundSystem() const; + // Used For Sounds + virtual AssetFile readAssetFile(const std::string&) const; #endif public: diff --git a/source/client/app/AssetFile.hpp b/source/client/app/AssetFile.hpp new file mode 100644 index 000000000..81a26900f --- /dev/null +++ b/source/client/app/AssetFile.hpp @@ -0,0 +1,20 @@ +/******************************************************************** +Minecraft: Pocket Edition - Decompilation Project + Copyright (C) 2023 iProgramInCpp + + The following code is licensed under the BSD 1 clause license. + SPDX-License-Identifier: BSD-1-Clause + ********************************************************************/ + +#pragma once + +#include + +struct AssetFile +{ + ptrdiff_t size; + unsigned char *data; + + AssetFile(): size(-1), data(nullptr) {} + AssetFile(ptrdiff_t size, unsigned char *data): size(size), data(data) {} +}; \ No newline at end of file diff --git a/source/client/app/Minecraft.cpp b/source/client/app/Minecraft.cpp index 0eeaa4bce..e0d48da55 100644 --- a/source/client/app/Minecraft.cpp +++ b/source/client/app/Minecraft.cpp @@ -97,8 +97,6 @@ Minecraft::Minecraft() : m_fLastUpdated = 0; m_fDeltaTime = 0; m_lastInteractTime = 0; - - m_Logger = new Logger(); } int Minecraft::getLicenseId() @@ -838,7 +836,7 @@ void Minecraft::init() GetPatchManager()->PatchTiles(); m_pSoundEngine = new SoundEngine(platform()->getSoundSystem()); - m_pSoundEngine->init(m_options); + m_pSoundEngine->init(m_options, platform()); m_pLevelRenderer = new LevelRenderer(this, m_pTextures); m_pGameRenderer = new GameRenderer(this); @@ -883,7 +881,6 @@ Minecraft::~Minecraft() SAFE_DELETE(m_pUser); SAFE_DELETE(m_pLevelStorageSource); SAFE_DELETE(m_pInputHolder); - SAFE_DELETE(m_Logger); //@BUG: potentially leaking a CThread instance if this is destroyed early? } diff --git a/source/client/app/Minecraft.hpp b/source/client/app/Minecraft.hpp index 114a7dff4..322dbc7a8 100644 --- a/source/client/app/Minecraft.hpp +++ b/source/client/app/Minecraft.hpp @@ -103,7 +103,6 @@ class Minecraft : public App static int customDebugId; private: - Logger *m_Logger; Options *m_options; public: diff --git a/source/client/gui/Gui.cpp b/source/client/gui/Gui.cpp index baedc763e..03cf7e631 100644 --- a/source/client/gui/Gui.cpp +++ b/source/client/gui/Gui.cpp @@ -288,9 +288,9 @@ void Gui::render(float f, bool bHaveScreen, int mouseX, int mouseY) int emptyHeartX = 16; bool b1 = false; - if (player->field_B8 < 10) + if (player->m_invulnerableTime < 10) { - b1 = player->field_B8 / 3 % 2; + b1 = player->m_invulnerableTime / 3 % 2; emptyHeartX += 9 * b1; } @@ -318,9 +318,9 @@ void Gui::render(float f, bool bHaveScreen, int mouseX, int mouseY) if (b1) { - if (healthNo < player->field_100) + if (healthNo < player->m_lastHealth) blit(heartX, heartY, 70, 0, 9, 9, 0, 0); - else if (healthNo == player->field_100) + else if (healthNo == player->m_lastHealth) blit(heartX, heartY, 79, 0, 9, 9, 0, 0); } diff --git a/source/client/gui/screens/StartMenuScreen.cpp b/source/client/gui/screens/StartMenuScreen.cpp index 18c196e4f..5156523d0 100644 --- a/source/client/gui/screens/StartMenuScreen.cpp +++ b/source/client/gui/screens/StartMenuScreen.cpp @@ -13,7 +13,7 @@ #include "SelectWorldScreen.hpp" #include "JoinGameScreen.hpp" -#if defined(_WIN32) || (defined(TARGET_OS_MAC) && TARGET_OS_IPHONE == 0) +#if (defined(USE_SDL) || defined(_WIN32) || (defined(TARGET_OS_MAC) && TARGET_OS_IPHONE == 0)) && !defined(ANDROID) #define CAN_QUIT #endif diff --git a/source/client/renderer/LevelRenderer.cpp b/source/client/renderer/LevelRenderer.cpp index b3c5b937b..e11800a26 100644 --- a/source/client/renderer/LevelRenderer.cpp +++ b/source/client/renderer/LevelRenderer.cpp @@ -903,17 +903,26 @@ void LevelRenderer::renderHitOutline(Player* pPlayer, const HitResult& hr, int i glDisable(GL_TEXTURE_2D); glDepthMask(false); - // Maximize Line Width - glEnable(GL_LINE_SMOOTH); - + // Determine Line Width + float line_width = 1.5f / Gui::InvGuiScale; + // Clamp Line Width float range[2]; +#ifdef GL_ALIASED_LINE_WIDTH_RANGE + glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range); +#else + glEnable(GL_LINE_SMOOTH); glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range); - - float lineWidth = 2.0f; - if (lineWidth > range[1]) - lineWidth = range[1]; - - glLineWidth(lineWidth); +#endif + if (range[1] < line_width) + { + line_width = range[1]; + } + else if (range[0] > line_width) + { + line_width = range[0]; + } + // Set Line Width + glLineWidth(line_width); TileID tile = m_pLevel->getTile(hr.m_tilePos); if (tile > 0) @@ -934,6 +943,9 @@ void LevelRenderer::renderHitOutline(Player* pPlayer, const HitResult& hr, int i render(aabb); } +#ifndef GL_ALIASED_LINE_WIDTH_RANGE + glDisable(GL_LINE_SMOOTH); +#endif glDepthMask(true); glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); diff --git a/source/client/renderer/entity/MobRenderer.cpp b/source/client/renderer/entity/MobRenderer.cpp index ec6ea0ae5..e7b66acdb 100644 --- a/source/client/renderer/entity/MobRenderer.cpp +++ b/source/client/renderer/entity/MobRenderer.cpp @@ -109,10 +109,10 @@ void MobRenderer::render(Entity* entity, float x, float y, float z, float unused //glTranslatef(0.0f, -1.5078f, 0.0f); glTranslatef(0.0f, -24.0f * fScale - (1.0f / 128.0f), 0.0f); - float x1 = pMob->field_128 + (pMob->field_12C - pMob->field_128) * f; + float x1 = pMob->field_128 + (pMob->m_walkAnimSpeed - pMob->field_128) * f; if (x1 > 1.0f) x1 = 1.0f; - float x2 = pMob->field_130 - pMob->field_12C * (1.0f - f); + float x2 = pMob->field_130 - pMob->m_walkAnimSpeed * (1.0f - f); bindTexture(pMob->getTexture()); glEnable(GL_ALPHA_TEST); diff --git a/source/client/sound/SoundData.cpp b/source/client/sound/SoundData.cpp index c1cabd486..2bdcf225a 100644 --- a/source/client/sound/SoundData.cpp +++ b/source/client/sound/SoundData.cpp @@ -8,13 +8,35 @@ #include "SoundData.hpp" -// -------------------------------------------------------------------- -// WARNING! If you have an error here it is most likely because you did -// not grab the sound data from a working Minecraft PE 0.1.3 .apk. -// -// Check the readme for a guide on how to extract game sounds from the -// Minecraft PE 0.1.3 .apk file. -// -------------------------------------------------------------------- -#ifndef MISSING_SOUND_DATA -#include "../../sound_data/sounds.h" -#endif +#include "client/app/AppPlatform.hpp" + +void SoundDesc::_load(const AppPlatform* platform, const char *name) +{ + if (m_isLoaded) + { + // Already Loaded + return; + } + // Read Asset File + m_file = platform->readAssetFile(std::string("sound/") + name + ".pcm"); + m_isLoaded = m_file.size > 0; + if (m_isLoaded) + { + m_fileData = m_file.data; + m_header = *(PCMSoundHeader *) m_fileData; + m_pData = (uint16_t *) (m_fileData + sizeof(PCMSoundHeader)); + field_4 = m_header.m_channels * m_header.m_length * m_header.m_bytes_per_sample; + } +} + +// Load All Sounds +void SoundDesc::_load(const AppPlatform* platform) +{ +#define SOUND(category, name) SA_##name._load(platform, #name); +#include "sound_list.h" +#undef SOUND +} + +#define SOUND(category, name) SoundDesc SA_##name; +#include "sound_list.h" +#undef SOUND \ No newline at end of file diff --git a/source/client/sound/SoundData.hpp b/source/client/sound/SoundData.hpp index 6769bc73b..75e74e1d6 100644 --- a/source/client/sound/SoundData.hpp +++ b/source/client/sound/SoundData.hpp @@ -10,6 +10,9 @@ #include #include "common/Utils.hpp" +#include "client/app/AssetFile.hpp" + +class AppPlatform; struct PCMSoundHeader { @@ -21,22 +24,17 @@ struct PCMSoundHeader struct SoundDesc { + bool m_isLoaded; + AssetFile m_file; uint16_t* m_pData; int field_4; PCMSoundHeader m_header; - PCMSoundHeader* m_pHeader; + unsigned char* m_fileData; - SoundDesc() - { - m_pData = nullptr; - field_4 = 0; - m_pHeader = nullptr; - } - SoundDesc(PCMSoundHeader& header, uint16_t* data) - { - m_pHeader = &header; - m_header = header; - m_pData = data; - field_4 = header.m_channels * header.m_length * header.m_bytes_per_sample; - } + void _load(const AppPlatform* platform, const char *name); + static void _load(const AppPlatform*); }; + +#define SOUND(category, name) extern SoundDesc SA_##name; +#include "sound_list.h" +#undef SOUND \ No newline at end of file diff --git a/source/client/sound/SoundEngine.cpp b/source/client/sound/SoundEngine.cpp index d67a9ec32..8ffc4b06e 100644 --- a/source/client/sound/SoundEngine.cpp +++ b/source/client/sound/SoundEngine.cpp @@ -25,46 +25,16 @@ float SoundEngine::_getVolumeMult(const Vec3& pos) return 1.0f; } -void SoundEngine::init(Options* options) +void SoundEngine::init(Options* options, AppPlatform* platform) { // TODO: Who's the genius who decided it'd be better to check a name string rather than an enum? m_pOptions = options; + // Load Sounds + SoundDesc::_load(platform); -#ifndef MISSING_SOUND_DATA - m_repository.add("step.cloth", SA_cloth1); - m_repository.add("step.cloth", SA_cloth2); - m_repository.add("step.cloth", SA_cloth3); - m_repository.add("step.cloth", SA_cloth4); - - m_repository.add("step.grass", SA_grass1); - m_repository.add("step.grass", SA_grass2); - m_repository.add("step.grass", SA_grass3); - m_repository.add("step.grass", SA_grass4); - - m_repository.add("step.gravel", SA_gravel1); - m_repository.add("step.gravel", SA_gravel2); - m_repository.add("step.gravel", SA_gravel3); - m_repository.add("step.gravel", SA_gravel4); - - m_repository.add("step.sand", SA_sand1); - m_repository.add("step.sand", SA_sand2); - m_repository.add("step.sand", SA_sand3); - m_repository.add("step.sand", SA_sand4); - - m_repository.add("step.stone", SA_stone1); - m_repository.add("step.stone", SA_stone2); - m_repository.add("step.stone", SA_stone3); - m_repository.add("step.stone", SA_stone4); - - m_repository.add("step.wood", SA_wood1); - m_repository.add("step.wood", SA_wood2); - m_repository.add("step.wood", SA_wood3); - m_repository.add("step.wood", SA_wood4); - - m_repository.add("random.splash", SA_splash); - m_repository.add("random.explode", SA_explode); - m_repository.add("random.click", SA_click); -#endif +#define SOUND(category, name) m_repository.add(category, SA_##name); +#include "sound_list.h" +#undef SOUND } void SoundEngine::enable(bool b) diff --git a/source/client/sound/SoundEngine.hpp b/source/client/sound/SoundEngine.hpp index 40012fc56..a7967ab0c 100644 --- a/source/client/sound/SoundEngine.hpp +++ b/source/client/sound/SoundEngine.hpp @@ -20,7 +20,7 @@ class SoundEngine float _getVolumeMult(const Vec3& pos); public: SoundEngine(SoundSystem* soundSystem); - void init(Options*); + void init(Options*, AppPlatform*); void enable(bool b); void updateOptions(); void mute(); diff --git a/source/client/sound/SoundRepository.cpp b/source/client/sound/SoundRepository.cpp index b2e54c9e7..1b7d3e32a 100644 --- a/source/client/sound/SoundRepository.cpp +++ b/source/client/sound/SoundRepository.cpp @@ -12,12 +12,14 @@ void SoundRepository::add(const std::string& name, SoundDesc& sd) { + if (!sd.m_isLoaded) + return; std::map >::iterator iter = m_repo.find(name); if (iter == m_repo.end()) { std::vector sdv; sdv.push_back(sd); - m_repo.insert(std::pair >(name, sdv)); + m_repo.insert(std::make_pair(name, sdv)); } else { diff --git a/source/client/sound/sound_list.h b/source/client/sound/sound_list.h new file mode 100644 index 000000000..8ee3d06b0 --- /dev/null +++ b/source/client/sound/sound_list.h @@ -0,0 +1,65 @@ +SOUND("step.cloth", cloth1) +SOUND("step.cloth", cloth2) +SOUND("step.cloth", cloth3) +SOUND("step.cloth", cloth4) + +SOUND("step.grass", grass1) +SOUND("step.grass", grass2) +SOUND("step.grass", grass3) +SOUND("step.grass", grass4) + +SOUND("step.gravel", gravel1) +SOUND("step.gravel", gravel2) +SOUND("step.gravel", gravel3) +SOUND("step.gravel", gravel4) + +SOUND("step.sand", sand1) +SOUND("step.sand", sand2) +SOUND("step.sand", sand3) +SOUND("step.sand", sand4) + +SOUND("step.stone", stone1) +SOUND("step.stone", stone2) +SOUND("step.stone", stone3) +SOUND("step.stone", stone4) + +SOUND("step.wood", wood1) +SOUND("step.wood", wood2) +SOUND("step.wood", wood3) +SOUND("step.wood", wood4) + +SOUND("random.splash", splash) +SOUND("random.explode", explode) +SOUND("random.click", click) +SOUND("random.door_close", door_close) +SOUND("random.door_open", door_open) +SOUND("random.pop", pop) + +SOUND("fire.fire", fire) + +SOUND("damage.fallbig", fallbig1) +SOUND("damage.fallbig", fallbig2) + +SOUND("damage.fallsmall", fallsmall) + +SOUND("mob.pig", pig1) +SOUND("mob.pig", pig2) +SOUND("mob.pig", pig3) +SOUND("mob.pigdeath", pigdeath) + +SOUND("mob.sheep", sheep1) +SOUND("mob.sheep", sheep2) +SOUND("mob.sheep", sheep3) + +SOUND("mob.cow", cow1) +SOUND("mob.cow", cow2) +SOUND("mob.cow", cow3) +SOUND("mob.cow", cow4) +SOUND("mob.cowhurt", cowhurt1) +SOUND("mob.cowhurt", cowhurt2) +SOUND("mob.cowhurt", cowhurt3) + +SOUND("mob.chicken", chicken2) +SOUND("mob.chicken", chicken3) +SOUND("mob.chickenhurt", chickenhurt1) +SOUND("mob.chickenhurt", chickenhurt2) \ No newline at end of file diff --git a/source/common/CThread.cpp b/source/common/CThread.cpp index f2857c8d9..530a40fbc 100644 --- a/source/common/CThread.cpp +++ b/source/common/CThread.cpp @@ -12,7 +12,7 @@ #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN -#include // for Sleep() +#include // for Sleep() #else #include #endif diff --git a/source/common/CThread.hpp b/source/common/CThread.hpp index b2b02b04a..ecc7cd955 100644 --- a/source/common/CThread.hpp +++ b/source/common/CThread.hpp @@ -13,7 +13,7 @@ #if defined(_WIN32) #ifndef USE_WIN32_THREADS -#if defined(_XBOX) || defined(USE_OLD_CPP) +#if defined(_XBOX) || defined(USE_OLD_CPP) || defined(__MINGW32__) // USE_WIN32_THREADS - Use a Win32 implementation of threads instead of using pthread #define USE_WIN32_THREADS #else @@ -41,7 +41,7 @@ #include #else #define WIN32_LEAN_AND_MEAN -#include +#include #endif #else diff --git a/source/common/Logger.cpp b/source/common/Logger.cpp index f629ac4f2..0b75ba832 100644 --- a/source/common/Logger.cpp +++ b/source/common/Logger.cpp @@ -12,11 +12,14 @@ Logger* const Logger::singleton() return m_singleton; } -Logger::Logger() +void Logger::setSingleton(Logger* logger) { // Stick with the first output handle we get - if (!m_singleton) - m_singleton = this; + if (!m_singleton) { + m_singleton = logger; + } else { + m_singleton->print(LOG_ERR, "Logging already setup!"); + } } Logger::~Logger() diff --git a/source/common/Logger.hpp b/source/common/Logger.hpp index 3d1f4a597..7ab2e5863 100644 --- a/source/common/Logger.hpp +++ b/source/common/Logger.hpp @@ -26,8 +26,8 @@ class Logger static Logger* m_singleton; public: static Logger* const singleton(); + static void setSingleton(Logger*); - Logger(); virtual ~Logger(); const char* GetTag(eLogLevel ll); diff --git a/source/common/Utils.cpp b/source/common/Utils.cpp index 34ba4ba26..eb097c935 100644 --- a/source/common/Utils.cpp +++ b/source/common/Utils.cpp @@ -14,7 +14,7 @@ #if defined(_WIN32) && !defined(_XBOX) #define WIN32_LEAN_AND_MEAN -#include +#include #include #include @@ -276,7 +276,7 @@ time_t getEpochTimeS() return time(0); } -#ifdef _WIN32 +#if defined(_WIN32) && !defined(USE_SDL) HINSTANCE g_hInstance = NULL; HWND g_hWnd = NULL; diff --git a/source/common/Utils.hpp b/source/common/Utils.hpp index 8098fc8f3..f0ae463d1 100644 --- a/source/common/Utils.hpp +++ b/source/common/Utils.hpp @@ -37,9 +37,9 @@ // Do we even need all this WinSock stuff anymore? #ifndef _XBOX // assume we're on a normal Windows device #define WIN32_LEAN_AND_MEAN -#include -#include -#include +#include +#include +#include #include #include diff --git a/source/world/entity/Entity.cpp b/source/world/entity/Entity.cpp index d783fcf1c..b915314f5 100644 --- a/source/world/entity/Entity.cpp +++ b/source/world/entity/Entity.cpp @@ -45,7 +45,7 @@ void Entity::_init() m_bNoPhysics = false; field_B0 = 0.0f; field_B4 = 0; - field_B8 = 0; + m_invulnerableTime = 0; m_airCapacity = TOTAL_AIR_SUPPLY; m_fireTicks = 0; m_flameTime = 0; diff --git a/source/world/entity/Entity.hpp b/source/world/entity/Entity.hpp index 98bc459a1..01bb2908b 100644 --- a/source/world/entity/Entity.hpp +++ b/source/world/entity/Entity.hpp @@ -210,7 +210,7 @@ class Entity bool m_bNoPhysics; float field_B0; int field_B4; - int field_B8; + int m_invulnerableTime; int m_airCapacity; int m_fireTicks; int m_flameTime; diff --git a/source/world/entity/ItemEntity.cpp b/source/world/entity/ItemEntity.cpp index 655cca5d7..5b7271d37 100644 --- a/source/world/entity/ItemEntity.cpp +++ b/source/world/entity/ItemEntity.cpp @@ -12,7 +12,7 @@ void ItemEntity::_init(const ItemInstance* itemInstance) { field_E0 = 0; - field_E4 = 0; + m_throwTime = 0; field_EC = 0; m_health = 5; m_bMakeStepSound = false; @@ -65,15 +65,17 @@ bool ItemEntity::isInWater() void ItemEntity::playerTouch(Player* player) { // Here, this would give the item to the player, and remove the item entity. - if (field_E4 != 0) + if (m_throwTime != 0) return; Inventory* pInventory = player->m_pInventory; pInventory->addItem(&m_itemInstance); - m_pLevel->playSound(this, "random.pop", 0.3f, - (((sharedRandom.nextFloat() - sharedRandom.nextFloat()) * 0.7f) + 1.0f) + (((sharedRandom.nextFloat() - sharedRandom.nextFloat()) * 0.7f) + 1.0f)); + m_pLevel->playSound(this, "random.pop", 0.2f, + (((sharedRandom.nextFloat() - sharedRandom.nextFloat()) * 0.7f) + 1.0f) * 2.0f); + + player->take(this, m_itemInstance.m_amount); if (m_itemInstance.m_amount <= 0) remove(); @@ -83,8 +85,8 @@ void ItemEntity::tick() { Entity::tick(); - if (field_E4 > 0) - field_E4--; + if (m_throwTime > 0) + m_throwTime--; m_oPos = m_pos; m_vel.y -= 0.04f; diff --git a/source/world/entity/ItemEntity.hpp b/source/world/entity/ItemEntity.hpp index e05d91fb2..3ccfbf621 100644 --- a/source/world/entity/ItemEntity.hpp +++ b/source/world/entity/ItemEntity.hpp @@ -37,7 +37,7 @@ class ItemEntity : public Entity #endif int field_E0; - int field_E4; + int m_throwTime; float field_E8; int field_EC; int m_health; diff --git a/source/world/entity/LocalPlayer.cpp b/source/world/entity/LocalPlayer.cpp index 434adff13..cf57de039 100644 --- a/source/world/entity/LocalPlayer.cpp +++ b/source/world/entity/LocalPlayer.cpp @@ -87,6 +87,11 @@ bool LocalPlayer::isImmobile() const return Player::isImmobile() || (m_pMinecraft->useController() && m_pMinecraft->m_pScreen); //!m_pMinecraft->m_bGrabbedMouse; // this works if we still set this when not using a mouse } +void LocalPlayer::take(Entity* pEnt, int orgCount) +{ + //m_pMinecraft->m_pParticleEngine->add(new TakeAnimationParticle(m_pLevel, pEnt, this, -0.5f)); +} + void LocalPlayer::animateRespawn() { diff --git a/source/world/entity/LocalPlayer.hpp b/source/world/entity/LocalPlayer.hpp index e2a59af71..15781a75c 100644 --- a/source/world/entity/LocalPlayer.hpp +++ b/source/world/entity/LocalPlayer.hpp @@ -30,6 +30,7 @@ class LocalPlayer : public Player virtual bool isLocalPlayer() const override { return true; } virtual void drop(const ItemInstance* pItemInstance, bool b = false) override; virtual bool isImmobile() const override; + virtual void take(Entity* pEnt, int orgCount); void calculateFlight(const Vec3& pos); void closeContainer(); //@HUH: oddly enough not a virtual/override diff --git a/source/world/entity/Mob.cpp b/source/world/entity/Mob.cpp index bab62d664..4fc1bce47 100644 --- a/source/world/entity/Mob.cpp +++ b/source/world/entity/Mob.cpp @@ -12,14 +12,14 @@ Mob::Mob(Level* pLevel) : Entity(pLevel) { - field_DC = 10; + m_invulnerableDuration = 10; field_E8 = 0.0f; field_EC = 0.0f; field_F0 = 0; m_oAttackAnim = 0.0f; m_attackAnim = 0.0f; m_health = 10; - field_100 = 20; + m_lastHealth = 20; m_hurtTime = 0; m_hurtDuration = 0; m_hurtDir = 0.0f; @@ -30,7 +30,7 @@ Mob::Mob(Level* pLevel) : Entity(pLevel) field_120 = 0; field_124 = 0; field_128 = 0.0f; - field_12C = 0.0f; + m_walkAnimSpeed = 0.0f; field_130 = 0.0f; field_AFC = 0; field_B00 = Vec2::ZERO; @@ -51,10 +51,11 @@ Mob::Mob(Level* pLevel) : Entity(pLevel) m_lSteps = 0; m_lPos = Vec3::ZERO; m_lRot = Vec2::ZERO; - field_B84 = 0; + m_lastHurt = 0; m_pEntLookedAt = nullptr; m_bSwinging = false; m_swingTime = 0; + m_ambientSoundTime = 0; m_texture = "/mob/pig.png"; m_class = ""; @@ -227,9 +228,21 @@ void Mob::baseTick() m_oAttackAnim = m_attackAnim; Entity::baseTick(); + if (m_random.nextInt(1000) < m_ambientSoundTime++) + { + playAmbientSound(); + } + if (isAlive() && isInWall()) hurt(nullptr, 1); + // Java + /*if (m_bFireImmune || m_pLevel->m_bIsMultiplayer) + { + m_fireTicks = 0; + }*/ + + if (isAlive() && isUnderLiquid(Material::water) && !isWaterMob()) { m_airCapacity--; @@ -261,7 +274,7 @@ void Mob::baseTick() if (field_114 > 0) field_114--; if (m_hurtTime > 0) m_hurtTime--; - if (field_B8 > 0) field_B8--; + if (m_invulnerableTime > 0) m_invulnerableTime--; if (m_health <= 0) { @@ -311,17 +324,31 @@ bool Mob::hurt(Entity *pAttacker, int damage) if (m_health <= 0) return false; - field_12C = 1.5f; - if (float(field_B8) <= float(field_DC) * 0.5f) + m_walkAnimSpeed = 1.5f; + bool var3 = true; + if (float(m_invulnerableTime) > float(m_invulnerableDuration) / 2.0f) + { + if (damage <= m_lastHurt) + return false; + + actuallyHurt(damage - m_lastHurt); + m_lastHurt = damage; + var3 = false; + } + else { - field_100 = m_health; - field_B8 = field_DC; - field_B84 = damage; + m_lastHurt = damage; + m_lastHealth = m_health; + m_invulnerableTime = m_invulnerableDuration; actuallyHurt(damage); - m_hurtDuration = 10; - m_hurtTime = 10; + m_hurtTime = m_hurtDuration = 10; + } - // not in 0.1 + m_hurtDir = 0.0f; + // not in 0.1 + if (var3) + { + //m_pLevel->broadcastEntityEvent(this, 2); // Java markHurt(); if (pAttacker) @@ -341,18 +368,21 @@ bool Mob::hurt(Entity *pAttacker, int damage) knockback(pAttacker, damage, xd, zd); } } - else + + if (m_health <= 0) { - if (field_B84 >= damage) - return 0; + if (var3) + { + m_pLevel->playSound(this, getDeathSound(), getSoundVolume(), (m_random.nextFloat() - m_random.nextFloat()) * 0.2f + 1.0f); + } - actuallyHurt(damage - field_B84); - field_B84 = damage; + die(pAttacker); + } + else if (var3) + { + m_pLevel->playSound(this, getHurtSound(), getSoundVolume(), (m_random.nextFloat() - m_random.nextFloat()) * 0.2f + 1.0f); } - m_hurtDir = 0; - if (m_health <= 0) - die(pAttacker); return true; } @@ -432,7 +462,12 @@ std::string Mob::getTexture() const void Mob::playAmbientSound() { - + m_ambientSoundTime = -getAmbientSoundInterval(); + std::string sound = getAmbientSound(); + if (sound != "") + { + m_pLevel->playSound(this, sound, getSoundVolume(), (m_random.nextFloat() - m_random.nextFloat()) * 0.2f + 1.0f); + } } int Mob::getAmbientSoundInterval() const @@ -449,7 +484,7 @@ void Mob::heal(int health) if (m_health > C_MAX_MOB_HEALTH) m_health = C_MAX_MOB_HEALTH; - field_B8 = field_DC / 2; + m_invulnerableTime = m_invulnerableDuration / 2; } HitResult Mob::pick(float f1, float f2) @@ -575,7 +610,7 @@ bool Mob::canSee(Entity* pEnt) const void Mob::updateWalkAnim() { - field_128 = field_12C; + field_128 = m_walkAnimSpeed; float diffX = m_pos.x - m_oPos.x; float diffZ = m_pos.z - m_oPos.z; @@ -584,8 +619,8 @@ void Mob::updateWalkAnim() if (spd > 1.0f) spd = 1.0f; - field_12C += (spd - field_12C) * 0.4f; - field_130 += field_12C; + m_walkAnimSpeed += (spd - m_walkAnimSpeed) * 0.4f; + field_130 += m_walkAnimSpeed; } void Mob::aiStep() diff --git a/source/world/entity/Mob.hpp b/source/world/entity/Mob.hpp index d75eb88c1..d6cf79a01 100644 --- a/source/world/entity/Mob.hpp +++ b/source/world/entity/Mob.hpp @@ -84,8 +84,11 @@ class Mob : public Entity float rotlerp(float, float, float); void updateAttackAnim(); +private: + int m_ambientSoundTime; + public: - int field_DC; + int m_invulnerableDuration; float field_E0; float field_E4; float field_E8; @@ -94,7 +97,7 @@ class Mob : public Entity float m_oAttackAnim; float m_attackAnim; int m_health; - int field_100; + int m_lastHealth; int m_hurtTime; int m_hurtDuration; float m_hurtDir; @@ -105,7 +108,7 @@ class Mob : public Entity int field_120; int field_124; float field_128; - float field_12C; + float m_walkAnimSpeed; float field_130; Random m_random; int field_AFC; @@ -129,7 +132,7 @@ class Mob : public Entity int m_lSteps; Vec3 m_lPos; Vec2 m_lRot; - int field_B84; + int m_lastHurt; Entity* m_pEntLookedAt; float v020_field_104; diff --git a/source/world/entity/Player.cpp b/source/world/entity/Player.cpp index 3b5f6c16a..3368847b9 100644 --- a/source/world/entity/Player.cpp +++ b/source/world/entity/Player.cpp @@ -210,7 +210,7 @@ void Player::drop(const ItemInstance* pItemInstance, bool b) return; ItemEntity* pItemEntity = new ItemEntity(m_pLevel, Vec3(m_pos.x, m_pos.y - 0.3f + getHeadHeight(), m_pos.z), pItemInstance); - pItemEntity->field_E4 = 40; + pItemEntity->m_throwTime = 40; if (b) { @@ -305,7 +305,7 @@ void Player::stopDestroying() m_destroyingBlock = false; } -void Player::take(Entity* pEnt, int x) +void Player::take(Entity* pEnt, int orgCount) { } diff --git a/source/world/entity/Player.hpp b/source/world/entity/Player.hpp index 08b27988a..0b803bbce 100644 --- a/source/world/entity/Player.hpp +++ b/source/world/entity/Player.hpp @@ -46,6 +46,7 @@ class Player : public Mob virtual void startDestroying(); virtual void stopDestroying(); virtual bool isLocalPlayer() const { return false; } + virtual void take(Entity* pEnt, int orgCount); int addResource(int); void animateRespawn(Player*, Level*); @@ -65,7 +66,6 @@ class Player : public Mob void setDefaultHeadHeight(); void setRespawnPos(const TilePos& pos); - void take(Entity* pEnt, int x); void touch(Entity* pEnt); GameType getPlayerGameType() const { return _playerGameType; } void setPlayerGameType(GameType playerGameType) { _playerGameType = playerGameType; } diff --git a/source/world/tile/FireTile.cpp b/source/world/tile/FireTile.cpp index e94f5b8a4..7e35ff6ec 100644 --- a/source/world/tile/FireTile.cpp +++ b/source/world/tile/FireTile.cpp @@ -68,6 +68,11 @@ int FireTile::getTickDelay() const void FireTile::animateTick(Level* level, const TilePos& pos, Random* random) { + if (random->nextInt(24) == 0) + { + level->playSound(pos + 0.5f, "fire.fire", 1.0f + random->nextFloat(), (random->nextFloat() * 0.7f) + 0.3f); + } + // @TODO: Mark Tile::fire as FireTile* instead of Tile* FireTile* pFireTile = (FireTile*)Tile::fire; if (level->isSolidTile(pos.below()) || pFireTile->canBurn(level, pos.below())) diff --git a/source/world/tile/Tile.cpp b/source/world/tile/Tile.cpp index ba590e2fd..233420d81 100644 --- a/source/world/tile/Tile.cpp +++ b/source/world/tile/Tile.cpp @@ -1059,7 +1059,7 @@ void Tile::spawnResources(Level* pLevel, const TilePos& pos, int data, float fCh ItemInstance inst(id, 1, getSpawnResourcesAuxValue(data)); ItemEntity* pEntity = new ItemEntity(pLevel, Vec3(pos) + o, &inst); - pEntity->field_E4 = 10; + pEntity->m_throwTime = 10; pLevel->addEntity(pEntity); } diff --git a/thirdparty/GL/GL.hpp b/thirdparty/GL/GL.hpp index 4aa5e6878..b8f599c24 100644 --- a/thirdparty/GL/GL.hpp +++ b/thirdparty/GL/GL.hpp @@ -137,7 +137,7 @@ void xglDrawArrays(GLenum mode, GLint first, GLsizei count); #endif -#if defined(_WIN32) && !defined(USE_SDL) +#if defined(_WIN32) && !defined(USE_GLES1_COMPATIBILITY_LAYER) // Win32 defines xglOrthof as a regular function #elif defined USE_GL_ORTHO_F #define xglOrthof glOrthof diff --git a/thirdparty/SDL2/SDL2.h b/thirdparty/SDL2/SDL2.h index 04de4d961..3d2518b96 100644 --- a/thirdparty/SDL2/SDL2.h +++ b/thirdparty/SDL2/SDL2.h @@ -3,6 +3,7 @@ #ifdef _WIN32 #pragma comment(lib, "SDL2.lib") #include +#include #else #include #endif \ No newline at end of file diff --git a/thirdparty/raknet/CMakeLists.txt b/thirdparty/raknet/CMakeLists.txt index 99465983b..3fac7eb43 100644 --- a/thirdparty/raknet/CMakeLists.txt +++ b/thirdparty/raknet/CMakeLists.txt @@ -115,3 +115,12 @@ add_library(raknet STATIC RakSleep.cpp ) target_include_directories(raknet PUBLIC .) + +# Windows Support +if(WIN32) + target_compile_definitions(raknet + PUBLIC SHA1_HAS_TCHAR + PUBLIC LOCKLESS_TYPES_USE_MUTEX + ) + target_link_libraries(raknet ws2_32) +endif() \ No newline at end of file diff --git a/thirdparty/raknet/WindowsIncludes.h b/thirdparty/raknet/WindowsIncludes.h index 9ec686837..969d9aeb5 100644 --- a/thirdparty/raknet/WindowsIncludes.h +++ b/thirdparty/raknet/WindowsIncludes.h @@ -16,9 +16,9 @@ #include #elif defined (_WIN32) && !defined(WINDOWS_PHONE_8) && !defined(WINDOWS_STORE_RT) #define _WINPC -#include +#include #include -#include +#include // Must always include Winsock2.h before windows.h // or else: diff --git a/tools/extract_apk.py b/tools/extract_apk.py new file mode 100755 index 000000000..21f8c8764 --- /dev/null +++ b/tools/extract_apk.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +import setup_venv + +import grabsounds +import sys +import zipfile +import os + +# Constants +TITLE = 'APK Extractor' +ASSETS_DIR = 'assets/' +SOUND_DATA_FILE = 'libminecraftpe.so' + +# Determine Mode +use_gui = len(sys.argv) < 2 +if use_gui: + # Setup GUI + import tkinter as tk + from tkinter import filedialog, messagebox + root = tk.Tk() + root.withdraw() + +# Show Information +def info(msg): + print(msg) + if use_gui: + messagebox.showinfo(title=TITLE, message=msg) + +# Extract Sounds +def extract_sounds(apk_zip): + # Search For File + for name in apk_zip.namelist(): + if os.path.basename(name) == SOUND_DATA_FILE: + with apk_zip.open(name) as sound_data: + grabsounds.main(sound_data) + return + raise Exception('Unable to find sound data!') + +# Extract Assets +def extract_assets(apk_zip): + assets = os.path.dirname(os.path.abspath(__file__)) + assets = os.path.join(assets, '..', 'game', 'assets') + # Search For Assets + for name in apk_zip.namelist(): + if name.startswith(ASSETS_DIR): + # Found Asset + short_name = name[len(ASSETS_DIR):] + print(f'Extracting Asset {short_name}...') + out = os.path.join(assets, short_name) + os.makedirs(os.path.dirname(out), exist_ok=True) + # Extract + with open(out, 'wb') as file: + file.write(apk_zip.read(name)) + +# Open APK +def open_apk(): + if use_gui: + out = filedialog.askopenfile('rb', title=TITLE, filetypes=[('APK', '*.apk')]) + if out is None: + sys.exit() + return out + else: + return open(sys.argv[1], 'rb') + +# Main +def main(): + with open_apk() as apk: + # Extract + with zipfile.ZipFile(apk) as apk_zip: + extract_sounds(apk_zip) + extract_assets(apk_zip) + # Done + info('Done!') + +# Handle Errors +try: + main() +except Exception as e: + if use_gui: + info('An error has occurred!') + raise diff --git a/tools/grabsounds.py b/tools/grabsounds.py index 42bacb235..9040bc8fc 100755 --- a/tools/grabsounds.py +++ b/tools/grabsounds.py @@ -1,155 +1,36 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 +import setup_venv -# Minecraft PE Reverse Engineering Project -# Copyright (C) 2023 iProgramInCpp -# ----------------------------------------------- -# This tool grabs the sound data from the .so file from the source Minecraft PE -# Android *.so file. Offsets are hardcoded to that version, nothing else will work. -# -# TODO: Lookup ELF symbols to un-hardcode the offsets? +import lief import sys import os -import hashlib -# use memory efficient range always -merange = range -try: - merange = xrange # python 2 -except NameError: - pass - -# defines -pcm_addresses = [ - ('PCM_cloth1', 0x00112B08), - ('PCM_cloth2', 0x00117134), - ('PCM_cloth3', 0x0011B760), - ('PCM_cloth4', 0x0011FD8C), - ('PCM_grass1', 0x001243B8), - ('PCM_grass2', 0x0012F00C), - ('PCM_grass3', 0x00139C60), - ('PCM_grass4', 0x001448B4), - ('PCM_gravel1', 0x0014F508), - ('PCM_gravel2', 0x0015A15C), - ('PCM_gravel3', 0x00164DB0), - ('PCM_gravel4', 0x0016FA04), - ('PCM_sand1', 0x0017A658), - ('PCM_sand2', 0x00181214), - ('PCM_sand3', 0x00187DD0), - ('PCM_sand4', 0x0018E98C), - ('PCM_stone1', 0x00195548), - ('PCM_stone2', 0x001A019C), - ('PCM_stone3', 0x001AADF0), - ('PCM_stone4', 0x001B5A44), - ('PCM_wood1', 0x001C0698), - ('PCM_wood2', 0x001CB2EC), - ('PCM_wood3', 0x001D5F40), - ('PCM_wood4', 0x001E0B94), - ('PCM_click', 0x001EB7E8), - ('PCM_explode', 0x001F78A8), - ('PCM_splash', 0x00209A38) -] - -so_file_sha256 = '157af341d13a54cc935bbe24c5e1cf3d02d7e40ec20f9859b9853c2e996ebd81' - -header_1 = '// Minecraft Pocket Edition Reverse Engineering Project\n// Copyright (C) 2011 Mojang Specifications.\n' -header_2 = '// Data extracted from libminecraftpe.so (Minecraft PE v0.1.3.apk).\n\n' - -def read_int_from_bytes(arr_bytes, offset): - return arr_bytes[offset] | arr_bytes[offset + 1] << 8 | arr_bytes[offset + 2] << 16 | arr_bytes[offset + 3] << 24 - -def read_short_from_bytes(arr_bytes, offset): - return arr_bytes[offset] | arr_bytes[offset + 1] << 8 - -def format_hex_short(short): - return "{:04x}".format(short) - -def main(): - if len(sys.argv) < 2: - print('Usage:', sys.argv[0], '[libminecraftpe.so] (output dir)') - return - - output_dir = '' - - if len(sys.argv) > 2: - output_dir = sys.argv[2] - - if len(output_dir) == 0: - output_dir = './sound_data/' - - # append a slash to the file name, if it doesn't have one already - if output_dir[len(output_dir) - 1] != '/': - output_dir += '/' - - if not os.path.exists(output_dir): - os.makedirs(output_dir) - - bytes = [] - - # open the file - try: - with open(sys.argv[1],mode='rb') as sofile: - # read all bytes - bytes = sofile.read() - - except FileNotFoundError: - print('ERROR: The file', sys.argv[1], 'was not found.') - return - - # first off, hash the file to ensure it matches - src_sha256 = hashlib.sha256(bytes).hexdigest() - - print('* Source file hash: ', src_sha256) - - if src_sha256 != so_file_sha256: - print('ERROR: Source file does not match the Source APK\'s SO file. Please extract one from the aforementioned APK. See the readme for more details.') - return - - print('* Extracting PCM data...') - - include_all_str = '#pragma once\n\n' + header_1 - include_all_str+= '\n// @NOTE: This is meant to be included in exactly 1 compile object/source file.\n\n' + header_2 - - for item in pcm_addresses: - include_all_str += '#include "' + item[0] + '.h"\n' - ostr = header_1 + header_2 - - channels = read_int_from_bytes(bytes, item[1] + 0) - data_length = read_int_from_bytes(bytes, item[1] + 12) - - # @NOTE: All the PCM sound data is in `.data`. So there's no consts to be found. - - ostr += 'PCMSoundHeader '+item[0]+' =\n{\n' - ostr += '\t' + str(channels) + ',\n' - ostr += '\t' + str(read_int_from_bytes(bytes, item[1] + 4)) + ',\n' - ostr += '\t' + str(read_int_from_bytes(bytes, item[1] + 8)) + ',\n' - ostr += '\t' + str(data_length) - ostr += '\n};\n\n' - - data_length *= channels - - ostr += 'uint16_t '+item[0]+'_data['+str(data_length)+'] =\n{' - - for i in merange(data_length): - if i % 16 == 0: - ostr += '\n\t' - ostr += '0x'+format_hex_short(read_short_from_bytes(bytes, item[1] + 16 + i * 2)) + ',' - - ostr += '\n};\n' - - filename = output_dir + item[0] + '.h' - with open(filename, 'w') as of: - of.write(ostr) - - include_all_str += '\n\n' - - for item in pcm_addresses: - include_all_str += 'SoundDesc SA_' + item[0][4:] + '(' + item[0] + ', ' + item[0] + '_data);\n' - - with open(output_dir + 'sounds.h', 'w') as of: - of.write(include_all_str) - - pass - - +# Main Function +def main(file): + # Output Directory + out = os.path.dirname(os.path.abspath(__file__)) + out = os.path.join(out, '..', 'game', 'assets', 'sound') + os.makedirs(out, exist_ok=True) + # Extract Sound Data + elf = lief.parse(file) + prefix = 'PCM_' + for sym in elf.dynamic_symbols: + if sym.name.startswith('PCM_'): + # Found Sound Symbol, Extract It + name = sym.name[len(prefix):] + print(f'Extracting Sound {name}...') + path = os.path.join(out, name + '.pcm') + data = bytes(elf.get_content_from_virtual_address(sym.value, sym.size)) + with open(path, 'wb') as file: + file.write(data) + +# Entrypoint if __name__ == '__main__': - main() + # Check Arguments + if len(sys.argv) < 2: + print(f'USAGE: {__file__} libminecraftpe.so') + sys.exit() + # Run + main(sys.argv[1]) + # Done + print('Done!') diff --git a/tools/setup_venv.py b/tools/setup_venv.py new file mode 100644 index 000000000..ae6010bfc --- /dev/null +++ b/tools/setup_venv.py @@ -0,0 +1,44 @@ +import os +import venv +import sys +import subprocess +import platform + +# Find Binary Directory +bin_dir = 'bin' +if platform.system() == 'Windows': + bin_dir = 'Scripts' + +# Paths +path = os.path.dirname(os.path.abspath(__file__)) +path = os.path.join(path, 'venv') +valid_file = os.path.join(path, '.valid') + +# Open In Virtualenv +def restart_in_venv(path): + print('Activating Virtualenv...') + py = os.path.basename(sys.executable) + py = os.path.join(path, bin_dir, py) + os.execv(py, [py] + sys.argv) + +# Create Virtualenv +def create_venv(path): + # Check If It Already Exists + if os.path.exists(valid_file): + return + # Build Environment + print('Creating Virtualenv...') + builder = venv.EnvBuilder(clear=True, symlinks=False, with_pip=True) + builder.create(path) + # Install LIEF + pip = 'pip' + if platform.system() == 'Windows': + pip += '.exe' + subprocess.run([os.path.join(path, bin_dir, pip), 'install', 'lief']) + # Mark As Created + open(valid_file, 'wb').close() + +# Run +if not sys.executable.startswith(path): + create_venv(path) + restart_in_venv(path)