├── .gitattributes ├── .github └── workflows │ └── gradle.yml ├── .gitignore ├── .gitmodules ├── .run └── Pojlib [build].run.xml ├── LICENSE ├── README.md ├── build.gradle ├── devmods.json ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jre_lwjgl3glfw ├── build.gradle ├── libs │ ├── jsr305.jar │ ├── lwjgl-freetype.jar │ ├── lwjgl-glfw.jar │ ├── lwjgl-jemalloc.jar │ ├── lwjgl-lwjglx.jar │ ├── lwjgl-nanovg.jar │ ├── lwjgl-openal.jar │ ├── lwjgl-opengl.jar │ ├── lwjgl-openvr.jar │ ├── lwjgl-stb.jar │ ├── lwjgl-tinyfd.jar │ └── lwjgl.jar └── src │ └── main │ └── java │ ├── android │ └── util │ │ ├── ArrayMap.java │ │ ├── ContainerHelpers.java │ │ ├── EmptyArray.java │ │ ├── MapCollections.java │ │ └── Objects.java │ ├── net │ ├── java │ │ └── openjdk │ │ │ └── cacio │ │ │ └── ctc │ │ │ ├── ExternalMouseReader.java │ │ │ └── InfdevGrabHandler.java │ └── minecraft │ │ └── client │ │ └── ClientBrandRetriever.java.z │ └── org │ └── lwjgl │ ├── glfw │ ├── CallbackBridge.java │ ├── Callbacks.java │ ├── GLFW.java │ ├── GLFWNativeCocoa.java │ ├── GLFWNativeEGL.java │ ├── GLFWNativeNSGL.java │ ├── GLFWNativeOSMesa.java │ ├── GLFWNativeWGL.java │ ├── GLFWNativeWayland.java │ ├── GLFWNativeWin32.java │ ├── GLFWNativeX11.java │ └── GLFWWindowProperties.java │ ├── input │ └── InfdevMouse.java │ └── opengl │ └── GLCapabilities.java ├── libs └── unity-classes.jar ├── mods.json ├── settings.gradle ├── src └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── hacks │ │ ├── ResConfHack.jar │ │ └── resolv.conf │ ├── immediatelyfast.json │ ├── lwjgl │ │ ├── lwjgl-glfw-classes.jar │ │ └── version │ ├── modernfix-mixins.properties │ ├── moreculling.toml │ ├── options.txt │ ├── servers.dat │ ├── smoothboot.json │ ├── sodium-options.json │ └── vivecraft-client-config.json │ ├── java │ ├── com │ │ └── oracle │ │ │ └── dalvik │ │ │ └── VMLauncher.java │ ├── dalvik │ │ └── annotation │ │ │ └── optimization │ │ │ └── CriticalNative.java │ ├── org │ │ └── lwjgl │ │ │ └── glfw │ │ │ └── CallbackBridge.java │ └── pojlib │ │ ├── API.java │ │ ├── APIHandler.java │ │ ├── InstanceHandler.java │ │ ├── UnityPlayerActivity.java │ │ ├── account │ │ ├── LoginHelper.java │ │ ├── MinecraftAccount.java │ │ ├── Msa.java │ │ └── TokenPersistence.java │ │ ├── input │ │ ├── AWTInputBridge.java │ │ ├── CriticalNativeTest.java │ │ ├── EfficientAndroidLWJGLKeycode.java │ │ ├── GrabListener.java │ │ ├── LwjglGlfwKeycode.java │ │ └── gamepad │ │ │ ├── DefaultDataProvider.java │ │ │ ├── Gamepad.java │ │ │ ├── GamepadButton.java │ │ │ ├── GamepadDataProvider.java │ │ │ ├── GamepadDpad.java │ │ │ ├── GamepadEmulatedButton.java │ │ │ ├── GamepadJoystick.java │ │ │ ├── GamepadMap.java │ │ │ └── GamepadMapStore.java │ │ ├── install │ │ ├── FabricMeta.java │ │ ├── Installer.java │ │ ├── MinecraftMeta.java │ │ ├── QuiltMeta.java │ │ └── VersionInfo.java │ │ └── util │ │ ├── Constants.java │ │ ├── FileUtil.java │ │ ├── GsonUtils.java │ │ ├── JREUtils.java │ │ ├── Logger.java │ │ ├── MCOptionUtils.java │ │ ├── MSAException.java │ │ ├── MathUtils.java │ │ ├── VLoader.java │ │ ├── Version.java │ │ ├── download │ │ ├── DownloadManager.java │ │ ├── DownloadUtils.java │ │ ├── StreamDL.java │ │ └── StreamListener.java │ │ └── json │ │ ├── MinecraftInstances.java │ │ ├── ModrinthIndexJson.java │ │ ├── ModsJson.java │ │ └── ProjectInfo.java │ ├── jni │ ├── Android.mk │ ├── Application.mk │ ├── GL │ │ ├── gl.h │ │ └── glext.h │ ├── awt_bridge.c │ ├── awt_xawt │ │ └── xawt_fake.c │ ├── egl_bridge.c │ ├── environ │ │ ├── environ.c │ │ └── environ.h │ ├── input_bridge_v3.c │ ├── jre_launcher.c │ ├── libopenxr_loader.so │ ├── log.h │ ├── openxr │ │ ├── openxr.h │ │ ├── openxr_loader_negotiation.h │ │ ├── openxr_platform.h │ │ ├── openxr_platform_defines.h │ │ ├── openxr_reflection.h │ │ ├── openxr_reflection_parent_structs.h │ │ └── openxr_reflection_structs.h │ ├── stdio_is.c │ ├── utils.c │ ├── utils.h │ └── vloader.cpp │ └── jniLibs │ └── arm64-v8a │ ├── libjnidispatch.so │ ├── libltw.so │ ├── liblwjgl.so │ ├── liblwjgl_lmdb.so │ ├── liblwjgl_nanovg.so │ ├── liblwjgl_opengl.so │ ├── liblwjgl_opengles.so │ ├── liblwjgl_openvr.so │ ├── liblwjgl_stb.so │ ├── liblwjgl_tinyfd.so │ ├── libopenal.so │ └── libsqlitejdbc.so └── supportedVersions.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # Linux start script should use lf 4 | /gradlew text eol=lf 5 | # These are Windows script files and should use crlf 6 | *.bat text eol=crlf 7 | *.so filter=lfs diff=lfs merge=lfs -text 8 | -------------------------------------------------------------------------------- /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | # This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time 6 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle 7 | 8 | name: Build Pojlib 9 | 10 | on: 11 | workflow_dispatch: 12 | push: 13 | pull_request: 14 | branches: [ "master", "QuestCraft" ] 15 | 16 | permissions: 17 | contents: read 18 | 19 | jobs: 20 | build: 21 | runs-on: windows-2022 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | with: 26 | submodules: true 27 | - name: Set up JDK 11 28 | uses: actions/setup-java@v3 29 | with: 30 | java-version: '11' 31 | distribution: 'temurin' 32 | - uses: nttld/setup-ndk@v1 33 | with: 34 | ndk-version: r26b 35 | local-cache: true 36 | link-to-sdk: true 37 | - name: Make Gradle wrapper executable and pull LFS 38 | run: git lfs pull | chmod +x ./gradlew 39 | - name: Decode keystore 40 | run: | 41 | bash -c 'base64 --decode <<< "$QCXR_KEYSTORE_BASE64" > qcxr.keystore' 42 | env: 43 | QCXR_KEYSTORE_BASE64: ${{ secrets.QCXR_KEYSTORE_BASE64 }} 44 | - name: Build with Gradle 45 | uses: gradle/gradle-build-action@v2 46 | with: 47 | arguments: build 48 | env: 49 | QCXR_KEYSTORE_ALIAS: ${{ secrets.QCXR_KEYSTORE_ALIAS }} 50 | QCXR_KEYSTORE_PASS: ${{ secrets.QCXR_KEYSTORE_PASS }} 51 | 52 | - name: Upload AAR 53 | uses: actions/upload-artifact@v4 54 | with: 55 | name: app-debug 56 | path: build/outputs/aar/* 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Gradle project-specific cache directory 2 | .gradle 3 | 4 | # Ignore Gradle build output directory 5 | build 6 | lib/build 7 | # Misc files 8 | .idea 9 | local.properties 10 | .github 11 | .DS_Store 12 | *.iml 13 | *.ipr 14 | *.iws 15 | .settings 16 | .vscode 17 | bin 18 | .classpath 19 | .project 20 | /.cxx 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "wrapper"] 2 | path = wrapper 3 | url = https://github.com/QuestCraftPlusPlus/Wrapper-IL2CPP.git 4 | -------------------------------------------------------------------------------- /.run/Pojlib [build].run.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | true 20 | false 21 | false 22 | 23 | 24 | 25 | 26 | 33 | 38 | 40 | true 41 | true 42 | false 43 | false 44 | 45 | 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU Lesser General Public License 2 | ================================= 3 | 4 | _Version 3, 29 June 2007_ 5 | _Copyright © 2007 Free Software Foundation, Inc. <>_ 6 | 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | 11 | This version of the GNU Lesser General Public License incorporates 12 | the terms and conditions of version 3 of the GNU General Public 13 | License, supplemented by the additional permissions listed below. 14 | 15 | ### 0. Additional Definitions 16 | 17 | As used herein, “this License” refers to version 3 of the GNU Lesser 18 | General Public License, and the “GNU GPL” refers to version 3 of the GNU 19 | General Public License. 20 | 21 | “The Library” refers to a covered work governed by this License, 22 | other than an Application or a Combined Work as defined below. 23 | 24 | An “Application” is any work that makes use of an interface provided 25 | by the Library, but which is not otherwise based on the Library. 26 | Defining a subclass of a class defined by the Library is deemed a mode 27 | of using an interface provided by the Library. 28 | 29 | A “Combined Work” is a work produced by combining or linking an 30 | Application with the Library. The particular version of the Library 31 | with which the Combined Work was made is also called the “Linked 32 | Version”. 33 | 34 | The “Minimal Corresponding Source” for a Combined Work means the 35 | Corresponding Source for the Combined Work, excluding any source code 36 | for portions of the Combined Work that, considered in isolation, are 37 | based on the Application, and not on the Linked Version. 38 | 39 | The “Corresponding Application Code” for a Combined Work means the 40 | object code and/or source code for the Application, including any data 41 | and utility programs needed for reproducing the Combined Work from the 42 | Application, but excluding the System Libraries of the Combined Work. 43 | 44 | ### 1. Exception to Section 3 of the GNU GPL 45 | 46 | You may convey a covered work under sections 3 and 4 of this License 47 | without being bound by section 3 of the GNU GPL. 48 | 49 | ### 2. Conveying Modified Versions 50 | 51 | If you modify a copy of the Library, and, in your modifications, a 52 | facility refers to a function or data to be supplied by an Application 53 | that uses the facility (other than as an argument passed when the 54 | facility is invoked), then you may convey a copy of the modified 55 | version: 56 | 57 | * **a)** under this License, provided that you make a good faith effort to 58 | ensure that, in the event an Application does not supply the 59 | function or data, the facility still operates, and performs 60 | whatever part of its purpose remains meaningful, or 61 | 62 | * **b)** under the GNU GPL, with none of the additional permissions of 63 | this License applicable to that copy. 64 | 65 | ### 3. Object Code Incorporating Material from Library Header Files 66 | 67 | The object code form of an Application may incorporate material from 68 | a header file that is part of the Library. You may convey such object 69 | code under terms of your choice, provided that, if the incorporated 70 | material is not limited to numerical parameters, data structure 71 | layouts and accessors, or small macros, inline functions and templates 72 | (ten or fewer lines in length), you do both of the following: 73 | 74 | * **a)** Give prominent notice with each copy of the object code that the 75 | Library is used in it and that the Library and its use are 76 | covered by this License. 77 | * **b)** Accompany the object code with a copy of the GNU GPL and this license 78 | document. 79 | 80 | ### 4. Combined Works 81 | 82 | You may convey a Combined Work under terms of your choice that, 83 | taken together, effectively do not restrict modification of the 84 | portions of the Library contained in the Combined Work and reverse 85 | engineering for debugging such modifications, if you also do each of 86 | the following: 87 | 88 | * **a)** Give prominent notice with each copy of the Combined Work that 89 | the Library is used in it and that the Library and its use are 90 | covered by this License. 91 | 92 | * **b)** Accompany the Combined Work with a copy of the GNU GPL and this license 93 | document. 94 | 95 | * **c)** For a Combined Work that displays copyright notices during 96 | execution, include the copyright notice for the Library among 97 | these notices, as well as a reference directing the user to the 98 | copies of the GNU GPL and this license document. 99 | 100 | * **d)** Do one of the following: 101 | - **0)** Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | - **1)** Use a suitable shared library mechanism for linking with the 109 | Library. A suitable mechanism is one that **(a)** uses at run time 110 | a copy of the Library already present on the user's computer 111 | system, and **(b)** will operate properly with a modified version 112 | of the Library that is interface-compatible with the Linked 113 | Version. 114 | 115 | * **e)** Provide Installation Information, but only if you would otherwise 116 | be required to provide such information under section 6 of the 117 | GNU GPL, and only to the extent that such information is 118 | necessary to install and execute a modified version of the 119 | Combined Work produced by recombining or relinking the 120 | Application with a modified version of the Linked Version. (If 121 | you use option **4d0**, the Installation Information must accompany 122 | the Minimal Corresponding Source and Corresponding Application 123 | Code. If you use option **4d1**, you must provide the Installation 124 | Information in the manner specified by section 6 of the GNU GPL 125 | for conveying Corresponding Source.) 126 | 127 | ### 5. Combined Libraries 128 | 129 | You may place library facilities that are a work based on the 130 | Library side by side in a single library together with other library 131 | facilities that are not Applications and are not covered by this 132 | License, and convey such a combined library under terms of your 133 | choice, if you do both of the following: 134 | 135 | * **a)** Accompany the combined library with a copy of the same work based 136 | on the Library, uncombined with any other library facilities, 137 | conveyed under the terms of this License. 138 | * **b)** Give prominent notice with the combined library that part of it 139 | is a work based on the Library, and explaining where to find the 140 | accompanying uncombined form of the same work. 141 | 142 | ### 6. Revised Versions of the GNU Lesser General Public License 143 | 144 | The Free Software Foundation may publish revised and/or new versions 145 | of the GNU Lesser General Public License from time to time. Such new 146 | versions will be similar in spirit to the present version, but may 147 | differ in detail to address new problems or concerns. 148 | 149 | Each version is given a distinguishing version number. If the 150 | Library as you received it specifies that a certain numbered version 151 | of the GNU Lesser General Public License “or any later version” 152 | applies to it, you have the option of following the terms and 153 | conditions either of that published version or of any later version 154 | published by the Free Software Foundation. If the Library as you 155 | received it does not specify a version number of the GNU Lesser 156 | General Public License, you may choose any version of the GNU Lesser 157 | General Public License ever published by the Free Software Foundation. 158 | 159 | If the Library as you received it specifies that a proxy can decide 160 | whether future versions of the GNU Lesser General Public License shall 161 | apply, that proxy's public statement of acceptance of any version is 162 | permanent authorization for you to choose that version for the 163 | Library. 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pojlib | Minecraft Launcher Core 2 | [![License: LGPL v3](https://img.shields.io/badge/License-LGPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) 3 | [![Pojlib Build](https://github.com/QuestCraftPlusPlus/Pojlib/actions/workflows/gradle.yml/badge.svg)](https://github.com/QuestCraftPlusPlus/Pojlib/actions/workflows/gradle.yml) 4 | 5 | A Minecraft: Java Edition launcher library partially made with elements from PojavLauncher. 6 | 7 | This library was initially meant for use in QuestCraft but has turned into the perfect library for Minecraft: Java Edition launchers. This includes everything needed for a basic and (soon) even advanced MCJE launchers written in Java (or any other language with interop). 8 | 9 | ## Contributing 10 | 11 | Contributions are always welcome! 12 | 13 | Please ensure your code follows the language's naming conventions, here's a list of a few of the most common languages used in our projects: 14 | 15 | - [Java's Conventions](https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html) 16 | - [C++'s Conventions](https://google.github.io/styleguide/cppguide.html) 17 | 18 | Make sure your pull request describes exactly what the code does and explains why you're making the pull request! 19 | 20 | 21 | ## Credits & Third Party Components 22 | ### Developers: 23 | 24 | * [@TheJudge156](https://github.com/thejudge156) | Senior Maintainer 25 | 26 | * [@CADIndie](https://github.com/CADIndie) | Jr. Maintainer 27 | 28 | * [@MrNavaStar](https://github.com/MrNavaStar) | Previous Main Feature Implementor 29 | 30 | ### Components: 31 | - [PojavLauncher](https://github.com/PojavLauncherTeam/PojavLauncher) (Pojlib Base application): [GNU LGPLv3](https://github.com/khanhduytran0/PojavLauncher/blob/master/LICENSE). 32 | - [LightThinWrapper](https://github.com/PojavLauncherTeam/BigTinyWrapper) (Main renderer/OpenGL Driver for QuestCraft): [PolyForm Shield](https://github.com/PojavLauncherTeam/BigTinyWrapper/blob/master/LICENSE) (Must be removed from forks of Pojlib IF said fork violates the guidelines set by this components license). 33 | - Android Support Libraries: [Apache License 2.0](https://android.googlesource.com/platform/prebuilts/maven_repo/android/+/master/NOTICE.txt). 34 | - [OpenJDK](https://github.com/PojavLauncherTeam/openjdk-multiarch-jdk8u): [GNU GPLv2 License](https://openjdk.java.net/legal/gplv2+ce.html). 35 | - [LWJGL3](https://github.com/PojavLauncherTeam/lwjgl3): [BSD-3 License](https://github.com/LWJGL/lwjgl3/blob/master/LICENSE.md). 36 | - [LWJGLX](https://github.com/PojavLauncherTeam/lwjglx) (LWJGL2 API compatibility layer for LWJGL3): unknown license. 37 | - [Mesa 3D Graphics Library](https://gitlab.freedesktop.org/mesa/mesa): [MIT License](https://docs.mesa3d.org/license.html). 38 | - [libepoxy](https://github.com/anholt/libepoxy): [MIT License](https://github.com/anholt/libepoxy/blob/master/COPYING). 39 | - [bhook](https://github.com/bytedance/bhook) (Used for exit code trapping): [MIT license](https://github.com/bytedance/bhook/blob/main/LICENSE). 40 | - [pro-grade](https://github.com/pro-grade/pro-grade) (Java sandboxing security manager): [Apache License 2.0](https://github.com/pro-grade/pro-grade/blob/master/LICENSE.txt). 41 | 42 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.library") version("7.4.2") 3 | } 4 | 5 | android { 6 | ndkVersion = "26.1.10909125" 7 | compileSdkVersion = "android-34" 8 | defaultConfig { 9 | minSdk 29 10 | multiDexEnabled true 11 | ndk.stl = "c++_shared" 12 | targetSdk 34 13 | } 14 | 15 | buildTypes { 16 | release { 17 | ndk.abiFilters.add("arm64-v8a") 18 | } 19 | debug { 20 | ndk.abiFilters.add("arm64-v8a") 21 | } 22 | } 23 | 24 | externalNativeBuild { 25 | ndkBuild { 26 | path(file("src/main/jni/Android.mk")) 27 | } 28 | } 29 | 30 | buildToolsVersion = "30.0.3" 31 | } 32 | 33 | build { 34 | //finalizedBy(':wrapper:launcher:build') 35 | } 36 | 37 | dependencies { 38 | // This dependency is exported to consumers, that is to say found on their compile classpath. 39 | api("org.apache.commons:commons-math3:3.6.1") 40 | 41 | // This dependency is used internally, and not exposed to consumers on their own compile classpath. 42 | implementation("com.google.guava:guava:31.0.1-jre") 43 | } 44 | 45 | dependencies { 46 | implementation("org.jetbrains:annotations:24.0.1") 47 | implementation("com.google.code.gson:gson:2.12.1") 48 | implementation("org.json:json:20220924") 49 | implementation("commons-io:commons-io:2.13.0") 50 | implementation("commons-codec:commons-codec:1.15") 51 | implementation("androidx.annotation:annotation:1.7.1") 52 | implementation("androidx.core:core:1.13.1") 53 | implementation("com.microsoft.azure:msal4j:1.17.2") 54 | implementation("com.github.Mathias-Boulay:android_gamepad_remapper:2.0.3") 55 | implementation("blank:unity-classes") 56 | } 57 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | org.gradle.jvmargs=-Xmx4G -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jun 04 16:34:57 EDT 2024 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Stop when "xargs" is not available. 209 | if ! command -v xargs >/dev/null 2>&1 210 | then 211 | die "xargs is not available" 212 | fi 213 | 214 | # Use "xargs" to parse quoted args. 215 | # 216 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 217 | # 218 | # In Bash we could simply go: 219 | # 220 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 221 | # set -- "${ARGS[@]}" "$@" 222 | # 223 | # but POSIX shell has neither arrays nor command substitution, so instead we 224 | # post-process each arg (as a line of input to sed) to backslash-escape any 225 | # character that might be a shell metacharacter, then use eval to reverse 226 | # that process (while maintaining the separation between arguments), and wrap 227 | # the whole thing up as a single "set" statement. 228 | # 229 | # This will of course break if any of these variables contains a newline or 230 | # an unmatched quote. 231 | # 232 | 233 | eval "set -- $( 234 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 235 | xargs -n1 | 236 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 237 | tr '\n' ' ' 238 | )" '"$@"' 239 | 240 | exec "$JAVACMD" "$@" 241 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if %ERRORLEVEL% equ 0 goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if %ERRORLEVEL% equ 0 goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group = 'org.lwjgl.glfw' 6 | 7 | configurations.default.setCanBeResolved(true) 8 | 9 | jar { 10 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE 11 | archiveBaseName = "lwjgl-glfw-classes" 12 | destinationDirectory.set(file("../src/main/assets/lwjgl/")) 13 | // Auto update the version with a timestamp so the project jar gets updated by Pojav 14 | File versionFile = file("../src/main/assets/lwjgl/version") 15 | versionFile.write(String.valueOf(new Date().getTime())) 16 | from { 17 | configurations.default.collect { 18 | println(it.getName()) 19 | it.isDirectory() ? it : zipTree(it) 20 | } 21 | } 22 | exclude 'net/java/openjdk/cacio/ctc/**' 23 | } 24 | 25 | java { 26 | toolchain { 27 | languageVersion = JavaLanguageVersion.of(8) 28 | } 29 | } 30 | 31 | dependencies { 32 | implementation fileTree(dir: 'libs', include: ['*.jar']) 33 | } 34 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/jsr305.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/jsr305.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-freetype.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-freetype.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-glfw.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-glfw.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-jemalloc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-jemalloc.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-lwjglx.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-lwjglx.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-nanovg.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-nanovg.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-openal.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-openal.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-opengl.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-opengl.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-openvr.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-openvr.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-stb.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-stb.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl-tinyfd.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl-tinyfd.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/libs/lwjgl.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/jre_lwjgl3glfw/libs/lwjgl.jar -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/android/util/ContainerHelpers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package android.util; 18 | 19 | class ContainerHelpers { 20 | 21 | // This is Arrays.binarySearch(), but doesn't do any argument validation. 22 | static int binarySearch(int[] array, int size, int value) { 23 | int lo = 0; 24 | int hi = size - 1; 25 | 26 | while (lo <= hi) { 27 | final int mid = (lo + hi) >>> 1; 28 | final int midVal = array[mid]; 29 | 30 | if (midVal < value) { 31 | lo = mid + 1; 32 | } else if (midVal > value) { 33 | hi = mid - 1; 34 | } else { 35 | return mid; // value found 36 | } 37 | } 38 | return ~lo; // value not present 39 | } 40 | 41 | static int binarySearch(long[] array, int size, long value) { 42 | int lo = 0; 43 | int hi = size - 1; 44 | 45 | while (lo <= hi) { 46 | final int mid = (lo + hi) >>> 1; 47 | final long midVal = array[mid]; 48 | 49 | if (midVal < value) { 50 | lo = mid + 1; 51 | } else if (midVal > value) { 52 | hi = mid - 1; 53 | } else { 54 | return mid; // value found 55 | } 56 | } 57 | return ~lo; // value not present 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/android/util/EmptyArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package android.util; 17 | 18 | public final class EmptyArray { 19 | private EmptyArray() {} 20 | public static final boolean[] BOOLEAN = new boolean[0]; 21 | public static final byte[] BYTE = new byte[0]; 22 | public static final char[] CHAR = new char[0]; 23 | public static final double[] DOUBLE = new double[0]; 24 | public static final int[] INT = new int[0]; 25 | public static final Class[] CLASS = new Class[0]; 26 | public static final Object[] OBJECT = new Object[0]; 27 | public static final String[] STRING = new String[0]; 28 | public static final Throwable[] THROWABLE = new Throwable[0]; 29 | public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0]; 30 | } 31 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/android/util/Objects.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package android.util; 17 | import java.lang.reflect.Field; 18 | import java.lang.reflect.Modifier; 19 | import java.util.Arrays; 20 | public final class Objects { 21 | private Objects() {} 22 | /** 23 | * Returns true if two possibly-null objects are equal. 24 | */ 25 | public static boolean equal(Object a, Object b) { 26 | return a == b || (a != null && a.equals(b)); 27 | } 28 | public static int hashCode(Object o) { 29 | return (o == null) ? 0 : o.hashCode(); 30 | } 31 | /** 32 | * Returns a string reporting the value of each declared field, via reflection. 33 | * Static and transient fields are automatically skipped. Produces output like 34 | * "SimpleClassName[integer=1234,string="hello",character='c',intArray=[1,2,3]]". 35 | */ 36 | public static String toString(Object o) { 37 | Class c = o.getClass(); 38 | StringBuilder sb = new StringBuilder(); 39 | sb.append(c.getSimpleName()).append('['); 40 | int i = 0; 41 | for (Field f : c.getDeclaredFields()) { 42 | if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0) { 43 | continue; 44 | } 45 | f.setAccessible(true); 46 | try { 47 | Object value = f.get(o); 48 | if (i++ > 0) { 49 | sb.append(','); 50 | } 51 | sb.append(f.getName()); 52 | sb.append('='); 53 | if (value.getClass().isArray()) { 54 | if (value.getClass() == boolean[].class) { 55 | sb.append(Arrays.toString((boolean[]) value)); 56 | } else if (value.getClass() == byte[].class) { 57 | sb.append(Arrays.toString((byte[]) value)); 58 | } else if (value.getClass() == char[].class) { 59 | sb.append(Arrays.toString((char[]) value)); 60 | } else if (value.getClass() == double[].class) { 61 | sb.append(Arrays.toString((double[]) value)); 62 | } else if (value.getClass() == float[].class) { 63 | sb.append(Arrays.toString((float[]) value)); 64 | } else if (value.getClass() == int[].class) { 65 | sb.append(Arrays.toString((int[]) value)); 66 | } else if (value.getClass() == long[].class) { 67 | sb.append(Arrays.toString((long[]) value)); 68 | } else if (value.getClass() == short[].class) { 69 | sb.append(Arrays.toString((short[]) value)); 70 | } else { 71 | sb.append(Arrays.toString((Object[]) value)); 72 | } 73 | } else if (value.getClass() == Character.class) { 74 | sb.append('\'').append(value).append('\''); 75 | } else if (value.getClass() == String.class) { 76 | sb.append('"').append(value).append('"'); 77 | } else { 78 | sb.append(value); 79 | } 80 | } catch (IllegalAccessException unexpected) { 81 | throw new AssertionError(unexpected); 82 | } 83 | } 84 | sb.append("]"); 85 | return sb.toString(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/net/java/openjdk/cacio/ctc/ExternalMouseReader.java: -------------------------------------------------------------------------------- 1 | package net.java.openjdk.cacio.ctc; 2 | 3 | public interface ExternalMouseReader { 4 | int getX(); 5 | int getY(); 6 | } 7 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/net/java/openjdk/cacio/ctc/InfdevGrabHandler.java: -------------------------------------------------------------------------------- 1 | package net.java.openjdk.cacio.ctc; 2 | 3 | public class InfdevGrabHandler { 4 | public static void setMouseReader(ExternalMouseReader reader) { 5 | 6 | } 7 | public static void setGrabbed(boolean grabbed) { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/net/minecraft/client/ClientBrandRetriever.java.z: -------------------------------------------------------------------------------- 1 | package net.minecraft.client; 2 | 3 | public class ClientBrandRetriever { 4 | public static String getClientModName() { 5 | // return "vanilla"; 6 | return System.getProperty("net.minecraft.clientmodname", "vanilla"); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/CallbackBridge.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | import java.util.*; 3 | 4 | public class CallbackBridge { 5 | public static final int CLIPBOARD_COPY = 2000; 6 | public static final int CLIPBOARD_PASTE = 2001; 7 | 8 | public static final int EVENT_TYPE_CHAR = 1000; 9 | public static final int EVENT_TYPE_CHAR_MODS = 1001; 10 | public static final int EVENT_TYPE_CURSOR_ENTER = 1002; 11 | public static final int EVENT_TYPE_CURSOR_POS = 1003; 12 | public static final int EVENT_TYPE_FRAMEBUFFER_SIZE = 1004; 13 | public static final int EVENT_TYPE_KEY = 1005; 14 | public static final int EVENT_TYPE_MOUSE_BUTTON = 1006; 15 | public static final int EVENT_TYPE_SCROLL = 1007; 16 | public static final int EVENT_TYPE_WINDOW_SIZE = 1008; 17 | 18 | public static final int ANDROID_TYPE_GRAB_STATE = 0; 19 | 20 | public static final boolean INPUT_DEBUG_ENABLED; 21 | 22 | // TODO send grab state event to Android 23 | 24 | static { 25 | INPUT_DEBUG_ENABLED = Boolean.parseBoolean(System.getProperty("glfwstub.debugInput", "false")); 26 | 27 | 28 | /* 29 | if (isDebugEnabled) { 30 | //try { 31 | //debugEventStream = new PrintStream(new File(System.getProperty("user.dir"), "glfwstub_inputeventlog.txt")); 32 | debugEventStream = System.out; 33 | //} catch (FileNotFoundException e) { 34 | // e.printStackTrace(); 35 | //} 36 | } 37 | 38 | //Quick and dirty: debul all key inputs to System.out 39 | */ 40 | 41 | Runtime.getRuntime().addShutdownHook(new Thread(CallbackBridge::restartUnitySession)); 42 | } 43 | 44 | public static native void restartUnitySession(); 45 | public static void sendData(int type, String data) { 46 | nativeSendData(false, type, data); 47 | } 48 | public static native void nativeSendData(boolean isAndroid, int type, String data); 49 | public static native boolean nativeSetInputReady(boolean ready); 50 | public static native String nativeClipboard(int action, byte[] copy); 51 | public static native void nativeSetGrabbing(boolean grab); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/Callbacks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright LWJGL. All rights reserved. 3 | * License terms: https://www.lwjgl.org/license 4 | */ 5 | package org.lwjgl.glfw; 6 | 7 | import org.lwjgl.system.*; 8 | 9 | import static org.lwjgl.system.Checks.*; 10 | import static org.lwjgl.system.JNI.*; 11 | import static org.lwjgl.system.MemoryUtil.*; 12 | import java.lang.reflect.*; 13 | 14 | /** Utility class for GLFW callbacks. */ 15 | public final class Callbacks { 16 | 17 | private Callbacks() {} 18 | 19 | /** 20 | * Resets all callbacks for the specified GLFW window to {@code NULL} and {@link Callback#free frees} all previously set callbacks. 21 | * 22 | *

This method resets only callbacks registered with a GLFW window. Non-window callbacks (registered with 23 | * {@link GLFW#glfwSetErrorCallback SetErrorCallback}, {@link GLFW#glfwSetMonitorCallback SetMonitorCallback}, etc.) must be reset and freed 24 | * separately.

25 | * 26 | *

This method is not official GLFW API. It exists in LWJGL to simplify window callback cleanup.

27 | * 28 | * @param window the GLFW window 29 | */ 30 | public static void glfwFreeCallbacks(@NativeType("GLFWwindow *") long window) { 31 | if (Checks.CHECKS) { 32 | check(window); 33 | } 34 | 35 | try { 36 | for (Method callback : GLFW.class.getMethods()) { 37 | if (callback.getName().startsWith("glfwSet") && callback.getName().endsWith("Callback")) { 38 | if (callback.getParameterCount() == 1) { 39 | callback.invoke(null, (Object)null); 40 | } else { 41 | callback.invoke(null, GLFW.glfwGetCurrentContext(), null); 42 | } 43 | } 44 | } 45 | } catch (IllegalAccessException|NullPointerException e) { 46 | throw new RuntimeException("org.lwjgl.GLFW.glfwSetXXXCallback() must be set to public and static", e); 47 | } catch (InvocationTargetException e) { 48 | throw new RuntimeException(e); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeCocoa.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.system.NativeType; 4 | 5 | public class GLFWNativeCocoa { 6 | @NativeType("CGDirectDisplayID") 7 | public static int glfwGetCocoaMonitor(@NativeType("GLFWmonitor *") long monitor) { 8 | throw new UnsupportedOperationException("Not implemented"); 9 | } 10 | @NativeType("id") 11 | public static long glfwGetCocoaWindow(@NativeType("GLFWwindow *") long window) { 12 | throw new UnsupportedOperationException("Not implemented"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeEGL.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.system.NativeType; 4 | 5 | public class GLFWNativeEGL { 6 | @NativeType("EGLDisplay") 7 | public static long glfwGetEGLDisplay() { 8 | throw new UnsupportedOperationException("Not implemented yet!"); 9 | } 10 | 11 | @NativeType("EGLContext") 12 | public static long glfwGetEGLContext(@NativeType("GLFWwindow *") long window) { 13 | throw new UnsupportedOperationException("Not implemented yet!"); 14 | } 15 | 16 | @NativeType("EGLSurface") 17 | public static long glfwGetEGLSurface(@NativeType("GLFWwindow *") long window) { 18 | throw new UnsupportedOperationException("Not implemented yet!"); 19 | } 20 | 21 | @NativeType("EGLConfig") 22 | public static long glfwGetEGLConfig(@NativeType("GLFWwindow *") long window) { 23 | throw new UnsupportedOperationException("Not implemented yet!"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeNSGL.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.system.NativeType; 4 | 5 | public class GLFWNativeNSGL { 6 | @NativeType("id") 7 | public static long glfwGetNSGLContext(@NativeType("GLFWwindow *") long window) { 8 | throw new UnsupportedOperationException("Not implemented"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeOSMesa.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.PointerBuffer; 4 | import org.lwjgl.system.NativeType; 5 | 6 | import java.nio.IntBuffer; 7 | 8 | import javax.annotation.Nullable; 9 | 10 | public class GLFWNativeOSMesa { 11 | @NativeType("int") 12 | public static boolean glfwGetOSMesaColorBuffer(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") IntBuffer width, @Nullable @NativeType("int *") IntBuffer height, @Nullable @NativeType("int *") IntBuffer format, @Nullable @NativeType("void **") PointerBuffer buffer) { 13 | throw new UnsupportedOperationException("Not implemented yet!"); 14 | } 15 | 16 | public static int glfwGetOSMesaDepthBuffer(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") IntBuffer width, @Nullable @NativeType("int *") IntBuffer height, @Nullable @NativeType("int *") IntBuffer bytesPerValue, @Nullable @NativeType("void **") PointerBuffer buffer) { 17 | throw new UnsupportedOperationException("Not implemented yet!"); 18 | } 19 | 20 | @NativeType("OSMesaContext") 21 | public static long glfwGetOSMesaContext(@NativeType("GLFWwindow *") long window) { 22 | throw new UnsupportedOperationException("Not implemented yet!"); 23 | } 24 | 25 | @NativeType("int") 26 | public static boolean glfwGetOSMesaColorBuffer(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") int[] width, @Nullable @NativeType("int *") int[] height, @Nullable @NativeType("int *") int[] format, @Nullable @NativeType("void **") PointerBuffer buffer) { 27 | throw new UnsupportedOperationException("Not implemented yet!"); 28 | } 29 | 30 | public static int glfwGetOSMesaDepthBuffer(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") int[] width, @Nullable @NativeType("int *") int[] height, @Nullable @NativeType("int *") int[] bytesPerValue, @Nullable @NativeType("void **") PointerBuffer buffer) { 31 | throw new UnsupportedOperationException("Not implemented yet!"); 32 | } 33 | } -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeWGL.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.system.NativeType; 4 | 5 | public class GLFWNativeWGL { 6 | @NativeType("HGLRC") 7 | public static long glfwGetWGLContext(@NativeType("GLFWwindow *") long window) { 8 | throw new UnsupportedOperationException("Not implemented"); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeWayland.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.system.NativeType; 4 | 5 | public class GLFWNativeWayland { 6 | @NativeType("struct wl_display *") 7 | public static long glfwGetWaylandDisplay() { 8 | throw new UnsupportedOperationException("Not implemented"); 9 | } 10 | 11 | @NativeType("struct wl_output *") 12 | public static long glfwGetWaylandMonitor(@NativeType("GLFWmonitor *") long monitor) { 13 | throw new UnsupportedOperationException("Not implemented"); 14 | } 15 | 16 | @NativeType("struct wl_surface *") 17 | public static long glfwGetWaylandWindow(@NativeType("GLFWwindow *") long window) { 18 | throw new UnsupportedOperationException("Not implemented"); 19 | } 20 | } -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeWin32.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.system.NativeType; 4 | 5 | import javax.annotation.Nullable; 6 | 7 | public class GLFWNativeWin32 { 8 | @Nullable 9 | @NativeType("char const *") 10 | public static String glfwGetWin32Adapter(@NativeType("GLFWmonitor *") long monitor) { 11 | throw new UnsupportedOperationException("Not implemented"); 12 | } 13 | 14 | @Nullable 15 | @NativeType("char const *") 16 | public static String glfwGetWin32Monitor(@NativeType("GLFWmonitor *") long monitor) { 17 | throw new UnsupportedOperationException("Not implemented"); 18 | } 19 | 20 | @NativeType("HWND") 21 | public static long glfwGetWin32Window(@NativeType("GLFWwindow *") long window) { 22 | throw new UnsupportedOperationException("Not implemented"); 23 | } 24 | 25 | @NativeType("GLFWwindow *") 26 | public static long glfwAttachWin32Window(@NativeType("HWND") long handle, @NativeType("GLFWwindow *") long share) { 27 | throw new UnsupportedOperationException("Not implemented"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWNativeX11.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import org.lwjgl.system.NativeType; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | import javax.annotation.Nullable; 8 | 9 | public class GLFWNativeX11 { 10 | @NativeType("Display *") 11 | public static long glfwGetX11Display() { 12 | throw new UnsupportedOperationException("Not implemented"); 13 | } 14 | 15 | @NativeType("RRCrtc") 16 | public static long glfwGetX11Adapter(@NativeType("GLFWmonitor *") long monitor) { 17 | throw new UnsupportedOperationException("Not implemented"); 18 | } 19 | 20 | @NativeType("RROutput") 21 | public static long glfwGetX11Monitor(@NativeType("GLFWmonitor *") long monitor) { 22 | throw new UnsupportedOperationException("Not implemented"); 23 | } 24 | 25 | @NativeType("Window") 26 | public static long glfwGetX11Window(@NativeType("GLFWwindow *") long window) { 27 | throw new UnsupportedOperationException("Not implemented"); 28 | } 29 | 30 | public static void glfwSetX11SelectionString(@NativeType("char const *") ByteBuffer string) { 31 | throw new UnsupportedOperationException("Not implemented"); 32 | } 33 | 34 | public static void glfwSetX11SelectionString(@NativeType("char const *") CharSequence string) { 35 | throw new UnsupportedOperationException("Not implemented"); 36 | } 37 | @Nullable 38 | @NativeType("char const *") 39 | public static String glfwGetX11SelectionString() { 40 | throw new UnsupportedOperationException("Not implemented"); 41 | } 42 | } -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/glfw/GLFWWindowProperties.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import java.util.*; 4 | 5 | public class GLFWWindowProperties { 6 | public int width = GLFW.mGLFWWindowWidth; 7 | public int height = GLFW.mGLFWWindowHeight; 8 | public int x, y; 9 | public CharSequence title; 10 | public boolean shouldClose, isInitialSizeCalled, isCursorEntered; 11 | public Map inputModes = new HashMap<>(); 12 | public Map windowAttribs = new HashMap<>(); 13 | } 14 | -------------------------------------------------------------------------------- /jre_lwjgl3glfw/src/main/java/org/lwjgl/input/InfdevMouse.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.input; 2 | 3 | import net.java.openjdk.cacio.ctc.ExternalMouseReader; 4 | import net.java.openjdk.cacio.ctc.InfdevGrabHandler; 5 | 6 | public class InfdevMouse implements ExternalMouseReader, Mouse.EmptyCursorGrabListener { 7 | static { 8 | InfdevGrabHandler.setMouseReader(new InfdevMouse()); 9 | } 10 | 11 | @Override 12 | public int getX() { 13 | return Mouse.getAbsoluteX(); 14 | } 15 | 16 | @Override 17 | public int getY() { 18 | return Mouse.getAbsoluteY(); 19 | } 20 | 21 | @Override 22 | public void onGrab(boolean grabbing) { 23 | InfdevGrabHandler.setGrabbed(grabbing); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /libs/unity-classes.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/libs/unity-classes.jar -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/7.5.1/userguide/multi_project_builds.html 8 | */ 9 | 10 | pluginManagement { 11 | repositories { 12 | gradlePluginPortal() 13 | google() 14 | mavenCentral() 15 | } 16 | } 17 | dependencyResolutionManagement { 18 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 19 | repositories { 20 | google() 21 | mavenCentral() 22 | maven { 23 | url = uri("https://jitpack.io") 24 | } 25 | flatDir { 26 | dirs("libs") 27 | dirs("wrapper/unityLibrary/libs") 28 | } 29 | } 30 | } 31 | 32 | rootProject.name = "Pojlib" 33 | include ":jre_lwjgl3glfw" 34 | 35 | -------------------------------------------------------------------------------- /src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/assets/hacks/ResConfHack.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/src/main/assets/hacks/ResConfHack.jar -------------------------------------------------------------------------------- /src/main/assets/hacks/resolv.conf: -------------------------------------------------------------------------------- 1 | nameserver 8.8.8.8 2 | nameserver 8.8.4.4 -------------------------------------------------------------------------------- /src/main/assets/immediatelyfast.json: -------------------------------------------------------------------------------- 1 | { 2 | "font_atlas_resizing": true, 3 | "map_atlas_generation": true, 4 | "hud_batching": false, 5 | "dont_add_info_into_debug_hud": false, 6 | "debug_only_and_not_recommended_disable_universal_batching": false 7 | } -------------------------------------------------------------------------------- /src/main/assets/lwjgl/lwjgl-glfw-classes.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/61e1d9e600ef0e2518a1b12affdbfa97374ad6a8/src/main/assets/lwjgl/lwjgl-glfw-classes.jar -------------------------------------------------------------------------------- /src/main/assets/lwjgl/version: -------------------------------------------------------------------------------- 1 | 1738988056798 -------------------------------------------------------------------------------- /src/main/assets/modernfix-mixins.properties: -------------------------------------------------------------------------------- 1 | # This is the configuration file for ModernFix. 2 | # In general, prefer using the config screen to editing this file. It can be accessed 3 | # via the standard mod menu on your respective mod loader. Changes will, however, 4 | # require restarting the game to take effect. 5 | # 6 | # The following options can be enabled or disabled if there is a compatibility issue. 7 | # Add a line with your option name and =true or =false at the bottom of the file to enable 8 | # or disable a rule. For example: 9 | # mixin.perf.dynamic_resources=true 10 | # Do not include the #. You may reset to defaults by deleting this file. 11 | # 12 | # Available options: 13 | # mixin.bugfix.chunk_deadlock=false # (overridden for mod compat) 14 | # mixin.bugfix.concurrency=true # (default) 15 | # mixin.bugfix.ender_dragon_leak=true # (default) 16 | # mixin.bugfix.packet_leak=false # (default) 17 | # mixin.bugfix.paper_chunk_patches=false # (overridden for mod compat) 18 | # mixin.devenv=false # (default) 19 | # mixin.feature.branding=true # (default) 20 | # mixin.feature.direct_stack_trace=false # (default) 21 | # mixin.feature.disable_unihex_font=false # (default) 22 | # mixin.feature.integrated_server_watchdog=true # (default) 23 | # mixin.feature.measure_time=true # (default) 24 | # mixin.feature.snapshot_easter_egg=true # (default) 25 | # mixin.feature.spam_thread_dump=false # (default) 26 | # mixin.feature.spark_profile_launch=false # (default) 27 | # mixin.feature.warn_missing_perf_mods=true # (default) 28 | # mixin.launch.class_search_cache=true # (default) 29 | # mixin.perf.blast_search_trees=true # (default) 30 | # mixin.perf.cache_blockstate_cache_arrays=true # (default) 31 | # mixin.perf.cache_model_materials=true # (default) 32 | # mixin.perf.cache_strongholds=true # (default) 33 | # mixin.perf.cache_upgraded_structures=true # (default) 34 | # mixin.perf.clear_fabric_mapping_tables=false # (default) 35 | # mixin.perf.clear_mixin_classinfo=false # (default) 36 | # mixin.perf.compact_bit_storage=true # (default) 37 | # mixin.perf.dedicated_reload_executor=true # (default) 38 | # mixin.perf.deduplicate_climate_parameters=false # (default) 39 | # mixin.perf.deduplicate_location=false # (default) 40 | # mixin.perf.deduplicate_wall_shapes=true # (default) 41 | # mixin.perf.dynamic_dfu=true # (default) 42 | # mixin.perf.dynamic_entity_renderers=false # (default) 43 | # mixin.perf.dynamic_resources=false # (default) 44 | # mixin.perf.dynamic_resources.diagonalfences=true # (default) 45 | # mixin.perf.dynamic_structure_manager=true # (default) 46 | # mixin.perf.faster_item_rendering=false # (default) 47 | # mixin.perf.faster_texture_stitching=true # (default) 48 | # mixin.perf.model_optimizations=true # (default) 49 | # mixin.perf.nbt_memory_usage=false # (overridden for mod compat) 50 | # mixin.perf.reduce_blockstate_cache_rebuilds=true # (default) 51 | # mixin.perf.remove_biome_temperature_cache=true # (default) 52 | # mixin.perf.remove_spawn_chunks=false # (default) 53 | # mixin.perf.resourcepacks=true # (default) 54 | # mixin.perf.state_definition_construct=true # (default) 55 | # mixin.perf.thread_priorities=true # (default) 56 | # mixin.safety=true # (default) 57 | # 58 | # User overrides go here. 59 | mixin.perf.dynamic_entity_renderers=true 60 | mixin.perf.dynamic_resources=true 61 | mixin.perf.faster_item_rendering=true 62 | 63 | -------------------------------------------------------------------------------- /src/main/assets/moreculling.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | enableSodiumMenu = true 3 | cloudCulling = true 4 | signTextCulling = true 5 | rainCulling = true 6 | useBlockStateCulling = true 7 | useCustomItemFrameRenderer = true 8 | itemFrameMapCulling = true 9 | useItemFrameLOD = true 10 | itemFrameLODRange = 16 11 | useItemFrame3FaceCulling = true 12 | itemFrame3FaceCullingRange = 2.0 13 | leavesCullingMode = "FAST" 14 | leavesCullingAmount = 2 15 | includeMangroveRoots = true 16 | powderSnowCulling = true 17 | endGatewayCulling = true 18 | beaconBeamCulling = true 19 | entityModelCulling = false 20 | useOnModdedBlocksByDefault = true 21 | 22 | [modCompatibility] 23 | minecraft = true 24 | -------------------------------------------------------------------------------- /src/main/assets/options.txt: -------------------------------------------------------------------------------- 1 | version:3218 2 | autoJump:false 3 | operatorItemsTab:false 4 | autoSuggestions:true 5 | chatColors:true 6 | chatLinks:true 7 | chatLinksPrompt:true 8 | enableVsync:false 9 | entityShadows:false 10 | forceUnicodeFont:false 11 | discrete_mouse_scroll:false 12 | invertYMouse:false 13 | realmsNotifications:true 14 | reducedDebugInfo:false 15 | showSubtitles:false 16 | directionalAudio:false 17 | touchscreen:false 18 | fullscreen:false 19 | bobView:false 20 | toggleCrouch:false 21 | toggleSprint:false 22 | darkMojangStudiosBackground:true 23 | hideLightningFlashes:false 24 | mouseSensitivity:0.5 25 | fov:0.0 26 | screenEffectScale:1.0 27 | fovEffectScale:1.0 28 | darknessEffectScale:1.0 29 | gamma:-0.2 30 | renderDistance:4 31 | simulationDistance:4 32 | entityDistanceScaling:1.0 33 | guiScale:4 34 | particles:2 35 | maxFps:260 36 | graphicsMode:0 37 | ao:true 38 | prioritizeChunkUpdates:1 39 | biomeBlendRadius:0 40 | renderClouds:"false" 41 | resourcePacks:["vanilla","fabric"] 42 | incompatibleResourcePacks:[] 43 | lastServer: 44 | lang:en_us 45 | soundDevice:"" 46 | chatVisibility:0 47 | chatOpacity:1.0 48 | chatLineSpacing:0.0 49 | textBackgroundOpacity:0.5 50 | backgroundForChatOnly:true 51 | hideServerAddress:false 52 | advancedItemTooltips:true 53 | pauseOnLostFocus:true 54 | overrideWidth:2960 55 | overrideHeight:1440 56 | heldItemTooltips:true 57 | chatHeightFocused:1.0 58 | chatDelay:0.0 59 | chatHeightUnfocused:0.44366196 60 | chatScale:1.0 61 | chatWidth:1.0 62 | mipmapLevels:4 63 | useNativeTransport:true 64 | mainHand:"right" 65 | attackIndicator:1 66 | narrator:0 67 | tutorialStep:none 68 | mouseWheelSensitivity:1.0 69 | rawMouseInput:true 70 | glDebugVerbosity:1 71 | skipMultiplayerWarning:true 72 | skipRealms32bitWarning:false 73 | hideMatchedNames:true 74 | joinedFirstServer:true 75 | hideBundleTutorial:false 76 | syncChunkWrites:false 77 | showAutosaveIndicator:false 78 | allowServerListing:true 79 | onlyShowSecureChat:false 80 | panoramaScrollSpeed:1.0 81 | debugifyTelemetry:0 82 | telemetryOptInExtra:false 83 | key_key.attack:key.mouse.left 84 | key_key.use:key.mouse.right 85 | key_key.forward:key.keyboard.w 86 | key_key.left:key.keyboard.a 87 | key_key.back:key.keyboard.s 88 | key_key.right:key.keyboard.d 89 | key_key.jump:key.keyboard.space 90 | key_key.sneak:key.keyboard.left.shift 91 | key_key.sprint:key.keyboard.left.control 92 | key_key.drop:key.keyboard.q 93 | key_key.inventory:key.keyboard.e 94 | key_key.chat:key.keyboard.t 95 | key_key.playerlist:key.keyboard.tab 96 | key_key.pickItem:key.mouse.middle 97 | key_key.command:key.keyboard.slash 98 | key_key.socialInteractions:key.keyboard.p 99 | key_key.screenshot:key.keyboard.f2 100 | key_key.togglePerspective:key.keyboard.f5 101 | key_key.smoothCamera:key.keyboard.unknown 102 | key_key.fullscreen:key.keyboard.f11 103 | key_key.spectatorOutlines:key.keyboard.unknown 104 | key_key.swapOffhand:key.keyboard.f 105 | key_key.saveToolbarActivator:key.keyboard.c 106 | key_key.loadToolbarActivator:key.keyboard.x 107 | key_key.advancements:key.keyboard.l 108 | key_key.hotbar.1:key.keyboard.1 109 | key_key.hotbar.2:key.keyboard.2 110 | key_key.hotbar.3:key.keyboard.3 111 | key_key.hotbar.4:key.keyboard.4 112 | key_key.hotbar.5:key.keyboard.5 113 | key_key.hotbar.6:key.keyboard.6 114 | key_key.hotbar.7:key.keyboard.7 115 | key_key.hotbar.8:key.keyboard.8 116 | key_key.hotbar.9:key.keyboard.9 117 | key_vivecraft.key.rotateLeft:key.keyboard.left 118 | key_vivecraft.key.rotateRight:key.keyboard.right 119 | key_vivecraft.key.rotateAxis:key.keyboard.unknown 120 | key_vivecraft.key.rotateFree:key.keyboard.home 121 | key_vivecraft.key.walkabout:key.keyboard.end 122 | key_vivecraft.key.teleport:key.keyboard.unknown 123 | key_vivecraft.key.teleportFallback:key.keyboard.unknown 124 | key_vivecraft.key.freeMoveRotate:key.keyboard.unknown 125 | key_vivecraft.key.freeMoveStrafe:key.keyboard.unknown 126 | key_vivecraft.key.toggleMovement:key.keyboard.unknown 127 | key_vivecraft.key.quickTorch:key.keyboard.insert 128 | key_vivecraft.key.hotbarNext:key.keyboard.page.up 129 | key_vivecraft.key.hotbarPrev:key.keyboard.page.down 130 | key_vivecraft.key.hotbarScroll:key.keyboard.unknown 131 | key_vivecraft.key.hotbarSwipeX:key.keyboard.unknown 132 | key_vivecraft.key.hotbarSwipeY:key.keyboard.unknown 133 | key_vivecraft.key.ingameMenuButton:key.keyboard.unknown 134 | key_vivecraft.key.radialMenu:key.keyboard.unknown 135 | key_vivecraft.key.vrInteract:key.keyboard.unknown 136 | key_vivecraft.key.swapMirrorView:key.keyboard.unknown 137 | key_vivecraft.key.exportWorld:key.keyboard.unknown 138 | key_vivecraft.key.toggleKeyboard:key.keyboard.unknown 139 | key_vivecraft.key.moveThirdPersonCam:key.keyboard.unknown 140 | key_vivecraft.key.togglePlayerList:key.keyboard.unknown 141 | key_vivecraft.key.toggleHandheldCam:key.keyboard.unknown 142 | key_vivecraft.key.quickHandheldCam:key.keyboard.unknown 143 | key_vivecraft.key.trackpadTouch:key.keyboard.unknown 144 | key_vivecraft.key.guiLeftClick:key.keyboard.unknown 145 | key_vivecraft.key.guiRightClick:key.keyboard.unknown 146 | key_vivecraft.key.guiMiddleClick:key.keyboard.unknown 147 | key_vivecraft.key.guiShift:key.keyboard.unknown 148 | key_vivecraft.key.guiCtrl:key.keyboard.unknown 149 | key_vivecraft.key.guiAlt:key.keyboard.unknown 150 | key_vivecraft.key.guiScrollUp:key.keyboard.unknown 151 | key_vivecraft.key.guiScrollDown:key.keyboard.unknown 152 | key_vivecraft.key.guiScrollAxis:key.keyboard.unknown 153 | key_vivecraft.key.keyboardClick:key.keyboard.unknown 154 | key_vivecraft.key.keyboardShift:key.keyboard.unknown 155 | key_vivecraft.key.climbeyGrab:key.keyboard.unknown 156 | key_vivecraft.key.climbeyJump:key.keyboard.unknown 157 | key_key.feytweaks.openConfigKey:key.keyboard.unknown 158 | key_key.gamma_utils.gamma_toggle:key.keyboard.g 159 | key_key.gamma_utils.increase_gamma:key.keyboard.up 160 | key_key.gamma_utils.decrease_gamma:key.keyboard.down 161 | key_key.gamma_utils.max_gamma:key.keyboard.unknown 162 | key_key.gamma_utils.min_gamma:key.keyboard.unknown 163 | key_key.gamma_utils.night_vision_toggle:key.keyboard.h 164 | key_key.modmenu.open_menu:key.keyboard.unknown 165 | key_key.push_to_talk:key.keyboard.caps.lock 166 | key_key.whisper:key.keyboard.unknown 167 | key_key.mute_microphone:key.keyboard.m 168 | key_key.disable_voice_chat:key.keyboard.n 169 | key_key.hide_icons:key.keyboard.h 170 | key_key.voice_chat:key.keyboard.v 171 | key_key.voice_chat_settings:key.keyboard.unknown 172 | key_key.voice_chat_group:key.keyboard.g 173 | key_key.voice_chat_toggle_recording:key.keyboard.unknown 174 | key_key.voice_chat_adjust_volumes:key.keyboard.unknown 175 | soundCategory_master:1.0 176 | soundCategory_music:1.0 177 | soundCategory_record:1.0 178 | soundCategory_weather:1.0 179 | soundCategory_block:1.0 180 | soundCategory_hostile:1.0 181 | soundCategory_neutral:1.0 182 | soundCategory_player:1.0 183 | soundCategory_ambient:1.0 184 | soundCategory_voice:1.0 185 | modelPart_cape:true 186 | modelPart_jacket:true 187 | modelPart_left_sleeve:true 188 | modelPart_right_sleeve:true 189 | modelPart_left_pants_leg:true 190 | modelPart_right_pants_leg:true 191 | modelPart_hat:true 192 | fullscreenResolution:1920x1080@90:24 193 | -------------------------------------------------------------------------------- /src/main/assets/servers.dat: -------------------------------------------------------------------------------- 1 | 2 | servers 3 | acceptTexturesipmc.xrcraftmc.comname&XRCraft - QuestCraft's Official Server -------------------------------------------------------------------------------- /src/main/assets/smoothboot.json: -------------------------------------------------------------------------------- 1 | { 2 | "threadCount": { 3 | "bootstrap": 1, 4 | "main": 2 5 | }, 6 | "threadPriority": { 7 | "game": 5, 8 | "bootstrap": 1, 9 | "main": 1, 10 | "io": 1, 11 | "integratedServer": 5 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/assets/sodium-options.json: -------------------------------------------------------------------------------- 1 | { 2 | "quality": { 3 | "weather_quality": "FAST", 4 | "leaves_quality": "FAST", 5 | "enable_vignette": false 6 | }, 7 | "advanced": { 8 | "arena_memory_allocator": "ASYNC", 9 | "allow_direct_memory_access": true, 10 | "enable_memory_tracing": false, 11 | "use_advanced_staging_buffers": true, 12 | "cpu_render_ahead_limit": 3 13 | }, 14 | "performance": { 15 | "chunk_builder_threads": 0, 16 | "always_defer_chunk_updates": false, 17 | "animate_only_visible_textures": true, 18 | "use_entity_culling": true, 19 | "use_particle_culling": true, 20 | "use_fog_occlusion": true, 21 | "use_block_face_culling": true 22 | }, 23 | "notifications": { 24 | "hide_donation_button": true 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/assets/vivecraft-client-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mrMovingCamOffsetZ": "0.0", 3 | "smoothTick": "false", 4 | "mrMovingCamOffsetY": "0.0", 5 | "mrMovingCamOffsetX": "0.0", 6 | "crawlThreshold": "0.82", 7 | "modelArmsMode": "COMPLETE", 8 | "reverseShootingEye": "false", 9 | "fbtExtendedCalibrated": "false", 10 | "closeWithRuntime": "true", 11 | "physicalKeyboardScale": "1.0", 12 | "renderTrackerPositions": "false", 13 | "disableShaderOptimization": "false", 14 | "keyboardKeys": "`1234567890-=qwertyuiop[]\\asdfghjkl;':\"zxcvbnm,./?<>", 15 | "FBTOFFSETS": "0.0,0.0,0.0;0.0,0.0,0.0;0.0,0.0,0.0;0.0,0.0,0.0;0.0,0.0,0.0;0.0,0.0,0.0;0.0,0.0,0.0", 16 | "weaponCollisionNew": "true", 17 | "vrTouchHotbar": "true", 18 | "useCrosshairOcclusion": "true", 19 | "displayMirrorMode": "OFF", 20 | "vrFixedCamrotW": "0.962", 21 | "vrFixedCamrotZ": "0.041", 22 | "realisticRowEnabled": "true", 23 | "vrFixedCamrotY": "0.239", 24 | "vrFixedCamrotX": "0.125", 25 | "low_health_indicator": "true", 26 | "version": "0", 27 | "mixedRealityAlphaMask": "false", 28 | "handCameraFov": "70.0", 29 | "lastUpdate": "", 30 | "unlabeledTrackersUsed": "false", 31 | "playerWalkAnim": "true", 32 | "reverseHands": "false", 33 | "keyboardKeysShift": "~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL;':\"ZXCVBNM,./?<>", 34 | "thirdPersonItems": "false", 35 | "worldScale": "1.0", 36 | "alwaysShowUpdates": "true", 37 | "playerModelArmsScale": "0.5", 38 | "renderVrPlayerAxes": "false", 39 | "hudDistance": "1.25", 40 | "stencilOn": "true", 41 | "hudPitchOffset": "-2.0", 42 | "onlySwordCollision": "false", 43 | "vehicleRotation": "true", 44 | "autoSprint": "true", 45 | "playerLimbsConnected": "true", 46 | "teleportLimitDown": "4", 47 | "ySensitivity": "1.0", 48 | "teleportLimitUp": "1", 49 | "allowAdvancedBindings": "false", 50 | "playerArmAnim": "true", 51 | "mrMovingCamOffsetRotW": "1.0", 52 | "pumpkinEffect": "true", 53 | "seatedHudAltMode": "true", 54 | "guiScale": "0", 55 | "insideBlockSolidColor": "false", 56 | "autoCloseKeyboard": "true", 57 | "mrMovingCamOffsetRotZ": "-0.0", 58 | "headHudScale": "1.0", 59 | "debugCameraTracker": "false", 60 | "autoSprintThreshold": "0.9", 61 | "mrMovingCamOffsetRotX": "-0.0", 62 | "mrMovingCamOffsetRotY": "-0.0", 63 | "QUICKCOMMAND_9": "take this!", 64 | "waterEffect": "true", 65 | "QUICKCOMMAND_1": "/gamemode creative", 66 | "menuBackground": "false", 67 | "QUICKCOMMAND_2": "/help", 68 | "QUICKCOMMAND_3": "/home", 69 | "simulateFalling": "true", 70 | "portalEffect": "true", 71 | "QUICKCOMMAND_4": "/sethome", 72 | "QUICKCOMMAND_5": "/spawn", 73 | "QUICKCOMMAND_6": "hi!", 74 | "realisticSneakEnabled": "true", 75 | "QUICKCOMMAND_7": "bye!", 76 | "QUICKCOMMAND_8": "follow me!", 77 | "analogMovement": "true", 78 | "QUICKCOMMAND_0": "/gamemode survival", 79 | "playerModelType": "VANILLA", 80 | "headToHmdLength": "0.10000000149011612", 81 | "chatNotificationSound": "block.note_block.bell", 82 | "jumpThreshold": "0.05", 83 | "movementSpeedMultiplier": "1.0", 84 | "seated": "false", 85 | "doubleGUIResolution": "false", 86 | "physicalKeyboardTheme": "DEFAULT", 87 | "limitedTeleport": "true", 88 | "RADIALALT_11": "", 89 | "RADIALALT_10": "", 90 | "RADIALALT_13": "", 91 | "RADIALALT_12": "", 92 | "bowMode": "ON", 93 | "allowStandingOriginOffset": "false", 94 | "crosshairScalesWithDistance": "false", 95 | "autoCalibration": "-1.0", 96 | "renderInGameCrosshairMode": "ALWAYS", 97 | "worldRotation": "0.0", 98 | "displayMirrorCenterSmooth": "0.0", 99 | "alwaysSimulateKeyboard": "false", 100 | "keyholeX": "15.0", 101 | "mixedRealityRenderCameraModel": "true", 102 | "thirdPersonItemsCustom": "true", 103 | "fovRedutioncOffset": "0.1", 104 | "RADIAL_2": "vivecraft.key.rotateRight", 105 | "RADIAL_3": "key.pickItem", 106 | "RADIAL_0": "key.drop", 107 | "disableGarbageCollectorMessage": "false", 108 | "RADIAL_1": "key.chat", 109 | "RADIAL_6": "vivecraft.key.rotateLeft", 110 | "RADIAL_7": "key.voice_chat", 111 | "doorHitting": "true", 112 | "RADIAL_4": "vivecraft.key.toggleHandheldCam", 113 | "RADIAL_5": "vivecraft.key.togglePlayerList", 114 | "rememberVr": "true", 115 | "hudOcclusion": "true", 116 | "RADIAL_8": "", 117 | "RADIAL_9": "", 118 | "playerLimbsLimit": "false", 119 | "mixedRealityUndistorted": "true", 120 | "vrSettingsButtonPositionLeft": "true", 121 | "vrFreeMoveMode": "CONTROLLER", 122 | "walkMultiplier": "1.0", 123 | "fovReduction": "false", 124 | "menuAlwaysFollowFace": "false", 125 | "hudMaxScale": "false", 126 | "vrHudLockMode": "WRIST", 127 | "shouldRenderSelf": "false", 128 | "menuWorldSelection": "BOTH", 129 | "useFsaa": "false", 130 | "renderScaleFactor": "1.0", 131 | "showServerPluginMissingMessageAlways": "true", 132 | "realisticBlockInteractEnabled": "true", 133 | "crosshairScale": "1.0", 134 | "hideGUI": "false", 135 | "mainPlayerDataSource": "REALTIME", 136 | "sneakThreshold": "0.4", 137 | "ingameBindingsInGui": "false", 138 | "RADIALALT_4": "", 139 | "RADIALALT_3": "", 140 | "RADIALALT_2": "", 141 | "RADIALALT_1": "", 142 | "RADIALALT_0": "", 143 | "mirrorCrop": "0.15", 144 | "mixedRealityKeyColor": "0,0,0", 145 | "oscTrackerPort": "9000", 146 | "showPlayerHands": "true", 147 | "realisticJumpEnabled": "AUTO", 148 | "vrRadialButtons": "8", 149 | "shaderFullSizeShadowLimbs": "true", 150 | "originOffset": "0.0,0.0,0.0", 151 | "vrToggleButtonEnabled": "true", 152 | "handCameraResScale": "1.0", 153 | "forceHardwareDetection": "0", 154 | "realisticClimbEnabled": "true", 155 | "forceStandingFreeMove": "false", 156 | "renderHeadHitbox": "false", 157 | "inertiaFactor": "NORMAL", 158 | "FBTROTATIONS": "1.0,0.0,0.0,0.0;1.0,0.0,0.0,0.0;1.0,0.0,0.0,0.0;1.0,0.0,0.0,0.0;1.0,0.0,0.0,0.0;1.0,0.0,0.0,0.0;1.0,0.0,0.0,0.0", 159 | "freezeEffect": "true", 160 | "mixedRealityFov": "40.0", 161 | "vrServerBlacklist": "mc.hypixel.net", 162 | "playerModelLegScale": "1.0", 163 | "xSensitivity": "1.0", 164 | "teleportLimitHoriz": "16", 165 | "monoFOV": "0.0", 166 | "physicalKeyboard": "true", 167 | "autoOpenKeyboard": "OFF", 168 | "realisticSwimEnabled": "true", 169 | "keyboardCodes": "96;49;50;51;52;53;54;55;56;57;48;45;61;81;87;69;82;84;89;85;73;79;80;91;93;92;65;83;68;70;71;72;74;75;76;59;39;-1;-1;90;88;67;86;66;78;77;44;46;47;-1;-1;-1", 170 | "RADIALALT_9": "", 171 | "stereoProviderPluginID": "OPENXR", 172 | "RADIALALT_8": "", 173 | "RADIALALT_7": "", 174 | "RADIALALT_6": "", 175 | "RADIALALT_5": "", 176 | "keyboardPressBinds": "false", 177 | "radialModeHold": "true", 178 | "chatNotifications": "NONE", 179 | "renderBlockOutlineMode": "ALWAYS", 180 | "showServerPluginMessage": "SERVER_ONLY", 181 | "reducedPlayerReach": "true", 182 | "modifyPauseMenu": "true", 183 | "guiAppearOverBlock": "true", 184 | "realisticDismountEnabled": "true", 185 | "bcbOn": "true", 186 | "hrtfSelection": "0", 187 | "menuCrosshairScale": "1.0", 188 | "renderDeviceAxes": "false", 189 | "seatedhmd": "false", 190 | "rightclickDelay": "VANILLA", 191 | "displayMirrorUseScreenshotCamera": "false", 192 | "manualCalibration": "-1.0", 193 | "allowCrawling": "true", 194 | "smoothRunTickCount": "20", 195 | "physicalGuiEnabled": "false", 196 | "vrHotswitchingEnabled": "true", 197 | "hudYawOffset": "0.0", 198 | "RADIAL_10": "", 199 | "menuWorldFallbackPanorama": "true", 200 | "shaderPatching": "true", 201 | "fovReductionMin": "0.25", 202 | "swordBlockCollision": "true", 203 | "externalCameraAngleOrder": "XZY", 204 | "RADIAL_12": "", 205 | "guiMipmaps": "false", 206 | "RADIAL_11": "", 207 | "vrFixedCamposX": "-1.0", 208 | "realisticEntityInteractEnabled": "true", 209 | "RADIAL_13": "", 210 | "stencilBufferDisable": "false", 211 | "vrFixedCamposY": "2.5", 212 | "fbtCalibrated": "false", 213 | "vrFixedCamposZ": "2.7", 214 | "QUICKCOMMAND_11": "praise the sun!", 215 | "QUICKCOMMAND_10": "thank you!", 216 | "mixedRealityRenderHands": "false", 217 | "hudOpacity": "1.0", 218 | "vrWorldRotationIncrement": "45.0", 219 | "vrFreeMoveFlyMode": "AUTO", 220 | "mixedRealityUnityLike": "true", 221 | "backpackSwitching": "true", 222 | "playerModelBodyScale": "1.0", 223 | "vrSettingsButtonEnabled": "true", 224 | "shaderGUIRender": "AFTER_SHADER", 225 | "displayMirrorLeftEye": "false", 226 | "selfButtSparklesInFirstPerson": "false", 227 | "vrEnabled": "false", 228 | "hitIndicator": "true", 229 | "walkUpBlocks": "true", 230 | "seatedFreeMove": "false", 231 | "updateType": "RELEASE", 232 | "showChatMessageStencil": "true" 233 | } -------------------------------------------------------------------------------- /src/main/java/com/oracle/dalvik/VMLauncher.java: -------------------------------------------------------------------------------- 1 | package com.oracle.dalvik; 2 | 3 | public final class VMLauncher { 4 | private VMLauncher() { 5 | } 6 | public static native int launchJVM(String[] args); 7 | 8 | static { 9 | System.loadLibrary("jrelauncher"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/dalvik/annotation/optimization/CriticalNative.java: -------------------------------------------------------------------------------- 1 | package dalvik.annotation.optimization; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | // Dummy CriticalNative annotation. On devices which dont have it this declaration will prevent errors. 8 | // On devices that do have it it will be overridden by the system one and work as usual 9 | @Retention(RetentionPolicy.CLASS) 10 | @Target(ElementType.METHOD) 11 | public @interface CriticalNative { 12 | } -------------------------------------------------------------------------------- /src/main/java/org/lwjgl/glfw/CallbackBridge.java: -------------------------------------------------------------------------------- 1 | package org.lwjgl.glfw; 2 | 3 | import android.app.Activity; 4 | import android.content.*; 5 | import android.view.Choreographer; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | import java.util.ArrayList; 10 | 11 | import dalvik.annotation.optimization.CriticalNative; 12 | import pojlib.UnityPlayerActivity; 13 | 14 | import pojlib.UnityPlayerActivity; 15 | import pojlib.input.GrabListener; 16 | import pojlib.input.LwjglGlfwKeycode; 17 | 18 | public class CallbackBridge { 19 | private static boolean isGrabbing = false; 20 | private static final ArrayList grabListeners = new ArrayList<>(); 21 | 22 | public static final int CLIPBOARD_COPY = 2000; 23 | public static final int CLIPBOARD_PASTE = 2001; 24 | public static final int CLIPBOARD_OPEN = 2002; 25 | 26 | public static volatile int windowWidth, windowHeight; 27 | public static volatile int physicalWidth, physicalHeight; 28 | public static float mouseX, mouseY; 29 | public volatile static boolean holdingAlt, holdingCapslock, holdingCtrl, 30 | holdingNumlock, holdingShift; 31 | 32 | public static void putMouseEventWithCoords(int button, float x, float y) { 33 | putMouseEventWithCoords(button, true, x, y); 34 | } 35 | 36 | public static void putMouseEventWithCoords(int button, boolean isDown, float x, float y /* , int dz, long nanos */) { 37 | sendCursorPos(x, y); 38 | sendMouseKeycode(button, CallbackBridge.getCurrentMods(), isDown); 39 | } 40 | 41 | 42 | public static void sendCursorPos(float x, float y) { 43 | mouseX = x; 44 | mouseY = y; 45 | nativeSendCursorPos(mouseX, mouseY); 46 | } 47 | 48 | public static void sendKeycode(int keycode, char keychar, int scancode, int modifiers, boolean isDown) { 49 | // TODO CHECK: This may cause input issue, not receive input! 50 | if(keycode != 0) nativeSendKey(keycode,scancode,isDown ? 1 : 0, modifiers); 51 | if(isDown && keychar != '\u0000') { 52 | nativeSendCharMods(keychar,modifiers); 53 | nativeSendChar(keychar); 54 | } 55 | } 56 | 57 | public static void sendChar(char keychar, int modifiers){ 58 | nativeSendCharMods(keychar,modifiers); 59 | nativeSendChar(keychar); 60 | } 61 | 62 | public static void sendKeyPress(int keyCode, int modifiers, boolean status) { 63 | sendKeyPress(keyCode, 0, modifiers, status); 64 | } 65 | 66 | public static void sendKeyPress(int keyCode, int scancode, int modifiers, boolean status) { 67 | sendKeyPress(keyCode, '\u0000', scancode, modifiers, status); 68 | } 69 | 70 | public static void sendKeyPress(int keyCode, char keyChar, int scancode, int modifiers, boolean status) { 71 | CallbackBridge.sendKeycode(keyCode, keyChar, scancode, modifiers, status); 72 | } 73 | 74 | public static void sendKeyPress(int keyCode) { 75 | sendKeyPress(keyCode, CallbackBridge.getCurrentMods(), true); 76 | sendKeyPress(keyCode, CallbackBridge.getCurrentMods(), false); 77 | } 78 | 79 | public static void sendMouseButton(int button, boolean status) { 80 | CallbackBridge.sendMouseKeycode(button, CallbackBridge.getCurrentMods(), status); 81 | } 82 | 83 | public static void sendMouseKeycode(int button, int modifiers, boolean isDown) { 84 | // if (isGrabbing()) DEBUG_STRING.append("MouseGrabStrace: " + android.util.Log.getStackTraceString(new Throwable()) + "\n"); 85 | nativeSendMouseButton(button, isDown ? 1 : 0, modifiers); 86 | } 87 | 88 | public static void sendMouseKeycode(int keycode) { 89 | sendMouseKeycode(keycode, CallbackBridge.getCurrentMods(), true); 90 | sendMouseKeycode(keycode, CallbackBridge.getCurrentMods(), false); 91 | } 92 | 93 | public static void sendScroll(double xoffset, double yoffset) { 94 | nativeSendScroll(xoffset, yoffset); 95 | } 96 | 97 | public static void sendUpdateWindowSize(int w, int h) { 98 | nativeSendScreenSize(w, h); 99 | } 100 | 101 | public static boolean isGrabbing() { 102 | // Avoid going through the JNI each time. 103 | return isGrabbing; 104 | } 105 | 106 | // Called from JRE side 107 | @SuppressWarnings("unused") 108 | public static @Nullable String accessAndroidClipboard(int type, String copy) { 109 | switch (type) { 110 | case CLIPBOARD_COPY: 111 | UnityPlayerActivity.GLOBAL_CLIPBOARD.setPrimaryClip(ClipData.newPlainText("Copy", copy)); 112 | return null; 113 | 114 | case CLIPBOARD_PASTE: 115 | if (UnityPlayerActivity.GLOBAL_CLIPBOARD.hasPrimaryClip() && UnityPlayerActivity.GLOBAL_CLIPBOARD.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) { 116 | return UnityPlayerActivity.GLOBAL_CLIPBOARD.getPrimaryClip().getItemAt(0).getText().toString(); 117 | } else { 118 | return ""; 119 | } 120 | 121 | default: return null; 122 | } 123 | } 124 | 125 | 126 | public static int getCurrentMods() { 127 | int currMods = 0; 128 | if (holdingAlt) { 129 | currMods |= LwjglGlfwKeycode.GLFW_MOD_ALT; 130 | } if (holdingCapslock) { 131 | currMods |= LwjglGlfwKeycode.GLFW_MOD_CAPS_LOCK; 132 | } if (holdingCtrl) { 133 | currMods |= LwjglGlfwKeycode.GLFW_MOD_CONTROL; 134 | } if (holdingNumlock) { 135 | currMods |= LwjglGlfwKeycode.GLFW_MOD_NUM_LOCK; 136 | } if (holdingShift) { 137 | currMods |= LwjglGlfwKeycode.GLFW_MOD_SHIFT; 138 | } 139 | return currMods; 140 | } 141 | 142 | public static void setModifiers(int keyCode, boolean isDown){ 143 | switch (keyCode){ 144 | case LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT: 145 | CallbackBridge.holdingShift = isDown; 146 | return; 147 | 148 | case LwjglGlfwKeycode.GLFW_KEY_LEFT_CONTROL: 149 | CallbackBridge.holdingCtrl = isDown; 150 | return; 151 | 152 | case LwjglGlfwKeycode.GLFW_KEY_LEFT_ALT: 153 | CallbackBridge.holdingAlt = isDown; 154 | return; 155 | 156 | case LwjglGlfwKeycode.GLFW_KEY_CAPS_LOCK: 157 | CallbackBridge.holdingCapslock = isDown; 158 | return; 159 | 160 | case LwjglGlfwKeycode.GLFW_KEY_NUM_LOCK: 161 | CallbackBridge.holdingNumlock = isDown; 162 | } 163 | } 164 | 165 | //Called from JRE side 166 | @SuppressWarnings("unused") 167 | private static void onGrabStateChanged(final boolean grabbing) { 168 | isGrabbing = grabbing; 169 | } 170 | 171 | public static void restartUnitySession(Activity activity) { 172 | UnityPlayerActivity unity = (UnityPlayerActivity) activity; 173 | unity.reinitUnity(); 174 | } 175 | 176 | public static void addGrabListener(GrabListener listener) { 177 | synchronized (grabListeners) { 178 | listener.onGrabState(isGrabbing); 179 | grabListeners.add(listener); 180 | } 181 | } 182 | public static void removeGrabListener(GrabListener listener) { 183 | synchronized (grabListeners) { 184 | grabListeners.remove(listener); 185 | } 186 | } 187 | 188 | @CriticalNative 189 | public static native void nativeSetUseInputStackQueue(boolean useInputStackQueue); 190 | 191 | @CriticalNative private static native boolean nativeSendChar(char codepoint); 192 | // GLFW: GLFWCharModsCallback deprecated, but is Minecraft still use? 193 | @CriticalNative private static native boolean nativeSendCharMods(char codepoint, int mods); 194 | @CriticalNative private static native void nativeSendKey(int key, int scancode, int action, int mods); 195 | // private static native void nativeSendCursorEnter(int entered); 196 | @CriticalNative private static native void nativeSendCursorPos(float x, float y); 197 | @CriticalNative private static native void nativeSendMouseButton(int button, int action, int mods); 198 | @CriticalNative private static native void nativeSendScroll(double xoffset, double yoffset); 199 | @CriticalNative private static native void nativeSendScreenSize(int width, int height); 200 | public static native void nativeSetWindowAttrib(int attrib, int value); 201 | static { 202 | System.loadLibrary("pojavexec"); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/main/java/pojlib/APIHandler.java: -------------------------------------------------------------------------------- 1 | package pojlib; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.gson.Gson; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.InputStreamReader; 12 | import java.io.OutputStream; 13 | import java.net.HttpURLConnection; 14 | import java.net.URL; 15 | import java.nio.charset.StandardCharsets; 16 | import java.util.HashMap; 17 | import java.util.stream.Collectors; 18 | 19 | import pojlib.util.Constants; 20 | import pojlib.util.download.DownloadManager; 21 | import pojlib.util.download.DownloadUtils; 22 | import pojlib.util.GsonUtils; 23 | import pojlib.util.Logger; 24 | 25 | public class APIHandler { 26 | public final String baseUrl; 27 | 28 | public APIHandler(String url) { 29 | baseUrl = url; 30 | } 31 | 32 | public T get(String endpoint, Class tClass) { 33 | return getFullUrl(baseUrl + "/" + endpoint, tClass); 34 | } 35 | 36 | public T get(String endpoint, HashMap query, Class tClass) { 37 | return getFullUrl(baseUrl + "/" + endpoint, query, tClass); 38 | } 39 | 40 | public T post(String endpoint, T body, Class tClass) { 41 | return postFullUrl(baseUrl + "/" + endpoint, body, tClass); 42 | } 43 | 44 | public T post(String endpoint, HashMap query, T body, Class tClass) { 45 | return postFullUrl(baseUrl + "/" + endpoint, query, body, tClass); 46 | } 47 | 48 | //Make a get request and return the response as a raw string; 49 | public static String getRaw(String url) { 50 | try { 51 | HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); 52 | InputStream inputStream = conn.getInputStream(); 53 | String data = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("\n")); 54 | inputStream.close(); 55 | conn.disconnect(); 56 | return data; 57 | } catch (IOException e) { 58 | e.printStackTrace(); 59 | } 60 | return null; 61 | } 62 | 63 | public static String postRaw(String url, String body) { 64 | try { 65 | HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); 66 | conn.setRequestMethod("POST"); 67 | conn.setRequestProperty("Content-Type", "application/json"); 68 | conn.setRequestProperty("Accept", "application/json"); 69 | conn.setDoOutput(true); 70 | 71 | OutputStream outputStream = conn.getOutputStream(); 72 | byte[] input = body.getBytes(StandardCharsets.UTF_8); 73 | outputStream.write(input, 0, input.length); 74 | outputStream.close(); 75 | 76 | InputStream inputStream = conn.getInputStream(); 77 | String data = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("\n")); 78 | inputStream.close(); 79 | 80 | conn.disconnect(); 81 | return data; 82 | } catch (IOException e) { 83 | e.printStackTrace(); 84 | } 85 | return null; 86 | } 87 | 88 | private static String parseQueries(HashMap query) { 89 | StringBuilder params = new StringBuilder("?"); 90 | for (String param : query.keySet()) { 91 | Object value = query.get(param); 92 | params.append(param).append("=").append(value).append("&"); 93 | } 94 | return params.substring(0, params.length() - 1); 95 | } 96 | 97 | public static T getFullUrl(String url, Class tClass) { 98 | return new Gson().fromJson(getRaw(url), tClass); 99 | } 100 | 101 | public static T getFullUrl(String url, HashMap query, Class tClass) { 102 | return getFullUrl(url + parseQueries(query), tClass); 103 | } 104 | 105 | public static T postFullUrl(String url, T body, Class tClass) { 106 | return new Gson().fromJson(postRaw(url, body.toString()), tClass); 107 | } 108 | 109 | public static T postFullUrl(String url, HashMap query, T body, Class tClass) { 110 | return new Gson().fromJson(postRaw(url + parseQueries(query), body.toString()), tClass); 111 | } 112 | 113 | public static final String SUPPORTED_VERSIONS = "https://raw.githubusercontent.com/QuestCraftPlusPlus/Pojlib/refs/heads/" + Constants.GIT_BRANCH + "/supportedVersions.json"; 114 | 115 | public static String[] getQCSupportedVersions(Context ctx) { 116 | File versionsJson = new File(Constants.USER_HOME + "/supportedVersions.json"); 117 | if(API.hasConnection(ctx)) { 118 | try { 119 | DownloadUtils.downloadFile(SUPPORTED_VERSIONS, versionsJson); 120 | } catch (IOException e) { 121 | Logger.getInstance().appendToLog("Error while grabbing supported versions!\n" + e); 122 | } 123 | } else { 124 | Logger.getInstance().appendToLog("Skipping supported versions download."); 125 | } 126 | 127 | DownloadManager.reset(); 128 | SupportedVersions versions = GsonUtils.jsonFileToObject(versionsJson.getAbsolutePath(), SupportedVersions.class); 129 | if(versions == null) { 130 | return new String[] { 131 | "1.21.4" 132 | }; 133 | } 134 | 135 | return versions.supportedVersions; 136 | } 137 | 138 | public static class SupportedVersions { 139 | public String[] supportedVersions; 140 | } 141 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/account/LoginHelper.java: -------------------------------------------------------------------------------- 1 | package pojlib.account; 2 | 3 | import android.app.Activity; 4 | import android.util.Log; 5 | 6 | import com.microsoft.aad.msal4j.DeviceCode; 7 | import com.microsoft.aad.msal4j.DeviceCodeFlowParameters; 8 | import com.microsoft.aad.msal4j.IAccount; 9 | import com.microsoft.aad.msal4j.IAuthenticationResult; 10 | import com.microsoft.aad.msal4j.PublicClientApplication; 11 | import com.microsoft.aad.msal4j.SilentParameters; 12 | 13 | import org.json.JSONException; 14 | 15 | import java.io.BufferedReader; 16 | import java.io.File; 17 | import java.io.FileReader; 18 | import java.io.IOException; 19 | import java.net.MalformedURLException; 20 | import java.util.ArrayList; 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | import java.util.concurrent.CompletableFuture; 24 | import java.util.concurrent.ExecutionException; 25 | import java.util.function.Consumer; 26 | 27 | import pojlib.API; 28 | import pojlib.util.Constants; 29 | import pojlib.util.GsonUtils; 30 | import pojlib.util.Logger; 31 | import pojlib.util.MSAException; 32 | 33 | public class LoginHelper { 34 | public static final Set SCOPES; 35 | private static Thread loginThread; 36 | private static PublicClientApplication pca; 37 | 38 | static { 39 | try { 40 | File cache = new File(Constants.USER_HOME + "/cache_data/serialized_cache.json"); 41 | if(!cache.exists()) { 42 | cache.getParentFile().mkdirs(); 43 | cache.createNewFile(); 44 | } 45 | 46 | // Loads cache from file 47 | BufferedReader reader = new BufferedReader(new FileReader(cache.getPath())); 48 | String dataToInitCache = reader.readLine(); 49 | reader.close(); 50 | 51 | TokenPersistence persistenceAspect = new TokenPersistence(dataToInitCache, cache); 52 | 53 | pca = PublicClientApplication.builder("d17a73a2-707c-40f5-8c90-d3eda0956f10") 54 | .setTokenCacheAccessAspect(persistenceAspect) 55 | .authority("https://login.microsoftonline.com/consumers/") 56 | .build(); 57 | } catch (IOException e) { 58 | throw new RuntimeException(e); 59 | } 60 | 61 | SCOPES = new HashSet<>(); 62 | SCOPES.add("XboxLive.SignIn"); 63 | SCOPES.add("XboxLive.offline_access"); 64 | } 65 | 66 | public static MinecraftAccount refreshAccount(Activity activity, String uuid) { 67 | Set accountsInCache = pca.getAccounts().join(); 68 | IAuthenticationResult result; 69 | try { 70 | for (IAccount account : accountsInCache) { 71 | SilentParameters silentParameters = 72 | SilentParameters 73 | .builder(SCOPES, account) 74 | .build(); 75 | 76 | result = pca.acquireTokenSilently(silentParameters).join(); 77 | MinecraftAccount acc = new Msa(activity).performLogin(result.accessToken()); 78 | GsonUtils.objectToJsonFile(activity.getFilesDir() + "/accounts/" + acc.uuid + ".json", acc); 79 | if (!acc.uuid.equals(uuid)) { 80 | // Refresh was for the wrong acc, try again 81 | continue; 82 | } 83 | return acc; 84 | } 85 | return null; 86 | } catch (Exception ex) { 87 | Logger.getInstance().appendToLog("Couldn't refresh token! " + ex); 88 | return null; 89 | } 90 | } 91 | 92 | public static void login(Activity activity) { 93 | loginThread = new Thread(() -> { 94 | Consumer deviceCodeConsumer = (DeviceCode deviceCode) -> API.msaMessage = deviceCode.message(); 95 | CompletableFuture future = pca.acquireToken( 96 | DeviceCodeFlowParameters.builder(SCOPES, deviceCodeConsumer).build()); 97 | 98 | try { 99 | IAuthenticationResult res = future.get(); 100 | while(res.account() == null) { 101 | Thread.sleep(20); 102 | } 103 | try { 104 | API.currentAcc = MinecraftAccount.login(activity, activity.getFilesDir() + "/accounts", res.accessToken()); 105 | } catch (IOException | JSONException | MSAException e) { 106 | Logger.getInstance().appendToLog("Unable to load account! | " + e); 107 | } 108 | API.profileImage = MinecraftAccount.getSkinFaceUrl(API.currentAcc); 109 | API.profileName = API.currentAcc.username; 110 | API.profileUUID = API.currentAcc.uuid; 111 | } catch (ExecutionException | InterruptedException e) { 112 | Logger.getInstance().appendToLog("MicrosoftLogin | Something went wrong! Couldn't reach the Microsoft Auth servers."); 113 | API.msaMessage = "MicrosoftLogin | Something went wrong! Couldn't reach the Microsoft Auth servers."; 114 | } 115 | }); 116 | 117 | loginThread.start(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/pojlib/account/MinecraftAccount.java: -------------------------------------------------------------------------------- 1 | package pojlib.account; 2 | 3 | import android.app.Activity; 4 | 5 | import com.google.gson.Gson; 6 | 7 | import org.json.JSONException; 8 | 9 | import java.io.File; 10 | import java.io.FileReader; 11 | import java.io.IOException; 12 | 13 | import javax.annotation.Nullable; 14 | 15 | import pojlib.util.Constants; 16 | import pojlib.util.GsonUtils; 17 | import pojlib.util.Logger; 18 | import pojlib.util.MSAException; 19 | 20 | public class MinecraftAccount { 21 | public String accessToken; 22 | public String uuid; 23 | public String username; 24 | public boolean isDemoMode = false; 25 | public long expiresOn; 26 | public final String userType = "msa"; 27 | 28 | public static MinecraftAccount login(Activity activity, String gameDir, String msToken) throws MSAException, IOException, JSONException { 29 | Msa instance = new Msa(activity); 30 | MinecraftAccount account = instance.performLogin(msToken); 31 | 32 | GsonUtils.objectToJsonFile(gameDir + "/" + account.uuid + ".json", account); 33 | return account; 34 | } 35 | 36 | public static boolean removeAccount(Activity activity, String uuid) { 37 | File accountFile = new File(activity.getFilesDir() + "/accounts/" + uuid + ".json"); 38 | File accountCache = new File(Constants.USER_HOME + "/cache_data"); 39 | 40 | return accountFile.delete() && accountCache.delete(); 41 | } 42 | 43 | //Try this before using login - the account will have been saved to disk if previously logged in 44 | public static MinecraftAccount load(String path, String uuid) { 45 | return GsonUtils.jsonFileToObject(path + "/" + uuid + ".json", MinecraftAccount.class); 46 | } 47 | 48 | public static String getSkinFaceUrl(MinecraftAccount account) { 49 | if (account.isDemoMode) { 50 | return Constants.MINOTAR_URL + "/helm/MHF_Steve"; 51 | } else { 52 | try { 53 | return Constants.MINOTAR_URL + "/helm/" + account.uuid; 54 | } catch (NullPointerException e) { 55 | Logger.getInstance().appendToLog("Username likely not set! Please set your username at Minecraft.net and try again. | " + e); 56 | return null; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/pojlib/account/TokenPersistence.java: -------------------------------------------------------------------------------- 1 | package pojlib.account; 2 | 3 | import com.microsoft.aad.msal4j.ITokenCacheAccessAspect; 4 | import com.microsoft.aad.msal4j.ITokenCacheAccessContext; 5 | 6 | import java.io.BufferedWriter; 7 | import java.io.File; 8 | import java.io.FileWriter; 9 | import java.io.IOException; 10 | 11 | public class TokenPersistence implements ITokenCacheAccessAspect { 12 | String data; 13 | File cache; 14 | 15 | TokenPersistence(String data, File cache) { 16 | this.data = data; 17 | this.cache = cache; 18 | } 19 | 20 | @Override 21 | public void beforeCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { 22 | iTokenCacheAccessContext.tokenCache().deserialize(data); 23 | } 24 | 25 | @Override 26 | public void afterCacheAccess(ITokenCacheAccessContext iTokenCacheAccessContext) { 27 | data = iTokenCacheAccessContext.tokenCache().serialize(); 28 | try { 29 | BufferedWriter writer = new BufferedWriter(new FileWriter(cache)); 30 | writer.write(data); 31 | writer.flush(); 32 | writer.close(); 33 | } catch (IOException e) { 34 | throw new RuntimeException(e); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/input/AWTInputBridge.java: -------------------------------------------------------------------------------- 1 | package pojlib.input; 2 | 3 | public class AWTInputBridge { 4 | public static final int EVENT_TYPE_CHAR = 1000; 5 | public static final int EVENT_TYPE_CURSOR_POS = 1003; 6 | public static final int EVENT_TYPE_KEY = 1005; 7 | public static final int EVENT_TYPE_MOUSE_BUTTON = 1006; 8 | 9 | public static void sendKey(char keychar, int keycode) { 10 | // TODO: Android -> AWT keycode mapping 11 | nativeSendData(EVENT_TYPE_KEY, (int) keychar, keycode, 1, 0); 12 | nativeSendData(EVENT_TYPE_KEY, (int) keychar, keycode, 0, 0); 13 | } 14 | 15 | public static void sendKey(char keychar, int keycode, int state) { 16 | // TODO: Android -> AWT keycode mapping 17 | nativeSendData(EVENT_TYPE_KEY, (int) keychar, keycode, state, 0); 18 | } 19 | 20 | public static void sendChar(char keychar){ 21 | nativeSendData(EVENT_TYPE_CHAR, (int) keychar, 0, 0, 0); 22 | } 23 | 24 | public static void sendMousePress(int awtButtons, boolean isDown) { 25 | nativeSendData(EVENT_TYPE_MOUSE_BUTTON, awtButtons, isDown ? 1 : 0, 0, 0); 26 | } 27 | 28 | public static void sendMousePress(int awtButtons) { 29 | sendMousePress(awtButtons, true); 30 | sendMousePress(awtButtons, false); 31 | } 32 | 33 | public static void sendMousePos(int x, int y) { 34 | nativeSendData(EVENT_TYPE_CURSOR_POS, x, y, 0, 0); 35 | } 36 | 37 | static { 38 | System.loadLibrary("pojavexec_awt"); 39 | } 40 | 41 | public static native void nativeSendData(int type, int i1, int i2, int i3, int i4); 42 | public static native void nativeClipboardReceived(String data, String mimeTypeSub); 43 | public static native void nativeMoveWindow(int xoff, int yoff); 44 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/input/CriticalNativeTest.java: -------------------------------------------------------------------------------- 1 | package pojlib.input; 2 | 3 | import dalvik.annotation.optimization.CriticalNative; 4 | 5 | public class CriticalNativeTest { 6 | @CriticalNative 7 | public static native void testCriticalNative(int arg0, int arg1); 8 | public static void invokeTest() { 9 | testCriticalNative(0, 0); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/pojlib/input/GrabListener.java: -------------------------------------------------------------------------------- 1 | package pojlib.input; 2 | 3 | public interface GrabListener { 4 | void onGrabState(boolean isGrabbing); 5 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/DefaultDataProvider.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | import pojlib.input.GrabListener; 4 | 5 | import org.lwjgl.glfw.CallbackBridge; 6 | 7 | public class DefaultDataProvider implements GamepadDataProvider { 8 | public static final DefaultDataProvider INSTANCE = new DefaultDataProvider(); 9 | 10 | // Cannot instantiate this class publicly 11 | private DefaultDataProvider() {} 12 | 13 | @Override 14 | public GamepadMap getGameMap() { 15 | return GamepadMapStore.getGameMap(); 16 | } 17 | 18 | 19 | @Override 20 | public GamepadMap getMenuMap() { 21 | return GamepadMapStore.getMenuMap(); 22 | } 23 | 24 | @Override 25 | public boolean isGrabbing() { 26 | return CallbackBridge.isGrabbing(); 27 | } 28 | 29 | @Override 30 | public void attachGrabListener(GrabListener grabListener) { 31 | CallbackBridge.addGrabListener(grabListener); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/GamepadButton.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | /** 4 | * This class corresponds to a button that does exist on the gamepad 5 | */ 6 | public class GamepadButton extends GamepadEmulatedButton { 7 | public boolean isToggleable = false; 8 | private boolean mIsToggled = false; 9 | 10 | 11 | @Override 12 | protected void onDownStateChanged(boolean isDown) { 13 | if(isToggleable && isDown){ 14 | mIsToggled = !mIsToggled; 15 | Gamepad.sendInput(keycodes, mIsToggled); 16 | return; 17 | } 18 | super.onDownStateChanged(isDown); 19 | } 20 | 21 | @Override 22 | public void resetButtonState() { 23 | if(!mIsDown && mIsToggled) { 24 | Gamepad.sendInput(keycodes, false); 25 | mIsToggled = false; 26 | } else { 27 | super.resetButtonState(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/GamepadDataProvider.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | import pojlib.input.GrabListener; 4 | 5 | public interface GamepadDataProvider { 6 | GamepadMap getMenuMap(); 7 | GamepadMap getGameMap(); 8 | boolean isGrabbing(); 9 | void attachGrabListener(GrabListener grabListener); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/GamepadDpad.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | import static android.view.InputDevice.KEYBOARD_TYPE_ALPHABETIC; 4 | import static android.view.InputDevice.SOURCE_GAMEPAD; 5 | import static android.view.KeyEvent.KEYCODE_DPAD_CENTER; 6 | import static android.view.KeyEvent.KEYCODE_DPAD_DOWN; 7 | import static android.view.KeyEvent.KEYCODE_DPAD_LEFT; 8 | import static android.view.KeyEvent.KEYCODE_DPAD_RIGHT; 9 | import static android.view.KeyEvent.KEYCODE_DPAD_UP; 10 | 11 | import android.view.InputDevice; 12 | import android.view.KeyEvent; 13 | import android.view.MotionEvent; 14 | 15 | 16 | public class GamepadDpad { 17 | private int mLastKeycode = KEYCODE_DPAD_CENTER; 18 | 19 | /** 20 | * Convert the event to a 2 int array: keycode and keyAction, similar to a keyEvent 21 | * @param event The motion to convert 22 | * @return int[0] keycode, int[1] keyAction 23 | */ 24 | public int[] convertEvent(MotionEvent event){ 25 | // Use the hat axis value to find the D-pad direction 26 | float xaxis = event.getAxisValue(MotionEvent.AXIS_HAT_X); 27 | float yaxis = event.getAxisValue(MotionEvent.AXIS_HAT_Y); 28 | int action = KeyEvent.ACTION_DOWN; 29 | 30 | // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad 31 | // LEFT and RIGHT direction accordingly. 32 | if (Float.compare(xaxis, -1.0f) == 0) { 33 | mLastKeycode = KEYCODE_DPAD_LEFT; 34 | } else if (Float.compare(xaxis, 1.0f) == 0) { 35 | mLastKeycode = KEYCODE_DPAD_RIGHT; 36 | } 37 | // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad 38 | // UP and DOWN direction accordingly. 39 | else if (Float.compare(yaxis, -1.0f) == 0) { 40 | mLastKeycode = KEYCODE_DPAD_UP; 41 | } else if (Float.compare(yaxis, 1.0f) == 0) { 42 | mLastKeycode = KEYCODE_DPAD_DOWN; 43 | }else { 44 | //No keycode change 45 | action = KeyEvent.ACTION_UP; 46 | } 47 | 48 | return new int[]{mLastKeycode, action}; 49 | 50 | } 51 | 52 | @SuppressWarnings("unused") public static boolean isDpadEvent(MotionEvent event) { 53 | // Check that input comes from a device with directional pads. 54 | // And... also the joystick since it declares sometimes as a joystick. 55 | return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK; 56 | } 57 | 58 | public static boolean isDpadEvent(KeyEvent event){ 59 | //return ((event.getSource() & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) && (event.getDevice().getKeyboardType() == KEYBOARD_TYPE_NON_ALPHABETIC); 60 | return event.isFromSource(SOURCE_GAMEPAD) && event.getDevice().getKeyboardType() != KEYBOARD_TYPE_ALPHABETIC; 61 | } 62 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/GamepadEmulatedButton.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | import android.view.KeyEvent; 4 | 5 | /** 6 | * This class corresponds to a button that does not physically exist on the gamepad, but is 7 | * emulated from other inputs on it (like WASD directional keys) 8 | */ 9 | public class GamepadEmulatedButton { 10 | public short[] keycodes; 11 | protected boolean mIsDown = false; 12 | 13 | public void update(KeyEvent event) { 14 | boolean isKeyDown = (event.getAction() == KeyEvent.ACTION_DOWN); 15 | update(isKeyDown); 16 | } 17 | 18 | public void update(boolean isKeyDown){ 19 | if(isKeyDown != mIsDown){ 20 | mIsDown = isKeyDown; 21 | onDownStateChanged(mIsDown); 22 | } 23 | } 24 | 25 | public void resetButtonState() { 26 | if(mIsDown) Gamepad.sendInput(keycodes, false); 27 | mIsDown = false; 28 | } 29 | 30 | protected void onDownStateChanged(boolean isDown) { 31 | Gamepad.sendInput(keycodes, mIsDown); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/GamepadJoystick.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | import android.view.InputDevice; 4 | import android.view.MotionEvent; 5 | 6 | import pojlib.util.MathUtils; 7 | 8 | public class GamepadJoystick { 9 | 10 | //Directions 11 | public static final int DIRECTION_NONE = -1; //GamepadJoystick at the center 12 | 13 | public static final int DIRECTION_EAST = 0; 14 | public static final int DIRECTION_NORTH_EAST = 1; 15 | public static final int DIRECTION_NORTH = 2; 16 | public static final int DIRECTION_NORTH_WEST = 3; 17 | public static final int DIRECTION_WEST = 4; 18 | public static final int DIRECTION_SOUTH_WEST = 5; 19 | public static final int DIRECTION_SOUTH = 6; 20 | public static final int DIRECTION_SOUTH_EAST = 7; 21 | 22 | private final InputDevice mInputDevice; 23 | 24 | private final int mHorizontalAxis; 25 | private final int mVerticalAxis; 26 | private float mVerticalAxisValue = 0; 27 | private float mHorizontalAxisValue = 0; 28 | 29 | public GamepadJoystick(int horizontalAxis, int verticalAxis, InputDevice device){ 30 | mHorizontalAxis = horizontalAxis; 31 | mVerticalAxis = verticalAxis; 32 | this.mInputDevice = device; 33 | } 34 | 35 | public double getAngleRadian(){ 36 | //From -PI to PI 37 | // TODO misuse of the deadzone here ! 38 | return -Math.atan2(getVerticalAxis(), getHorizontalAxis()); 39 | } 40 | 41 | 42 | public double getAngleDegree(){ 43 | //From 0 to 360 degrees 44 | double result = Math.toDegrees(getAngleRadian()); 45 | if(result < 0) result += 360; 46 | 47 | return result; 48 | } 49 | 50 | public double getMagnitude(){ 51 | float x = Math.abs(mHorizontalAxisValue); 52 | float y = Math.abs(mVerticalAxisValue); 53 | 54 | return MathUtils.dist(0,0, x, y); 55 | } 56 | 57 | public float getVerticalAxis(){ 58 | return mVerticalAxisValue; 59 | } 60 | 61 | public float getHorizontalAxis(){ 62 | return mHorizontalAxisValue; 63 | } 64 | 65 | public static boolean isJoystickEvent(MotionEvent event){ 66 | return (event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK 67 | && event.getAction() == MotionEvent.ACTION_MOVE; 68 | } 69 | 70 | 71 | public int getHeightDirection(){ 72 | if(getMagnitude() == 0) return DIRECTION_NONE; 73 | return ((int) ((getAngleDegree()+22.5)/45)) % 8; 74 | } 75 | 76 | 77 | /* Setters */ 78 | public void setXAxisValue(float value){ 79 | this.mHorizontalAxisValue = value; 80 | } 81 | 82 | public void setYAxisValue(float value){ 83 | this.mVerticalAxisValue = value; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/GamepadMap.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | import pojlib.input.LwjglGlfwKeycode; 4 | 5 | public class GamepadMap { 6 | 7 | 8 | public static final short MOUSE_SCROLL_DOWN = -1; 9 | public static final short MOUSE_SCROLL_UP = -2; 10 | // Made mouse keycodes their own specials because managing special keycodes above 0 11 | // proved to be complicated 12 | public static final short MOUSE_LEFT = -3; 13 | public static final short MOUSE_MIDDLE = -4; 14 | public static final short MOUSE_RIGHT = -5; 15 | // Workaround, because GLFW_KEY_UNKNOWN and GLFW_MOUSE_BUTTON_LEFT are both 0 16 | public static final short UNSPECIFIED = -6; 17 | 18 | /* 19 | This class is just here to store the mapping 20 | can be modified to create re-mappable controls I guess 21 | 22 | Be warned, you should define ALL keys if you want to avoid a non defined exception 23 | */ 24 | 25 | public GamepadButton BUTTON_A, BUTTON_B, BUTTON_X, BUTTON_Y, BUTTON_START, BUTTON_SELECT, 26 | TRIGGER_RIGHT, TRIGGER_LEFT, SHOULDER_RIGHT, SHOULDER_LEFT, THUMBSTICK_RIGHT, 27 | THUMBSTICK_LEFT, DPAD_UP, DPAD_DOWN, DPAD_RIGHT, DPAD_LEFT; 28 | 29 | public GamepadEmulatedButton DIRECTION_FORWARD, DIRECTION_BACKWARD, DIRECTION_RIGHT, DIRECTION_LEFT; 30 | 31 | /* 32 | * Sets all buttons to a not pressed state, sending an input if needed 33 | */ 34 | public void resetPressedState(){ 35 | BUTTON_A.resetButtonState(); 36 | BUTTON_B.resetButtonState(); 37 | BUTTON_X.resetButtonState(); 38 | BUTTON_Y.resetButtonState(); 39 | 40 | BUTTON_START.resetButtonState(); 41 | BUTTON_SELECT.resetButtonState(); 42 | 43 | TRIGGER_LEFT.resetButtonState(); 44 | TRIGGER_RIGHT.resetButtonState(); 45 | 46 | SHOULDER_LEFT.resetButtonState(); 47 | SHOULDER_RIGHT.resetButtonState(); 48 | 49 | THUMBSTICK_LEFT.resetButtonState(); 50 | THUMBSTICK_RIGHT.resetButtonState(); 51 | 52 | DPAD_UP.resetButtonState(); 53 | DPAD_RIGHT.resetButtonState(); 54 | DPAD_DOWN.resetButtonState(); 55 | DPAD_LEFT.resetButtonState(); 56 | 57 | } 58 | 59 | private static GamepadMap createAndInitializeButtons() { 60 | GamepadMap gamepadMap = new GamepadMap(); 61 | gamepadMap.BUTTON_A = new GamepadButton(); 62 | gamepadMap.BUTTON_B = new GamepadButton(); 63 | gamepadMap.BUTTON_X = new GamepadButton(); 64 | gamepadMap.BUTTON_Y = new GamepadButton(); 65 | 66 | gamepadMap.BUTTON_START = new GamepadButton(); 67 | gamepadMap.BUTTON_SELECT = new GamepadButton(); 68 | 69 | gamepadMap.TRIGGER_RIGHT = new GamepadButton(); 70 | gamepadMap.TRIGGER_LEFT = new GamepadButton(); 71 | 72 | gamepadMap.SHOULDER_RIGHT = new GamepadButton(); 73 | gamepadMap.SHOULDER_LEFT = new GamepadButton(); 74 | 75 | gamepadMap.DIRECTION_FORWARD = new GamepadEmulatedButton(); 76 | gamepadMap.DIRECTION_BACKWARD = new GamepadEmulatedButton(); 77 | gamepadMap.DIRECTION_RIGHT = new GamepadEmulatedButton(); 78 | gamepadMap.DIRECTION_LEFT = new GamepadEmulatedButton(); 79 | 80 | gamepadMap.THUMBSTICK_RIGHT = new GamepadButton(); 81 | gamepadMap.THUMBSTICK_LEFT = new GamepadButton(); 82 | 83 | gamepadMap.DPAD_UP = new GamepadButton(); 84 | gamepadMap.DPAD_RIGHT = new GamepadButton(); 85 | gamepadMap.DPAD_DOWN = new GamepadButton(); 86 | gamepadMap.DPAD_LEFT = new GamepadButton(); 87 | return gamepadMap; 88 | } 89 | 90 | /* 91 | * Returns a pre-done mapping used when the mouse is grabbed by the game. 92 | */ 93 | public static GamepadMap getDefaultGameMap(){ 94 | GamepadMap gameMap = GamepadMap.createEmptyMap(); 95 | 96 | gameMap.BUTTON_A.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_SPACE; 97 | gameMap.BUTTON_B.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_Q; 98 | gameMap.BUTTON_X.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_E; 99 | gameMap.BUTTON_Y.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_F; 100 | 101 | gameMap.DIRECTION_FORWARD.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_W; 102 | gameMap.DIRECTION_BACKWARD.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_S; 103 | gameMap.DIRECTION_RIGHT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_D; 104 | gameMap.DIRECTION_LEFT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_A; 105 | 106 | gameMap.DPAD_UP.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT; 107 | gameMap.DPAD_DOWN.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_O; //For mods ? 108 | gameMap.DPAD_RIGHT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_K; //For mods ? 109 | gameMap.DPAD_LEFT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_J; //For mods ? 110 | 111 | gameMap.SHOULDER_LEFT.keycodes[0] = GamepadMap.MOUSE_SCROLL_UP; 112 | gameMap.SHOULDER_RIGHT.keycodes[0] = GamepadMap.MOUSE_SCROLL_DOWN; 113 | 114 | gameMap.TRIGGER_LEFT.keycodes[0] = GamepadMap.MOUSE_RIGHT; 115 | gameMap.TRIGGER_RIGHT.keycodes[0] = GamepadMap.MOUSE_LEFT; 116 | 117 | gameMap.THUMBSTICK_LEFT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_LEFT_CONTROL; 118 | gameMap.THUMBSTICK_RIGHT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT; 119 | gameMap.THUMBSTICK_RIGHT.isToggleable = true; 120 | 121 | gameMap.BUTTON_START.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_ESCAPE; 122 | gameMap.BUTTON_SELECT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_TAB; 123 | 124 | return gameMap; 125 | } 126 | 127 | /* 128 | * Returns a pre-done mapping used when the mouse is NOT grabbed by the game. 129 | */ 130 | public static GamepadMap getDefaultMenuMap(){ 131 | GamepadMap menuMap = GamepadMap.createEmptyMap(); 132 | 133 | menuMap.BUTTON_A.keycodes[0] = GamepadMap.MOUSE_LEFT; 134 | menuMap.BUTTON_B.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_ESCAPE; 135 | menuMap.BUTTON_X.keycodes[0] = GamepadMap.MOUSE_RIGHT; 136 | { 137 | short[] keycodes = menuMap.BUTTON_Y.keycodes; 138 | keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_LEFT_SHIFT; 139 | keycodes[1] = GamepadMap.MOUSE_RIGHT; 140 | } 141 | 142 | { 143 | short[] keycodes = menuMap.DIRECTION_FORWARD.keycodes; 144 | keycodes[0] = keycodes[1] = keycodes[2] = keycodes[3] = GamepadMap.MOUSE_SCROLL_UP; 145 | } 146 | { 147 | short[] keycodes = menuMap.DIRECTION_BACKWARD.keycodes; 148 | keycodes[0] = keycodes[1] = keycodes[2] = keycodes[3] = GamepadMap.MOUSE_SCROLL_DOWN; 149 | } 150 | 151 | menuMap.DPAD_UP.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_TAB; // QC Funnies 152 | menuMap.DPAD_DOWN.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_ENTER; //For mods ? 153 | menuMap.DPAD_RIGHT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_K; //For mods ? 154 | menuMap.DPAD_LEFT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_J; //For mods ? 155 | 156 | menuMap.SHOULDER_LEFT.keycodes[0] = GamepadMap.MOUSE_SCROLL_UP; 157 | menuMap.SHOULDER_RIGHT.keycodes[0] = GamepadMap.MOUSE_SCROLL_DOWN; 158 | 159 | menuMap.BUTTON_SELECT.keycodes[0] = LwjglGlfwKeycode.GLFW_KEY_ESCAPE; 160 | 161 | return menuMap; 162 | } 163 | 164 | /* 165 | * Returns all GamepadEmulatedButtons of the controller key map. 166 | */ 167 | public GamepadEmulatedButton[] getButtons(){ 168 | return new GamepadEmulatedButton[]{ BUTTON_A, BUTTON_B, BUTTON_X, BUTTON_Y, 169 | BUTTON_SELECT, BUTTON_START, 170 | TRIGGER_LEFT, TRIGGER_RIGHT, 171 | SHOULDER_LEFT, SHOULDER_RIGHT, 172 | THUMBSTICK_LEFT, THUMBSTICK_RIGHT, 173 | DPAD_UP, DPAD_RIGHT, DPAD_DOWN, DPAD_LEFT, 174 | DIRECTION_FORWARD, DIRECTION_BACKWARD, 175 | DIRECTION_LEFT, DIRECTION_RIGHT}; 176 | } 177 | 178 | /* 179 | * Returns an pre-initialized GamepadMap with only empty keycodes 180 | */ 181 | @SuppressWarnings("unused") public static GamepadMap createEmptyMap(){ 182 | GamepadMap emptyMap = createAndInitializeButtons(); 183 | for(GamepadEmulatedButton button : emptyMap.getButtons()) 184 | button.keycodes = new short[] {UNSPECIFIED, UNSPECIFIED, UNSPECIFIED, UNSPECIFIED}; 185 | return emptyMap; 186 | } 187 | 188 | public static String[] getSpecialKeycodeNames() { 189 | return new String[] {"UNSPECIFIED", "MOUSE_RIGHT", "MOUSE_MIDDLE", "MOUSE_LEFT", "SCROLL_UP", "SCROLL_DOWN"}; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/main/java/pojlib/input/gamepad/GamepadMapStore.java: -------------------------------------------------------------------------------- 1 | package pojlib.input.gamepad; 2 | 3 | import android.util.Log; 4 | 5 | import com.google.gson.JsonParseException; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | 10 | import pojlib.util.Constants; 11 | import pojlib.util.FileUtil; 12 | import pojlib.util.GsonUtils; 13 | 14 | public class GamepadMapStore { 15 | private static final File STORE_FILE = new File(Constants.USER_HOME, "gamepad_map.json"); 16 | private static GamepadMapStore sMapStore; 17 | private GamepadMap mInMenuMap; 18 | private GamepadMap mInGameMap; 19 | private static GamepadMapStore createDefault() { 20 | GamepadMapStore mapStore = new GamepadMapStore(); 21 | mapStore.mInGameMap = GamepadMap.getDefaultGameMap(); 22 | mapStore.mInMenuMap = GamepadMap.getDefaultMenuMap(); 23 | return mapStore; 24 | } 25 | 26 | private static void loadIfNecessary() { 27 | if(sMapStore == null) return; 28 | load(); 29 | } 30 | 31 | public static void load() { 32 | GamepadMapStore mapStore = null; 33 | if(STORE_FILE.exists() && STORE_FILE.canRead()) { 34 | try { 35 | String storeFileContent = FileUtil.read(STORE_FILE.getPath()); 36 | mapStore = GsonUtils.GLOBAL_GSON.fromJson(storeFileContent, GamepadMapStore.class); 37 | } catch (JsonParseException | IOException e) { 38 | Log.w("GamepadMapStore", "Map store failed to load!", e); 39 | } 40 | } 41 | if(mapStore == null) mapStore = createDefault(); 42 | sMapStore = mapStore; 43 | } 44 | 45 | public static void save() throws IOException { 46 | if(sMapStore == null) throw new RuntimeException("Must load map store first!"); 47 | FileUtil.ensureParentDirectory(STORE_FILE); 48 | String jsonData = GsonUtils.GLOBAL_GSON.toJson(sMapStore); 49 | FileUtil.write(STORE_FILE.getAbsolutePath(), jsonData.getBytes()); 50 | } 51 | 52 | public static GamepadMap getGameMap() { 53 | loadIfNecessary(); 54 | return sMapStore.mInGameMap; 55 | } 56 | 57 | public static GamepadMap getMenuMap() { 58 | loadIfNecessary(); 59 | return sMapStore.mInMenuMap; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/pojlib/install/FabricMeta.java: -------------------------------------------------------------------------------- 1 | package pojlib.install; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import pojlib.APIHandler; 5 | import pojlib.util.Constants; 6 | import pojlib.util.Version; 7 | 8 | public class FabricMeta { 9 | 10 | private static final APIHandler handler = new APIHandler(Constants.FABRIC_META_URL); 11 | 12 | public static class FabricVersion { 13 | @SerializedName("version") 14 | public String version; 15 | @SerializedName("stable") 16 | public boolean stable; 17 | @SerializedName("separator") 18 | public String separator; 19 | } 20 | 21 | public static FabricVersion[] getVersions() { 22 | return handler.get("versions/loader", FabricVersion[].class); 23 | } 24 | 25 | private static Version getVersionFromFabric(FabricVersion fabric) { 26 | if(fabric.separator.contains("+")) { 27 | // Only used pre-0.11, no use for us 28 | return null; 29 | } 30 | 31 | String[] verName = fabric.version.split("\\."); 32 | if(verName.length < 3) { 33 | return null; 34 | } 35 | int major = Integer.parseInt(verName[0]); 36 | int minor = Integer.parseInt(verName[1]); 37 | int patch = Integer.parseInt(verName[2]); 38 | 39 | return new Version(major, minor, patch); 40 | } 41 | 42 | public static FabricVersion getLatestVersion() { 43 | FabricVersion latest = null; 44 | for (FabricVersion version : getVersions()) { 45 | if(latest == null) { 46 | latest = version; 47 | continue; 48 | } 49 | 50 | Version newVer = getVersionFromFabric(version); 51 | Version latestVer = getVersionFromFabric(latest); 52 | 53 | if(newVer == null || latestVer == null) 54 | continue; 55 | 56 | if(latestVer.major < newVer.major) { 57 | latest = version; 58 | } else if(latestVer.major == newVer.major && latestVer.minor < newVer.major) { 59 | latest = version; 60 | } else if(latestVer.major == newVer.major && latestVer.minor == newVer.major && latestVer.patch < newVer.patch) { 61 | latest = version; 62 | } 63 | } 64 | return latest; 65 | } 66 | 67 | public static VersionInfo getVersionInfo(FabricVersion fabricVersion, String minecraftVersion) { 68 | return handler.get(String.format("versions/loader/%s/%s/profile/json", minecraftVersion, fabricVersion.version), VersionInfo.class); 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/install/MinecraftMeta.java: -------------------------------------------------------------------------------- 1 | package pojlib.install; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import pojlib.APIHandler; 5 | import pojlib.util.Constants; 6 | 7 | public class MinecraftMeta { 8 | 9 | private static final APIHandler handler = new APIHandler(Constants.MOJANG_META_URL); 10 | 11 | public static class MinecraftVersions { 12 | @SerializedName("versions") 13 | public MinecraftVersion[] versions; 14 | } 15 | 16 | public static class MinecraftVersion { 17 | @SerializedName("id") 18 | public String id; 19 | @SerializedName("sha1") 20 | public String sha1; 21 | } 22 | 23 | public static MinecraftVersion[] getVersions() { 24 | return handler.get("mc/game/version_manifest_v2.json", MinecraftVersions.class).versions; 25 | } 26 | 27 | public static VersionInfo getVersionInfo(String versionName) { 28 | for (MinecraftVersion minecraftVersion : getVersions()) { 29 | if (minecraftVersion.id.equals(versionName)) { 30 | return handler.get(String.format("v1/packages/%s/%s.json", minecraftVersion.sha1, minecraftVersion.id), VersionInfo.class); 31 | } 32 | } 33 | return null; 34 | } 35 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/install/QuiltMeta.java: -------------------------------------------------------------------------------- 1 | package pojlib.install; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import pojlib.APIHandler; 5 | import pojlib.util.Constants; 6 | 7 | public class QuiltMeta { 8 | 9 | private static final APIHandler handler = new APIHandler(Constants.QUILT_META_URL); 10 | 11 | public static class QuiltVersion { 12 | @SerializedName("version") 13 | public String version; 14 | } 15 | 16 | public static QuiltVersion[] getVersions() { 17 | return handler.get("versions/loader", QuiltVersion[].class); 18 | } 19 | 20 | public static QuiltVersion getLatestVersion() { 21 | QuiltVersion[] versions = getVersions(); 22 | if (versions != null) return versions[0]; 23 | return null; 24 | } 25 | 26 | public static VersionInfo getVersionInfo(QuiltVersion quiltVersion, String minecraftVersion) { 27 | return handler.get(String.format("versions/loader/%s/%s/profile/json", minecraftVersion, quiltVersion.version), VersionInfo.class); 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/install/VersionInfo.java: -------------------------------------------------------------------------------- 1 | package pojlib.install; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class VersionInfo { 6 | @SerializedName("id") 7 | public String id; 8 | @SerializedName("type") 9 | public String type; 10 | @SerializedName("assetIndex") 11 | public AssetIndex assetIndex; 12 | @SerializedName("downloads") 13 | public Downloads downloads; 14 | @SerializedName("libraries") 15 | public Library[] libraries; 16 | @SerializedName("mainClass") 17 | public String mainClass; 18 | @SerializedName("arguments") 19 | public Arguments arguments; 20 | @SerializedName("assets") 21 | public String assets; 22 | 23 | public static class AssetIndex { 24 | @SerializedName("id") 25 | public String id; 26 | @SerializedName("totalSize") 27 | public int totalSize; 28 | @SerializedName("url") 29 | public String url; 30 | } 31 | 32 | public static class Downloads { 33 | @SerializedName("client") 34 | public Client client; 35 | 36 | public static class Client { 37 | @SerializedName("sha1") 38 | public String sha1; 39 | @SerializedName("url") 40 | public String url; 41 | } 42 | } 43 | 44 | public static class Arguments { 45 | @SerializedName("game") 46 | public Object[] game; 47 | @SerializedName("jvm") 48 | public Object[] jvm; 49 | 50 | public static class ArgValue { 51 | @SerializedName("rules") 52 | public ArgRules[] rules; 53 | @SerializedName("value") 54 | public String value; 55 | 56 | public static class ArgRules { 57 | @SerializedName("action") 58 | public String action; 59 | @SerializedName("features") 60 | public String features; 61 | @SerializedName("os") 62 | public ArgOS os; 63 | 64 | public static class ArgOS { 65 | @SerializedName("name") 66 | public String name; 67 | @SerializedName("version") 68 | public String version; 69 | } 70 | } 71 | } 72 | } 73 | 74 | public static class Library { 75 | @SerializedName("downloads") 76 | public Downloads downloads; 77 | @SerializedName("name") 78 | public String name; 79 | @SerializedName("url") 80 | public String url; 81 | 82 | public static class Downloads { 83 | @SerializedName("artifact") 84 | public Artifact artifact; 85 | } 86 | 87 | public static class Artifact { 88 | @SerializedName("path") 89 | public String path; 90 | @SerializedName("sha1") 91 | public String sha1; 92 | @SerializedName("size") 93 | public int size; 94 | @SerializedName("url") 95 | public String url; 96 | } 97 | } 98 | 99 | public static class Asset { 100 | @SerializedName("hash") 101 | public String hash; 102 | @SerializedName("size") 103 | public int size; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/Constants.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | import android.app.Activity; 4 | 5 | public class Constants { 6 | 7 | public static final String MOJANG_META_URL = "https://piston-meta.mojang.com"; 8 | 9 | public static final String MOJANG_RESOURCES_URL = "https://resources.download.minecraft.net"; 10 | 11 | public static final String FABRIC_META_URL = "https://meta.fabricmc.net/v2"; 12 | 13 | public static final String QUILT_META_URL = "https://meta.quiltmc.org/v3"; 14 | 15 | public static final String OAUTH_TOKEN_URL = "https://login.live.com/oauth20_token.srf"; 16 | 17 | public static final String XBL_AUTH_URL = "https://user.auth.xboxlive.com/user/authenticate"; 18 | 19 | public static final String XSTS_AUTH_URL = "https://xsts.auth.xboxlive.com/xsts/authorize"; 20 | 21 | public static final String MC_LOGIN_URL = "https://api.minecraftservices.com/authentication/login_with_xbox"; 22 | 23 | public static final String MC_STORE_URL = "https://api.minecraftservices.com/entitlements/mcstore"; 24 | 25 | public static final String MC_PROFILE_URL = "https://api.minecraftservices.com/minecraft/profile"; 26 | 27 | public static final String MINOTAR_URL = "https://minotar.net"; 28 | public static final String GIT_BRANCH = "QuestCraft-6.0.0"; 29 | public static String USER_HOME; 30 | 31 | public static void initConstants(Activity activity) { 32 | USER_HOME = activity.getExternalFilesDir(null).getAbsolutePath(); 33 | } 34 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import org.apache.commons.io.FileUtils; 7 | 8 | import java.io.*; 9 | import java.nio.file.Files; 10 | import java.nio.file.Paths; 11 | import java.util.Enumeration; 12 | import java.util.Objects; 13 | import java.util.zip.ZipEntry; 14 | import java.util.zip.ZipFile; 15 | import java.util.zip.ZipInputStream; 16 | 17 | public class FileUtil { 18 | 19 | public static String DIR_GAME_NEW; 20 | public static String DIR_HOME_VERSION; 21 | 22 | 23 | public static byte[] loadFromAssetToByte(Context ctx, String inFile) { 24 | byte[] buffer = null; 25 | 26 | try { 27 | InputStream stream = ctx.getAssets().open(inFile); 28 | 29 | int size = stream.available(); 30 | buffer = new byte[size]; 31 | stream.read(buffer); 32 | stream.close(); 33 | } catch (IOException e) { 34 | // Handle exceptions here 35 | e.printStackTrace(); 36 | } 37 | return buffer; 38 | } 39 | 40 | public static boolean matchingAssetFile(File sourceFile, byte[] assetFile) throws IOException { 41 | byte[] sf = Files.readAllBytes(sourceFile.toPath()); 42 | return sf == assetFile; 43 | } 44 | 45 | public static String read(String path) throws IOException { 46 | return read(Files.newInputStream(Paths.get(path))); 47 | } 48 | 49 | public static String read(InputStream is) throws IOException { 50 | StringBuilder out = new StringBuilder(); 51 | int len; 52 | byte[] buf = new byte[512]; 53 | while((len = is.read(buf))!=-1) { 54 | out.append(new String(buf, 0, len)); 55 | } 56 | return out.toString(); 57 | } 58 | 59 | public static void write(String path, byte[] content) throws IOException 60 | { 61 | File outPath = new File(path); 62 | Objects.requireNonNull(outPath.getParentFile()).mkdirs(); 63 | if(!outPath.exists()) { 64 | outPath.createNewFile(); 65 | } 66 | 67 | BufferedOutputStream fos = new BufferedOutputStream(Files.newOutputStream(outPath.toPath())); 68 | fos.write(content, 0, content.length); 69 | fos.close(); 70 | } 71 | 72 | public static void unzipArchive(String archivePath, String extractPath) { 73 | try { 74 | try(ZipFile zipFile = new ZipFile(archivePath)) { 75 | byte[] buf = new byte[1024]; 76 | Enumeration entries = zipFile.entries(); 77 | while(entries.hasMoreElements()) { 78 | ZipEntry entry = entries.nextElement(); 79 | if(entry.isDirectory()) { 80 | continue; 81 | } 82 | 83 | File newFile = newFile(new File(extractPath), entry); 84 | newFile.getParentFile().mkdirs(); 85 | 86 | FileOutputStream fos = new FileOutputStream(newFile); 87 | InputStream input = zipFile.getInputStream(entry); 88 | int len; 89 | while ((len = input.read(buf)) > 0) { 90 | fos.write(buf, 0, len); 91 | fos.flush(); 92 | } 93 | fos.close(); 94 | } 95 | } 96 | } catch (IOException e) { 97 | Logger.getInstance().appendToLog(e.getMessage()); 98 | } 99 | } 100 | 101 | public static void unzipArchiveFromAsset(Activity activity, String archiveName, String extractPath) { 102 | try { 103 | File zip = new File(extractPath, archiveName); 104 | FileUtils.writeByteArrayToFile(zip, FileUtil.loadFromAssetToByte(activity, archiveName)); 105 | try(ZipFile zipFile = new ZipFile(zip)) { 106 | byte[] buf = new byte[1024]; 107 | Enumeration entries = zipFile.entries(); 108 | while(entries.hasMoreElements()) { 109 | ZipEntry entry = entries.nextElement(); 110 | if(entry.isDirectory()) { 111 | continue; 112 | } 113 | 114 | File newFile = newFile(new File(extractPath), entry); 115 | newFile.getParentFile().mkdirs(); 116 | 117 | FileOutputStream fos = new FileOutputStream(newFile); 118 | InputStream input = zipFile.getInputStream(entry); 119 | int len; 120 | while ((len = input.read(buf)) > 0) { 121 | fos.write(buf, 0, len); 122 | fos.flush(); 123 | } 124 | fos.close(); 125 | } 126 | } 127 | } catch (IOException e) { 128 | Logger.getInstance().appendToLog(e.getMessage()); 129 | } 130 | } 131 | 132 | public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { 133 | File destFile = new File(destinationDir, zipEntry.getName()); 134 | 135 | String destDirPath = destinationDir.getCanonicalPath(); 136 | String destFilePath = destFile.getCanonicalPath(); 137 | 138 | if (!destFilePath.startsWith(destDirPath + File.separator)) { 139 | throw new IOException("Entry is outside of the target dir: " + zipEntry.getName()); 140 | } 141 | 142 | return destFile; 143 | } 144 | 145 | /** 146 | * @author PojavLauncherTeam 147 | * Same as ensureDirectorySilently(), but throws an IOException telling why the check failed. 148 | * @param targetFile the directory to check 149 | * @throws IOException when the checks fail 150 | */ 151 | public static void ensureDirectory(File targetFile) throws IOException{ 152 | if(targetFile.isFile()) throw new IOException("Target directory is a file"); 153 | if(targetFile.exists()) { 154 | if(!targetFile.canWrite()) throw new IOException("Target directory is not writable"); 155 | }else if(!targetFile.mkdirs()) throw new IOException("Unable to create target directory"); 156 | } 157 | 158 | /** 159 | * @author PojavLauncherTeam 160 | * Same as ensureParentDirectorySilently(), but throws an IOException telling why the check failed. 161 | * @param targetFile the File whose parent should be checked 162 | * @throws IOException when the checks fail 163 | */ 164 | public static void ensureParentDirectory(File targetFile) throws IOException{ 165 | File parentFile = targetFile.getParentFile(); 166 | if(parentFile == null) throw new IOException("targetFile does not have a parent"); 167 | ensureDirectory(parentFile); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/GsonUtils.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | 6 | import java.io.*; 7 | import java.nio.charset.StandardCharsets; 8 | import java.nio.file.Files; 9 | import java.nio.file.Paths; 10 | 11 | public class GsonUtils { 12 | public static final Gson GLOBAL_GSON = new GsonBuilder().setPrettyPrinting().create(); 13 | 14 | public static T jsonFileToObject(String path, Class tClass) { 15 | try { 16 | return new Gson().fromJson(new FileReader(path), tClass); 17 | } catch (FileNotFoundException e) { 18 | return null; 19 | } 20 | } 21 | 22 | public static void objectToJsonFile(String path, Object object) { 23 | File dir = new File(path).getParentFile(); 24 | if (dir != null) dir.mkdirs(); 25 | 26 | try (Writer writer = Files.newBufferedWriter(Paths.get(path), StandardCharsets.UTF_8)) { 27 | Gson gson = new GsonBuilder().setPrettyPrinting().create(); 28 | gson.toJson(object, writer); 29 | } catch (IOException ignored) {} 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/Logger.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | import androidx.annotation.Keep; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.io.PrintStream; 8 | import java.lang.ref.WeakReference; 9 | 10 | /** Singleton class made to log on one file 11 | * The singleton part can be removed but will require more implementation from the end-dev 12 | */ 13 | @Keep 14 | public class Logger { 15 | 16 | /* Instance variables */ 17 | private final File mLogFile; 18 | private PrintStream mLogStream; 19 | private WeakReference mLogListenerWeakReference = null; 20 | 21 | /* No public construction */ 22 | private Logger(){ 23 | this("latestlog.txt"); 24 | } 25 | 26 | private Logger(String fileName){ 27 | mLogFile = new File(Constants.USER_HOME, fileName); 28 | // Make a new instance of the log file 29 | mLogFile.delete(); 30 | try { 31 | mLogFile.createNewFile(); 32 | mLogStream = new PrintStream(mLogFile.getAbsolutePath()); 33 | }catch (IOException e){e.printStackTrace();} 34 | 35 | } 36 | 37 | private static final class SLoggerSingletonHolder { 38 | static final Logger sLoggerSingleton = new Logger(); 39 | } 40 | 41 | public static Logger getInstance(){ 42 | return SLoggerSingletonHolder.sLoggerSingleton; 43 | } 44 | 45 | 46 | /** Print the text to the log file if not censored */ 47 | public void appendToLog(String text){ 48 | if(shouldCensorLog(text)) return; 49 | appendToLogUnchecked(text); 50 | } 51 | 52 | /** Print the text to the log file, no china censoring there */ 53 | public void appendToLogUnchecked(String text){ 54 | mLogStream.println(text); 55 | notifyLogListener(text); 56 | } 57 | 58 | /** Reset the log file, effectively erasing any previous logs */ 59 | public void reset(){ 60 | try{ 61 | mLogFile.delete(); 62 | mLogFile.createNewFile(); 63 | mLogStream = new PrintStream(mLogFile.getAbsolutePath()); 64 | }catch (IOException e){ e.printStackTrace();} 65 | } 66 | 67 | /** Disables the printing */ 68 | public void shutdown(){ 69 | mLogStream.close(); 70 | } 71 | 72 | /** 73 | * Perform various checks to see if the log is safe to print 74 | * Subclasses may want to override this behavior 75 | * @param text The text to check 76 | * @return Whether the log should be censored 77 | */ 78 | private static boolean shouldCensorLog(String text){ 79 | return text.contains("Session ID is"); 80 | } 81 | 82 | /** Small listener for anything listening to the log */ 83 | public interface eventLogListener { 84 | void onEventLogged(String text); 85 | } 86 | 87 | /** Link a log listener to the logger */ 88 | public void setLogListener(eventLogListener logListener){ 89 | this.mLogListenerWeakReference = new WeakReference<>(logListener); 90 | } 91 | 92 | /** Notifies the event listener, if it exists */ 93 | private void notifyLogListener(String text){ 94 | if(mLogListenerWeakReference == null) return; 95 | eventLogListener logListener = mLogListenerWeakReference.get(); 96 | if(logListener == null){ 97 | mLogListenerWeakReference = null; 98 | return; 99 | } 100 | logListener.onEventLogged(text); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/MCOptionUtils.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | import static org.lwjgl.glfw.CallbackBridge.windowHeight; 4 | import static org.lwjgl.glfw.CallbackBridge.windowWidth; 5 | 6 | import android.os.Build; 7 | import android.os.FileObserver; 8 | import android.util.Log; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.annotation.Nullable; 12 | 13 | import java.io.BufferedReader; 14 | import java.io.File; 15 | import java.io.FileReader; 16 | import java.io.IOException; 17 | import java.lang.ref.WeakReference; 18 | import java.util.ArrayList; 19 | import java.util.HashMap; 20 | import java.util.Objects; 21 | 22 | import pojlib.API; 23 | 24 | public class MCOptionUtils { 25 | private static final HashMap sParameterMap = new HashMap<>(); 26 | private static final ArrayList> sOptionListeners = new ArrayList<>(); 27 | private static FileObserver sFileObserver; 28 | private static String sOptionFolderPath = null; 29 | public interface MCOptionListener { 30 | /** Called when an option is changed. Don't know which one though */ 31 | void onOptionChanged(); 32 | } 33 | 34 | 35 | public static void load(){ 36 | load(sOptionFolderPath == null 37 | ? API.currentInstance.gameDir 38 | : sOptionFolderPath); 39 | } 40 | 41 | public static void load(@NonNull String folderPath) { 42 | File optionFile = new File(folderPath + "/options.txt"); 43 | if(!optionFile.exists()) { 44 | try { // Needed for new instances I guess :think: 45 | optionFile.createNewFile(); 46 | } catch (IOException e) { e.printStackTrace(); } 47 | } 48 | 49 | if(sFileObserver == null || !Objects.equals(sOptionFolderPath, folderPath)){ 50 | sOptionFolderPath = folderPath; 51 | setupFileObserver(); 52 | } 53 | sOptionFolderPath = folderPath; // Yeah I know, it may be redundant 54 | 55 | sParameterMap.clear(); 56 | 57 | try { 58 | BufferedReader reader = new BufferedReader(new FileReader(optionFile)); 59 | String line; 60 | while ((line = reader.readLine()) != null) { 61 | int firstColonIndex = line.indexOf(':'); 62 | if(firstColonIndex < 0) { 63 | Log.w("QuestCraft", "No colon on line \""+line+"\", skipping"); 64 | continue; 65 | } 66 | sParameterMap.put(line.substring(0,firstColonIndex), line.substring(firstColonIndex+1)); 67 | } 68 | reader.close(); 69 | } catch (IOException e) { 70 | Log.w("QuestCraft", "Could not load options.txt", e); 71 | } 72 | } 73 | 74 | public static String get(String key) { 75 | return sParameterMap.get(key); 76 | } 77 | 78 | /** @return The stored Minecraft GUI scale, also auto-computed if on auto-mode or improper setting */ 79 | public static int getMcScale() { 80 | String str = MCOptionUtils.get("guiScale"); 81 | int guiScale = (str == null ? 0 :Integer.parseInt(str)); 82 | 83 | int scale = Math.max(Math.min(windowWidth / 320, windowHeight / 240), 1); 84 | if(scale < guiScale || guiScale == 0){ 85 | guiScale = scale; 86 | } 87 | 88 | return guiScale; 89 | } 90 | 91 | /** Add a file observer to reload options on file change 92 | * Listeners get notified of the change */ 93 | private static void setupFileObserver(){ 94 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ 95 | sFileObserver = new FileObserver(new File(sOptionFolderPath + "/options.txt"), FileObserver.MODIFY) { 96 | @Override 97 | public void onEvent(int i, @Nullable String s) { 98 | MCOptionUtils.load(); 99 | notifyListeners(); 100 | } 101 | }; 102 | }else{ 103 | sFileObserver = new FileObserver(sOptionFolderPath + "/options.txt", FileObserver.MODIFY) { 104 | @Override 105 | public void onEvent(int i, @Nullable String s) { 106 | MCOptionUtils.load(); 107 | notifyListeners(); 108 | } 109 | }; 110 | } 111 | 112 | sFileObserver.startWatching(); 113 | } 114 | 115 | /** Notify the option listeners */ 116 | public static void notifyListeners(){ 117 | for(WeakReference weakReference : sOptionListeners){ 118 | MCOptionListener optionListener = weakReference.get(); 119 | if(optionListener == null) continue; 120 | 121 | optionListener.onOptionChanged(); 122 | } 123 | } 124 | 125 | /** Add an option listener, notice how we don't have a reference to it */ 126 | public static void addMCOptionListener(MCOptionListener listener){ 127 | sOptionListeners.add(new WeakReference<>(listener)); 128 | } 129 | 130 | /** Remove a listener from existence, or at least, its reference here */ 131 | public static void removeMCOptionListener(MCOptionListener listener){ 132 | for(WeakReference weakReference : sOptionListeners){ 133 | MCOptionListener optionListener = weakReference.get(); 134 | if(optionListener == null) continue; 135 | if(optionListener == listener){ 136 | sOptionListeners.remove(weakReference); 137 | return; 138 | } 139 | } 140 | } 141 | 142 | } -------------------------------------------------------------------------------- /src/main/java/pojlib/util/MSAException.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | import pojlib.API; 4 | 5 | public class MSAException extends Exception { 6 | public MSAException(String msaMessage) { 7 | API.msaMessage = msaMessage; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/MathUtils.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | public class MathUtils { 4 | 5 | /** Returns the distance between two points. */ 6 | public static float dist(float x1, float y1, float x2, float y2) { 7 | final float x = (x2 - x1); 8 | final float y = (y2 - y1); 9 | return (float) Math.hypot(x, y); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/VLoader.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | import android.content.Context; 4 | 5 | public class VLoader { 6 | static { 7 | System.loadLibrary("vloader"); 8 | } 9 | 10 | public static native void setAndroidInitInfo(Context ctx); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/Version.java: -------------------------------------------------------------------------------- 1 | package pojlib.util; 2 | 3 | public class Version { 4 | public final int major, minor, patch; 5 | 6 | public Version(int major, int minor, int patch) { 7 | this.major = major; 8 | this.minor = minor; 9 | this.patch = patch; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/download/DownloadManager.java: -------------------------------------------------------------------------------- 1 | package pojlib.util.download; 2 | 3 | public class DownloadManager { 4 | private static long downloadedBytes = 0; 5 | private static long totalBytes = 0; 6 | 7 | public static void addBytes(long add) { 8 | downloadedBytes += add; 9 | } 10 | 11 | public static void addTotalBytes(long add) { 12 | totalBytes += add; 13 | } 14 | 15 | public static void reset() { 16 | downloadedBytes = 0; 17 | totalBytes = 0; 18 | } 19 | 20 | public static boolean downloadsCompleted() { 21 | return downloadedBytes == totalBytes; 22 | } 23 | 24 | public static float getPercentComplete() { 25 | if(totalBytes == 0 || downloadedBytes > totalBytes) { 26 | return 100.0f; 27 | } 28 | 29 | return (float) downloadedBytes/totalBytes * 100; 30 | } 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/download/DownloadUtils.java: -------------------------------------------------------------------------------- 1 | package pojlib.util.download; 2 | 3 | import org.apache.commons.codec.binary.Hex; 4 | import org.apache.commons.codec.digest.DigestUtils; 5 | import org.apache.commons.io.IOUtils; 6 | 7 | import pojlib.API; 8 | import pojlib.util.Logger; 9 | 10 | import javax.net.ssl.SSLException; 11 | import java.io.*; 12 | import java.net.HttpURLConnection; 13 | import java.net.URL; 14 | import java.nio.file.Files; 15 | import java.util.Objects; 16 | import javax.annotation.Nullable; 17 | 18 | public class DownloadUtils { 19 | private static void download(URL url, OutputStream os, long size) throws IOException { 20 | final int MAX_RETRIES = 3; 21 | int attempts = 0; 22 | 23 | while (true) { 24 | try { 25 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 26 | conn.setRequestProperty("User-Agent", "QuestCraft"); 27 | conn.setConnectTimeout(10000); 28 | conn.setDoInput(true); 29 | conn.connect(); 30 | 31 | if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { 32 | if(size == -1) { 33 | size = conn.getContentLengthLong(); 34 | } 35 | 36 | try (InputStream is = new StreamDL(conn.getInputStream(), size)) { 37 | IOUtils.copy(is, os); 38 | } 39 | return; 40 | } 41 | } catch (IOException e) { 42 | if (++attempts >= MAX_RETRIES || e instanceof SSLException) { 43 | throw new IOException("Unable to download from " + url, e); 44 | } 45 | } 46 | } 47 | } 48 | 49 | public static void downloadFile(String url, File out) throws IOException { 50 | downloadFile(url, out, -1); 51 | } 52 | 53 | public static void downloadFile(String url, File out, long size) throws IOException { 54 | Objects.requireNonNull(out.getParentFile()).mkdirs(); 55 | File tempOut = File.createTempFile(out.getName(), ".part", out.getParentFile()); 56 | try { 57 | try (OutputStream bos2 = new BufferedOutputStream(Files.newOutputStream(tempOut.toPath()))) { 58 | download(new URL(url), bos2, size); 59 | tempOut.renameTo(out); 60 | bos2.close(); 61 | if (tempOut.exists()) tempOut.delete(); 62 | } catch (IOException th2) { 63 | if (tempOut.exists()) tempOut.delete(); 64 | throw th2; 65 | } 66 | } catch (IOException e) { 67 | if (tempOut.exists()) tempOut.delete(); 68 | throw e; 69 | } 70 | } 71 | 72 | public static boolean compareSHA1(File f, @Nullable String sourceSHA) { 73 | try { 74 | String sha1_dst; 75 | try (InputStream is = Files.newInputStream(f.toPath())) { 76 | sha1_dst = new String(Hex.encodeHex(DigestUtils.sha1(is))); 77 | } 78 | if (sourceSHA != null) return sha1_dst.equalsIgnoreCase(sourceSHA); 79 | else return true; // No hash provided 80 | 81 | } catch (IOException e) { 82 | Logger.getInstance().appendToLog("Issue while comparing SHA1: " + e); 83 | return false; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/download/StreamDL.java: -------------------------------------------------------------------------------- 1 | package pojlib.util.download; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.ArrayList; 6 | import java.util.Collection; 7 | 8 | public class StreamDL extends InputStream { 9 | private final InputStream in; 10 | private int count; 11 | private final Collection listeners = new ArrayList<>(); 12 | 13 | public StreamDL(InputStream in, long totalBytes) { 14 | this.in = in; 15 | DownloadManager.addTotalBytes(totalBytes); 16 | } 17 | 18 | @Override 19 | public int read() throws IOException { 20 | int b = in.read(); 21 | byteReceived(b); 22 | return b; 23 | } 24 | 25 | public void addListener(StreamListener listener) { 26 | listeners.add(listener); 27 | } 28 | 29 | private void byteReceived(int b) { 30 | if (b != -1) { 31 | count++; 32 | DownloadManager.addBytes(1); 33 | } 34 | 35 | for (StreamListener l : listeners) { 36 | l.byteReceived(b, count); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/download/StreamListener.java: -------------------------------------------------------------------------------- 1 | package pojlib.util.download; 2 | 3 | import java.util.EventListener; 4 | 5 | public interface StreamListener extends EventListener { 6 | void byteReceived(int b, int count); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/json/ModrinthIndexJson.java: -------------------------------------------------------------------------------- 1 | package pojlib.util.json; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class ModrinthIndexJson { 6 | public String versionId; 7 | public String name; 8 | public String summary; 9 | public ModpackFile[] files; 10 | public Dependencies dependencies; 11 | 12 | public static class ModpackFile { 13 | public String path; 14 | public String[] downloads; 15 | public int fileSize; 16 | } 17 | 18 | public static class Dependencies { 19 | public String minecraft; 20 | @SerializedName("fabric-loader") 21 | public String fabricLoader; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/json/ModsJson.java: -------------------------------------------------------------------------------- 1 | package pojlib.util.json; 2 | 3 | public class ModsJson { 4 | public Version[] versions; 5 | 6 | public static class Version { 7 | public String name; 8 | public ProjectInfo[] coreMods; 9 | public ProjectInfo[] defaultMods; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/pojlib/util/json/ProjectInfo.java: -------------------------------------------------------------------------------- 1 | package pojlib.util.json; 2 | 3 | public class ProjectInfo { 4 | public String slug; 5 | public String fileName; 6 | public String version; 7 | public String type = "mod"; 8 | public String download_link; 9 | } -------------------------------------------------------------------------------- /src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | HERE_PATH := $(LOCAL_PATH) 3 | 4 | # include $(HERE_PATH)/crash_dump/libbase/Android.mk 5 | # include $(HERE_PATH)/crash_dump/libbacktrace/Android.mk 6 | # include $(HERE_PATH)/crash_dump/debuggerd/Android.mk 7 | 8 | LOCAL_PATH := $(HERE_PATH) 9 | 10 | include $(CLEAR_VARS) 11 | LOCAL_MODULE := openxr_loader 12 | LOCAL_SRC_FILES := libopenxr_loader.so 13 | include $(PREBUILT_SHARED_LIBRARY) 14 | 15 | include $(CLEAR_VARS) 16 | # Link GLESv2 for test 17 | LOCAL_LDLIBS := -ldl -llog -landroid -lGLESv3 -lEGL 18 | LOCAL_CFLAGS := -DXR_USE_PLATFORM_ANDROID -DXR_USE_GRAPHICS_API_OPENGL_ES 19 | # -lGLESv2 20 | LOCAL_MODULE := pojavexec 21 | # LOCAL_CFLAGS += -DDEBUG 22 | # -DGLES_TEST 23 | LOCAL_SRC_FILES := \ 24 | egl_bridge.c \ 25 | utils.c \ 26 | environ/environ.c \ 27 | input_bridge_v3.c 28 | include $(BUILD_SHARED_LIBRARY) 29 | 30 | include $(CLEAR_VARS) 31 | LOCAL_LDLIBS := -llog -landroid -lGLESv3 -lvulkan -lEGL 32 | LOCAL_CFLAGS := -DXR_USE_PLATFORM_ANDROID -DXR_USE_GRAPHICS_API_OPENGL_ES 33 | LOCAL_SHARED_LIBRARIES := pojavexec openxr_loader 34 | LOCAL_MODULE := vloader 35 | LOCAL_SRC_FILES := \ 36 | vloader.cpp 37 | include $(BUILD_SHARED_LIBRARY) 38 | 39 | include $(CLEAR_VARS) 40 | LOCAL_MODULE := istdio 41 | LOCAL_SRC_FILES := \ 42 | stdio_is.c 43 | include $(BUILD_SHARED_LIBRARY) 44 | 45 | include $(CLEAR_VARS) 46 | LOCAL_MODULE := pojavexec_awt 47 | LOCAL_SRC_FILES := \ 48 | awt_bridge.c 49 | include $(BUILD_SHARED_LIBRARY) 50 | 51 | include $(CLEAR_VARS) 52 | LOCAL_MODULE := jrelauncher 53 | LOCAL_SHARED_LIBRARIES := pojavexec 54 | LOCAL_LDLIBS := -llog -landroid 55 | LOCAL_SRC_FILES := \ 56 | jre_launcher.c 57 | include $(BUILD_SHARED_LIBRARY) 58 | 59 | # Helper to get current thread 60 | # include $(CLEAR_VARS) 61 | # LOCAL_MODULE := thread64helper 62 | # LOCAL_SRC_FILES := thread_helper.cpp 63 | # include $(BUILD_SHARED_LIBRARY) 64 | 65 | # fake lib for linker 66 | include $(CLEAR_VARS) 67 | LOCAL_MODULE := awt_headless 68 | include $(BUILD_SHARED_LIBRARY) 69 | 70 | # libawt_xawt without X11, used to get Caciocavallo working 71 | LOCAL_PATH := $(HERE_PATH)/awt_xawt 72 | include $(CLEAR_VARS) 73 | LOCAL_MODULE := awt_xawt 74 | # LOCAL_CFLAGS += -DHEADLESS 75 | LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) 76 | LOCAL_SHARED_LIBRARIES := awt_headless 77 | LOCAL_SRC_FILES := xawt_fake.c 78 | include $(BUILD_SHARED_LIBRARY) 79 | 80 | # delete fake libs after linked 81 | $(info $(shell (rm $(HERE_PATH)/../jniLibs/*/libawt_headless.so))) 82 | 83 | -------------------------------------------------------------------------------- /src/main/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_STL := c++_shared -------------------------------------------------------------------------------- /src/main/jni/awt_xawt/xawt_fake.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // java.awt.* 4 | JNIEXPORT void JNICALL 5 | Java_java_awt_AWTEvent_initIDs(JNIEnv *env, jclass cls) 6 | { 7 | } 8 | 9 | JNIEXPORT void JNICALL 10 | Java_java_awt_Button_initIDs 11 | (JNIEnv *env, jclass cls) 12 | { 13 | } 14 | 15 | JNIEXPORT void JNICALL 16 | Java_java_awt_Component_initIDs 17 | (JNIEnv *env, jclass cls) 18 | { 19 | } 20 | 21 | JNIEXPORT void JNICALL 22 | Java_java_awt_Container_initIDs 23 | (JNIEnv *env, jclass cls) 24 | { 25 | } 26 | 27 | JNIEXPORT void JNICALL 28 | Java_java_awt_Checkbox_initIDs 29 | (JNIEnv *env, jclass cls) 30 | { 31 | } 32 | 33 | JNIEXPORT void JNICALL 34 | Java_java_awt_Cursor_initIDs 35 | (JNIEnv *env, jclass cls) 36 | { 37 | 38 | } 39 | 40 | JNIEXPORT void JNICALL 41 | Java_java_awt_Cursor_finalizeImpl(JNIEnv *env, jclass clazz, jlong pData) 42 | { 43 | 44 | } 45 | 46 | JNIEXPORT void JNICALL 47 | Java_java_awt_Dialog_initIDs 48 | (JNIEnv *env, jclass cls) 49 | { 50 | 51 | } 52 | 53 | JNIEXPORT void JNICALL 54 | Java_java_awt_Event_initIDs(JNIEnv *env, jclass cls) 55 | { 56 | 57 | } 58 | 59 | JNIEXPORT void JNICALL 60 | Java_java_awt_FileDialog_initIDs 61 | (JNIEnv *env, jclass cls) 62 | { 63 | 64 | } 65 | 66 | JNIEXPORT void JNICALL 67 | Java_java_awt_Frame_initIDs 68 | (JNIEnv *env, jclass cls) 69 | { 70 | } 71 | 72 | JNIEXPORT void JNICALL 73 | Java_java_awt_Insets_initIDs 74 | (JNIEnv *env, jclass cls) 75 | { 76 | } 77 | 78 | JNIEXPORT void JNICALL 79 | Java_java_awt_KeyboardFocusManager_initIDs 80 | (JNIEnv *env, jclass cls) 81 | { 82 | 83 | } 84 | 85 | JNIEXPORT void JNICALL Java_java_awt_Menu_initIDs 86 | (JNIEnv *env, jclass cls) 87 | { 88 | } 89 | 90 | JNIEXPORT void JNICALL 91 | Java_java_awt_MenuComponent_initIDs(JNIEnv *env, jclass cls) 92 | { 93 | 94 | } 95 | 96 | JNIEXPORT void JNICALL Java_java_awt_MenuItem_initIDs 97 | (JNIEnv *env, jclass cls) 98 | { 99 | } 100 | 101 | JNIEXPORT void JNICALL 102 | Java_java_awt_Scrollbar_initIDs 103 | (JNIEnv *env, jclass cls) 104 | { 105 | 106 | } 107 | 108 | JNIEXPORT void JNICALL Java_java_awt_ScrollPane_initIDs 109 | (JNIEnv *env, jclass cls) 110 | { 111 | } 112 | 113 | JNIEXPORT void JNICALL 114 | Java_java_awt_TextArea_initIDs 115 | (JNIEnv *env, jclass cls) 116 | { 117 | } 118 | 119 | JNIEXPORT void JNICALL 120 | Java_java_awt_TextField_initIDs 121 | (JNIEnv *env, jclass cls) 122 | { 123 | } 124 | 125 | JNIEXPORT void JNICALL Java_java_awt_TrayIcon_initIDs(JNIEnv *env , jclass clazz) 126 | { 127 | } 128 | 129 | JNIEXPORT void JNICALL 130 | Java_java_awt_Window_initIDs 131 | (JNIEnv *env, jclass cls) 132 | { 133 | } 134 | 135 | // java.awt.event.* 136 | JNIEXPORT void JNICALL 137 | Java_java_awt_event_InputEvent_initIDs(JNIEnv *env, jclass cls) 138 | { 139 | } 140 | 141 | JNIEXPORT void JNICALL 142 | Java_java_awt_event_KeyEvent_initIDs(JNIEnv *env, jclass cls) 143 | { 144 | } 145 | 146 | JNIEXPORT void JNICALL 147 | Java_java_awt_AWTEvent_nativeSetSource(JNIEnv *env, jobject self, 148 | jobject newSource) 149 | { 150 | // Maybe implement this? 151 | } 152 | 153 | // sun.awt.SunToolkit 154 | JNIEXPORT void JNICALL 155 | Java_sun_awt_SunToolkit_closeSplashScreen 156 | (JNIEnv *env, jclass cls) 157 | { 158 | 159 | } 160 | // sun.awt.UNIXToolkit 161 | JNIEXPORT jboolean JNICALL 162 | Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) { 163 | return JNI_FALSE; 164 | } 165 | 166 | JNIEXPORT jint JNICALL 167 | Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv *env, jclass klass) 168 | { 169 | // return GTK_ANY; 170 | return (jint) 1; 171 | } 172 | 173 | JNIEXPORT jboolean JNICALL 174 | Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl(JNIEnv *env, jobject this, 175 | jint major, jint minor, jint micro) 176 | { 177 | return JNI_FALSE; 178 | } 179 | 180 | JNIEXPORT jboolean JNICALL 181 | Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version, 182 | jboolean verbose) { 183 | return JNI_FALSE; 184 | } 185 | 186 | JNIEXPORT jboolean JNICALL 187 | Java_sun_awt_UNIXToolkit_load_1gtk_1icon(JNIEnv *env, jobject this, 188 | jstring filename) 189 | { 190 | return JNI_FALSE; 191 | } 192 | 193 | JNIEXPORT jboolean JNICALL 194 | Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this, 195 | jint widget_type, jstring stock_id, jint icon_size, 196 | jint text_direction, jstring detail) 197 | { 198 | return JNI_FALSE; 199 | } 200 | 201 | JNIEXPORT void JNICALL 202 | Java_sun_awt_UNIXToolkit_nativeSync(JNIEnv *env, jobject this) 203 | { 204 | 205 | } 206 | 207 | JNIEXPORT jboolean JNICALL 208 | Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv *env, jclass klass) 209 | { 210 | return JNI_FALSE; 211 | } 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /src/main/jni/egl_bridge.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #ifdef GLES_TEST 15 | #include 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "utils.h" 24 | #include "environ/environ.h" 25 | #include "GL/gl.h" 26 | 27 | typedef EGLDisplay eglGetDisplay_t (EGLNativeDisplayType display_id); 28 | typedef EGLBoolean eglInitialize_t (EGLDisplay dpy, EGLint *major, EGLint *minor); 29 | typedef EGLBoolean eglChooseConfig_t (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); 30 | typedef EGLBoolean eglGetConfigAttrib_t (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); 31 | typedef EGLBoolean eglBindAPI_t (EGLenum api); 32 | typedef EGLSurface eglCreatePbufferSurface_t (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); 33 | typedef EGLContext eglCreateContext_t (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); 34 | typedef EGLBoolean eglMakeCurrent_t (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); 35 | typedef EGLint eglGetError_t (void); 36 | typedef EGLBoolean eglSwapBuffers_t (EGLDisplay dpy, EGLSurface surface); 37 | typedef EGLBoolean eglSwapInterval_t (EGLDisplay dpy, EGLint interval); 38 | typedef __eglMustCastToProperFunctionPointerType eglGetProcAddress_t (const char *procname); 39 | 40 | eglGetDisplay_t* eglGetDisplay_p; 41 | eglInitialize_t* eglInitialize_p; 42 | eglChooseConfig_t* eglChooseConfig_p; 43 | eglGetConfigAttrib_t* eglGetConfigAttrib_p; 44 | eglBindAPI_t* eglBindAPI_p; 45 | eglCreatePbufferSurface_t* eglCreatePbufferSurface_p; 46 | eglCreateContext_t* eglCreateContext_p; 47 | eglMakeCurrent_t* eglMakeCurrent_p; 48 | eglGetError_t* eglGetError_p; 49 | eglSwapBuffers_t* eglSwapBuffers_p; 50 | eglSwapInterval_t* eglSwapInterval_p; 51 | eglGetProcAddress_t* eglGetProcAddress_p; 52 | 53 | EGLContext xrEglContext; 54 | EGLDisplay xrEglDisplay; 55 | EGLSurface xrEglSurface; 56 | EGLConfig xrConfig; 57 | 58 | void* gbuffer; 59 | 60 | void pojav_openGLOnLoad() { 61 | } 62 | void pojav_openGLOnUnload() { 63 | 64 | } 65 | 66 | void pojavTerminate() { 67 | } 68 | 69 | void dlsym_egl() { 70 | void* handle = dlopen("libltw.so", RTLD_NOW); 71 | eglGetProcAddress_p = (eglGetProcAddress_t*) dlsym(handle, "eglGetProcAddress"); 72 | eglGetDisplay_p = (eglGetDisplay_t*) eglGetProcAddress_p("eglGetDisplay"); 73 | eglInitialize_p = (eglInitialize_t*) eglGetProcAddress_p("eglInitialize"); 74 | eglChooseConfig_p = (eglChooseConfig_t*) eglGetProcAddress_p("eglChooseConfig"); 75 | eglGetConfigAttrib_p = (eglGetConfigAttrib_t*) eglGetProcAddress_p("eglGetConfigAttrib"); 76 | eglBindAPI_p = (eglBindAPI_t*) eglGetProcAddress_p("eglBindAPI"); 77 | eglCreatePbufferSurface_p = (eglCreatePbufferSurface_t*) eglGetProcAddress_p("eglCreatePbufferSurface"); 78 | eglCreateContext_p = (eglCreateContext_t*) eglGetProcAddress_p("eglCreateContext"); 79 | eglMakeCurrent_p = (eglMakeCurrent_t*) eglGetProcAddress_p("eglMakeCurrent"); 80 | eglGetError_p = (eglGetError_t*) eglGetProcAddress_p("eglGetError"); 81 | eglSwapBuffers_p = (eglSwapBuffers_t*) eglGetProcAddress_p("eglSwapBuffers"); 82 | eglSwapInterval_p = (eglSwapInterval_t*) eglGetProcAddress_p("eglSwapInterval"); 83 | } 84 | 85 | void* pojavGetCurrentContext() { 86 | return xrEglContext; 87 | } 88 | 89 | int xrEglInit() { 90 | dlsym_egl(); 91 | 92 | if (xrEglDisplay == NULL || xrEglDisplay == EGL_NO_DISPLAY) { 93 | xrEglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY); 94 | if (xrEglDisplay == EGL_NO_DISPLAY) { 95 | printf("EGLBridge: Error eglGetDefaultDisplay() failed: %p\n", eglGetError_p()); 96 | return 0; 97 | } 98 | } 99 | 100 | printf("EGLBridge: Initializing\n"); 101 | // printf("EGLBridge: ANativeWindow pointer = %p\n", androidWindow); 102 | //(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); 103 | if (!eglInitialize_p(xrEglDisplay, NULL, NULL)) { 104 | printf("EGLBridge: Error eglInitialize() failed: %s\n", eglGetError_p()); 105 | return 0; 106 | } 107 | 108 | static const EGLint attribs[] = { 109 | EGL_RED_SIZE, 8, 110 | EGL_GREEN_SIZE, 8, 111 | EGL_BLUE_SIZE, 8, 112 | EGL_ALPHA_SIZE, 8, 113 | // Minecraft required on initial 24 114 | EGL_DEPTH_SIZE, 24, 115 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, 116 | EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 117 | EGL_NONE 118 | }; 119 | 120 | EGLint num_configs; 121 | EGLint vid; 122 | 123 | if (!eglChooseConfig_p(xrEglDisplay, attribs, &xrConfig, 1, &num_configs)) { 124 | printf("EGLBridge: Error couldn't get an EGL visual config: %s\n", eglGetError_p()); 125 | return 0; 126 | } 127 | 128 | assert(xrConfig); 129 | assert(num_configs > 0); 130 | 131 | if (!eglGetConfigAttrib_p(xrEglDisplay, xrConfig, EGL_NATIVE_VISUAL_ID, &vid)) { 132 | printf("EGLBridge: Error eglGetConfigAttrib() failed: %s\n", eglGetError_p()); 133 | return 0; 134 | } 135 | 136 | eglBindAPI_p(EGL_OPENGL_ES_API); 137 | 138 | xrEglSurface = eglCreatePbufferSurface_p(xrEglDisplay, xrConfig, 139 | NULL); 140 | if (!xrEglSurface) { 141 | printf("EGLBridge: Error eglCreatePbufferSurface failed: %d\n", eglGetError_p()); 142 | return 0; 143 | } 144 | 145 | printf("Created pbuffersurface\n"); 146 | 147 | printf("XREGLBridge: Initialized!\n"); 148 | printf("XREGLBridge: ThreadID=%d\n", gettid()); 149 | printf("XREGLBridge: XREGLDisplay=%p, XREGLSurface=%p\n", 150 | /* window==0 ? EGL_NO_CONTEXT : */ 151 | xrEglDisplay, 152 | xrEglSurface 153 | ); 154 | 155 | return 1; 156 | } 157 | 158 | int pojavInit() { 159 | savedWidth = 1; 160 | savedHeight = 1; 161 | printf("XREGLBridge: Thread name is %d\n", gettid()); 162 | 163 | return xrEglInit(); 164 | } 165 | 166 | void pojavSetWindowHint(int hint, int value) { 167 | // Stub 168 | } 169 | 170 | 171 | int32_t stride; 172 | void pojavSwapBuffers() { 173 | eglSwapBuffers_p(xrEglDisplay, xrEglSurface); 174 | } 175 | 176 | bool locked = false; 177 | void pojavMakeCurrent(void* window) { 178 | EGLBoolean success = eglMakeCurrent_p( 179 | xrEglDisplay, 180 | xrEglSurface, 181 | xrEglSurface, 182 | window 183 | ); 184 | 185 | xrEglContext = window; 186 | 187 | if (success == EGL_FALSE) { 188 | printf("XREGLBridge: Error: eglMakeCurrent() failed: %p\n", eglGetError()); 189 | } else { 190 | printf("XREGLBridge: eglMakeCurrent() succeed!\n"); 191 | } 192 | } 193 | 194 | JNIEXPORT JNICALL jlong 195 | Java_pojlib_util_JREUtils_getEGLDisplayPtr(JNIEnv *env, jclass clazz) { 196 | return (jlong) &xrEglDisplay; 197 | } 198 | 199 | JNIEXPORT JNICALL jlong 200 | Java_pojlib_util_JREUtils_getEGLContextPtr(JNIEnv *env, jclass clazz) { 201 | return (jlong) &xrEglContext; 202 | } 203 | 204 | JNIEXPORT JNICALL jlong 205 | Java_pojlib_util_JREUtils_getEGLConfigPtr(JNIEnv *env, jclass clazz) { 206 | return (jlong) &xrConfig; 207 | } 208 | 209 | void* pojavCreateContext(void* contextSrc) { 210 | const EGLint ctx_attribs[] = { 211 | EGL_CONTEXT_CLIENT_VERSION, 3, 212 | EGL_NONE 213 | }; 214 | EGLContext* ctx = eglCreateContext_p(xrEglDisplay, xrConfig, contextSrc, ctx_attribs); 215 | 216 | printf("XREGLBridge: %p\n", ctx); 217 | return ctx; 218 | } 219 | 220 | JNIEXPORT JNICALL jlong 221 | Java_org_lwjgl_opengl_GL_getGraphicsBufferAddr(JNIEnv *env, jobject thiz) { 222 | return (jlong) &gbuffer; 223 | } 224 | JNIEXPORT JNICALL jintArray 225 | Java_org_lwjgl_opengl_GL_getNativeWidthHeight(JNIEnv *env, jobject thiz) { 226 | jintArray ret = (*env)->NewIntArray(env,2); 227 | jint arr[] = {savedWidth, savedHeight}; 228 | (*env)->SetIntArrayRegion(env,ret,0,2,arr); 229 | return ret; 230 | } 231 | void pojavSwapInterval(int interval) { 232 | eglSwapInterval_p(xrEglDisplay, interval); 233 | } 234 | -------------------------------------------------------------------------------- /src/main/jni/environ/environ.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maks on 24.09.2022. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "environ.h" 10 | struct pojav_environ_s *pojav_environ; 11 | __attribute__((constructor)) void env_init() { 12 | char* strptr_env = getenv("POJAV_ENVIRON"); 13 | if(strptr_env == NULL) { 14 | __android_log_print(ANDROID_LOG_INFO, "Environ", "No environ found, creating..."); 15 | pojav_environ = malloc(sizeof(struct pojav_environ_s)); 16 | assert(pojav_environ); 17 | memset(pojav_environ, 0 , sizeof(struct pojav_environ_s)); 18 | if(asprintf(&strptr_env, "%p", pojav_environ) == -1) abort(); 19 | setenv("POJAV_ENVIRON", strptr_env, 1); 20 | free(strptr_env); 21 | }else{ 22 | __android_log_print(ANDROID_LOG_INFO, "Environ", "Found existing environ: %s", strptr_env); 23 | pojav_environ = (void*) strtoul(strptr_env, NULL, 0x10); 24 | } 25 | __android_log_print(ANDROID_LOG_INFO, "Environ", "%p", pojav_environ); 26 | } -------------------------------------------------------------------------------- /src/main/jni/environ/environ.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by maks on 24.09.2022. 3 | // 4 | 5 | #ifndef POJAVLAUNCHER_ENVIRON_H 6 | #define POJAVLAUNCHER_ENVIRON_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* How many events can be handled at the same time */ 14 | #define EVENT_WINDOW_SIZE 8000 15 | 16 | typedef struct { 17 | int type; 18 | int i1; 19 | int i2; 20 | int i3; 21 | int i4; 22 | } GLFWInputEvent; 23 | 24 | typedef void GLFW_invoke_Char_func(void* window, unsigned int codepoint); 25 | typedef void GLFW_invoke_CharMods_func(void* window, unsigned int codepoint, int mods); 26 | typedef void GLFW_invoke_CursorEnter_func(void* window, int entered); 27 | typedef void GLFW_invoke_CursorPos_func(void* window, double xpos, double ypos); 28 | typedef void GLFW_invoke_FramebufferSize_func(void* window, int width, int height); 29 | typedef void GLFW_invoke_Key_func(void* window, int key, int scancode, int action, int mods); 30 | typedef void GLFW_invoke_MouseButton_func(void* window, int button, int action, int mods); 31 | typedef void GLFW_invoke_Scroll_func(void* window, double xoffset, double yoffset); 32 | typedef void GLFW_invoke_WindowSize_func(void* window, int width, int height); 33 | 34 | struct pojav_environ_s { 35 | atomic_size_t eventCounter; // Count the number of events to be pumped out 36 | GLFWInputEvent events[EVENT_WINDOW_SIZE]; 37 | size_t outEventIndex; // Point to the current event that has yet to be pumped out to MC 38 | size_t outTargetIndex; // Point to the newt index to stop by 39 | size_t inEventIndex; // Point to the next event that has to be filled 40 | size_t inEventCount; // Count registered right before pumping OUT events. Used as a cache. 41 | double cursorX, cursorY, cLastX, cLastY; 42 | jmethodID method_accessAndroidClipboard; 43 | jmethodID method_onGrabStateChanged; 44 | jmethodID method_glftSetWindowAttrib; 45 | jmethodID method_internalWindowSizeChanged; 46 | jmethodID method_restartUnity; 47 | jclass bridgeClazz; 48 | jclass apiClass; 49 | jclass vmGlfwClass; 50 | jboolean isGrabbing; 51 | jbyte* keyDownBuffer; 52 | jbyte* mouseDownBuffer; 53 | JavaVM* runtimeJavaVMPtr; 54 | JNIEnv* runtimeJNIEnvPtr_JRE; 55 | JavaVM* dalvikJavaVMPtr; 56 | JNIEnv* dalvikJNIEnvPtr_ANDROID; 57 | jobject activity; 58 | long showingWindow; 59 | bool isInputReady, isCursorEntered, isUseStackQueueCall, shouldUpdateMouse; 60 | int savedWidth, savedHeight; 61 | #define ADD_CALLBACK_WWIN(NAME) \ 62 | GLFW_invoke_##NAME##_func* GLFW_invoke_##NAME; 63 | ADD_CALLBACK_WWIN(Char); 64 | ADD_CALLBACK_WWIN(CharMods); 65 | ADD_CALLBACK_WWIN(CursorEnter); 66 | ADD_CALLBACK_WWIN(CursorPos); 67 | ADD_CALLBACK_WWIN(FramebufferSize); 68 | ADD_CALLBACK_WWIN(Key); 69 | ADD_CALLBACK_WWIN(MouseButton); 70 | ADD_CALLBACK_WWIN(Scroll); 71 | ADD_CALLBACK_WWIN(WindowSize); 72 | 73 | #undef ADD_CALLBACK_WWIN 74 | }; 75 | extern struct pojav_environ_s *pojav_environ; 76 | 77 | #endif //POJAVLAUNCHER_ENVIRON_H 78 | -------------------------------------------------------------------------------- /src/main/jni/jre_launcher.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "log.h" 36 | #include "utils.h" 37 | 38 | // Uncomment to try redirect signal handling to JVM 39 | #define TRY_SIG2JVM 40 | 41 | #define FULL_VERSION "1.8.0-internal" 42 | #define DOT_VERSION "1.8" 43 | 44 | static const char* const_progname = "java"; 45 | static const char* const_launcher = "openjdk"; 46 | static const char** const_jargs = NULL; 47 | static const char** const_appclasspath = NULL; 48 | static const jboolean const_javaw = JNI_FALSE; 49 | static const jboolean const_cpwildcard = JNI_TRUE; 50 | static const jint const_ergo_class = 0; // DEFAULT_POLICY 51 | static struct sigaction old_sa[NSIG]; 52 | 53 | void (*__old_sa)(int signal, siginfo_t *info, void *reserved); 54 | int (*JVM_handle_linux_signal)(int signo, siginfo_t* siginfo, void* ucontext, int abort_if_unrecognized); 55 | 56 | void android_sigaction(int signal, siginfo_t *info, void *reserved) { 57 | if (JVM_handle_linux_signal == NULL) { // should not happen, but still 58 | __old_sa = old_sa[signal].sa_sigaction; 59 | __old_sa(signal,info,reserved); 60 | exit(1); 61 | } else { 62 | // Based on https://github.com/PojavLauncherTeam/openjdk-multiarch-jdk8u/blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/linux/vm/os_linux.cpp#L4688-4693 63 | int orig_errno = errno; // Preserve errno value over signal handler. 64 | JVM_handle_linux_signal(signal, info, reserved, true); 65 | errno = orig_errno; 66 | } 67 | } 68 | typedef jint JNI_CreateJavaVM_func(JavaVM **pvm, void **penv, void *args); 69 | 70 | typedef jint JLI_Launch_func(int argc, char ** argv, /* main argc, argc */ 71 | int jargc, const char** jargv, /* java args */ 72 | int appclassc, const char** appclassv, /* app classpath */ 73 | const char* fullversion, /* full version defined */ 74 | const char* dotversion, /* dot version defined */ 75 | const char* pname, /* program name */ 76 | const char* lname, /* launcher name */ 77 | jboolean javaargs, /* JAVA_ARGS */ 78 | jboolean cpwildcard, /* classpath wildcard*/ 79 | jboolean javaw, /* windows-only javaw */ 80 | jint ergo /* ergonomics class policy */ 81 | ); 82 | 83 | static jint launchJVM(int margc, char** margv) { 84 | void* libjli = dlopen("libjli.so", RTLD_LAZY | RTLD_GLOBAL); 85 | 86 | // Boardwalk: silence 87 | // LOGD("JLI lib = %x", (int)libjli); 88 | if (NULL == libjli) { 89 | LOGE("JLI lib = NULL: %s", dlerror()); 90 | return -1; 91 | } 92 | LOGD("Found JLI lib"); 93 | 94 | JLI_Launch_func *pJLI_Launch = 95 | (JLI_Launch_func *)dlsym(libjli, "JLI_Launch"); 96 | // Boardwalk: silence 97 | // LOGD("JLI_Launch = 0x%x", *(int*)&pJLI_Launch); 98 | 99 | if (NULL == pJLI_Launch) { 100 | LOGE("JLI_Launch = NULL"); 101 | return -1; 102 | } 103 | 104 | LOGD("Calling JLI_Launch"); 105 | 106 | return pJLI_Launch(margc, margv, 107 | 0, NULL, // sizeof(const_jargs) / sizeof(char *), const_jargs, 108 | 0, NULL, // sizeof(const_appclasspath) / sizeof(char *), const_appclasspath, 109 | FULL_VERSION, 110 | DOT_VERSION, 111 | *margv, // (const_progname != NULL) ? const_progname : *margv, 112 | *margv, // (const_launcher != NULL) ? const_launcher : *margv, 113 | (const_jargs != NULL) ? JNI_TRUE : JNI_FALSE, 114 | const_cpwildcard, const_javaw, const_ergo_class); 115 | } 116 | 117 | /* 118 | * Class: com_oracle_dalvik_VMLauncher 119 | * Method: launchJVM 120 | * Signature: ([Ljava/lang/String;)I 121 | */ 122 | JNIEXPORT jint JNICALL Java_com_oracle_dalvik_VMLauncher_launchJVM(JNIEnv *env, jclass clazz, jobjectArray argsArray) { 123 | #ifdef TRY_SIG2JVM 124 | void* libjvm = dlopen("libjvm.so", RTLD_LAZY | RTLD_GLOBAL); 125 | if (NULL == libjvm) { 126 | LOGE("JVM lib = NULL: %s", dlerror()); 127 | return -1; 128 | } 129 | JVM_handle_linux_signal = dlsym(libjvm, "JVM_handle_linux_signal"); 130 | #endif 131 | 132 | jint res = 0; 133 | // int i; 134 | //Prepare the signal trapper 135 | struct sigaction catcher; 136 | memset(&catcher,0,sizeof(sigaction)); 137 | catcher.sa_sigaction = android_sigaction; 138 | catcher.sa_flags = SA_SIGINFO|SA_RESTART; 139 | // SA_RESETHAND; 140 | #define CATCHSIG(X) sigaction(X, &catcher, &old_sa[X]) 141 | CATCHSIG(SIGILL); 142 | CATCHSIG(SIGABRT); 143 | CATCHSIG(SIGBUS); 144 | CATCHSIG(SIGFPE); 145 | #ifdef TRY_SIG2JVM 146 | CATCHSIG(SIGSEGV); 147 | #endif 148 | CATCHSIG(SIGSTKFLT); 149 | CATCHSIG(SIGPIPE); 150 | CATCHSIG(SIGXFSZ); 151 | //Signal trapper ready 152 | 153 | // Save dalvik JNIEnv pointer for JVM launch thread 154 | dalvikJNIEnvPtr_ANDROID = env; 155 | 156 | if (argsArray == NULL) { 157 | LOGE("Args array null, returning"); 158 | //handle error 159 | return 0; 160 | } 161 | 162 | int argc = (*env)->GetArrayLength(env, argsArray); 163 | char **argv = convert_to_char_array(env, argsArray); 164 | 165 | LOGD("Done processing args"); 166 | 167 | res = launchJVM(argc, argv); 168 | 169 | LOGD("Going to free args"); 170 | free_char_array(env, argsArray, argv); 171 | 172 | LOGD("Free done"); 173 | 174 | return res; 175 | } 176 | -------------------------------------------------------------------------------- /src/main/jni/libopenxr_loader.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:547bc81d961b6830c6e2e6d19fb417cf583ebcba0819bb26f84d9fbabf8acb97 3 | size 1583672 4 | -------------------------------------------------------------------------------- /src/main/jni/log.h: -------------------------------------------------------------------------------- 1 | #ifdef __ANDROID__ 2 | #include 3 | 4 | #define TAG "jrelog" 5 | #endif 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define LOGE(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) 12 | #define LOGW(...) __android_log_print(ANDROID_LOG_SILENT, TAG, __VA_ARGS__) 13 | #define LOGI(...) __android_log_print(ANDROID_LOG_SILENT, TAG, __VA_ARGS__) 14 | #define LOGD(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /src/main/jni/openxr/openxr_loader_negotiation.h: -------------------------------------------------------------------------------- 1 | #ifndef OPENXR_LOADER_NEGOTIATION_H_ 2 | #define OPENXR_LOADER_NEGOTIATION_H_ 1 3 | 4 | /* 5 | ** Copyright 2017-2024, The Khronos Group Inc. 6 | ** 7 | ** SPDX-License-Identifier: Apache-2.0 OR MIT 8 | */ 9 | 10 | /* 11 | ** This header is generated from the Khronos OpenXR XML API Registry. 12 | ** 13 | */ 14 | 15 | #include "openxr.h" 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | 23 | // XR_LOADER_VERSION_1_0 is a preprocessor guard. Do not pass it to API calls. 24 | #define XR_LOADER_VERSION_1_0 1 25 | 26 | #define XR_CURRENT_LOADER_API_LAYER_VERSION 1 27 | 28 | 29 | #define XR_CURRENT_LOADER_RUNTIME_VERSION 1 30 | 31 | 32 | #define XR_LOADER_INFO_STRUCT_VERSION 1 33 | 34 | 35 | #define XR_API_LAYER_INFO_STRUCT_VERSION 1 36 | 37 | 38 | #define XR_RUNTIME_INFO_STRUCT_VERSION 1 39 | 40 | 41 | #define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1 42 | 43 | 44 | #define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1 45 | 46 | 47 | #define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512 48 | 49 | 50 | typedef enum XrLoaderInterfaceStructs { 51 | XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0, 52 | XR_LOADER_INTERFACE_STRUCT_LOADER_INFO = 1, 53 | XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST = 2, 54 | XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST = 3, 55 | XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO = 4, 56 | XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO = 5, 57 | XR_LOADER_INTERFACE_STRUCTS_MAX_ENUM = 0x7FFFFFFF 58 | } XrLoaderInterfaceStructs; 59 | typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance instance, const char* name, PFN_xrVoidFunction* function); 60 | 61 | typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo; 62 | typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)( 63 | const XrInstanceCreateInfo* info, 64 | const XrApiLayerCreateInfo* apiLayerInfo, 65 | XrInstance* instance); 66 | 67 | typedef struct XrApiLayerNextInfo { 68 | XrLoaderInterfaceStructs structType; 69 | uint32_t structVersion; 70 | size_t structSize; 71 | char layerName[XR_MAX_API_LAYER_NAME_SIZE]; 72 | PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; 73 | PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; 74 | struct XrApiLayerNextInfo* next; 75 | } XrApiLayerNextInfo; 76 | 77 | typedef struct XrApiLayerCreateInfo { 78 | XrLoaderInterfaceStructs structType; 79 | uint32_t structVersion; 80 | size_t structSize; 81 | void* XR_MAY_ALIAS loaderInstance; 82 | char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; 83 | XrApiLayerNextInfo* nextInfo; 84 | } XrApiLayerCreateInfo; 85 | 86 | typedef struct XrNegotiateLoaderInfo { 87 | XrLoaderInterfaceStructs structType; 88 | uint32_t structVersion; 89 | size_t structSize; 90 | uint32_t minInterfaceVersion; 91 | uint32_t maxInterfaceVersion; 92 | XrVersion minApiVersion; 93 | XrVersion maxApiVersion; 94 | } XrNegotiateLoaderInfo; 95 | 96 | typedef struct XrNegotiateRuntimeRequest { 97 | XrLoaderInterfaceStructs structType; 98 | uint32_t structVersion; 99 | size_t structSize; 100 | uint32_t runtimeInterfaceVersion; 101 | XrVersion runtimeApiVersion; 102 | PFN_xrGetInstanceProcAddr getInstanceProcAddr; 103 | } XrNegotiateRuntimeRequest; 104 | 105 | typedef struct XrNegotiateApiLayerRequest { 106 | XrLoaderInterfaceStructs structType; 107 | uint32_t structVersion; 108 | size_t structSize; 109 | uint32_t layerInterfaceVersion; 110 | XrVersion layerApiVersion; 111 | PFN_xrGetInstanceProcAddr getInstanceProcAddr; 112 | PFN_xrCreateApiLayerInstance createApiLayerInstance; 113 | } XrNegotiateApiLayerRequest; 114 | 115 | typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo* info, const XrApiLayerCreateInfo* layerInfo, XrInstance* instance); 116 | typedef XrResult (XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo* loaderInfo, XrNegotiateRuntimeRequest* runtimeRequest); 117 | typedef XrResult (XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo* loaderInfo, const char* layerName, XrNegotiateApiLayerRequest* apiLayerRequest); 118 | 119 | #ifndef XR_NO_PROTOTYPES 120 | #ifdef XR_EXTENSION_PROTOTYPES 121 | XRAPI_ATTR XrResult XRAPI_CALL xrCreateApiLayerInstance( 122 | const XrInstanceCreateInfo* info, 123 | const XrApiLayerCreateInfo* layerInfo, 124 | XrInstance* instance); 125 | 126 | XRAPI_ATTR XrResult XRAPI_CALL xrNegotiateLoaderRuntimeInterface( 127 | const XrNegotiateLoaderInfo* loaderInfo, 128 | XrNegotiateRuntimeRequest* runtimeRequest); 129 | 130 | XRAPI_ATTR XrResult XRAPI_CALL xrNegotiateLoaderApiLayerInterface( 131 | const XrNegotiateLoaderInfo* loaderInfo, 132 | const char* layerName, 133 | XrNegotiateApiLayerRequest* apiLayerRequest); 134 | #endif /* XR_EXTENSION_PROTOTYPES */ 135 | #endif /* !XR_NO_PROTOTYPES */ 136 | 137 | #ifdef __cplusplus 138 | } 139 | #endif 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /src/main/jni/openxr/openxr_platform_defines.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2017-2024, The Khronos Group Inc. 3 | ** 4 | ** SPDX-License-Identifier: Apache-2.0 OR MIT 5 | */ 6 | 7 | #ifndef OPENXR_PLATFORM_DEFINES_H_ 8 | #define OPENXR_PLATFORM_DEFINES_H_ 1 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /* Platform-specific calling convention macros. 15 | * 16 | * Platforms should define these so that OpenXR clients call OpenXR functions 17 | * with the same calling conventions that the OpenXR implementation expects. 18 | * 19 | * XRAPI_ATTR - Placed before the return type in function declarations. 20 | * Useful for C++11 and GCC/Clang-style function attribute syntax. 21 | * XRAPI_CALL - Placed after the return type in function declarations. 22 | * Useful for MSVC-style calling convention syntax. 23 | * XRAPI_PTR - Placed between the '(' and '*' in function pointer types. 24 | * 25 | * Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void); 26 | * Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void); 27 | */ 28 | #if defined(_WIN32) 29 | #define XRAPI_ATTR 30 | // On Windows, functions use the stdcall convention 31 | #define XRAPI_CALL __stdcall 32 | #define XRAPI_PTR XRAPI_CALL 33 | #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7 34 | #error "API not supported for the 'armeabi' NDK ABI" 35 | #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE) 36 | // On Android 32-bit ARM targets, functions use the "hardfloat" 37 | // calling convention, i.e. float parameters are passed in registers. This 38 | // is true even if the rest of the application passes floats on the stack, 39 | // as it does by default when compiling for the armeabi-v7a NDK ABI. 40 | #define XRAPI_ATTR __attribute__((pcs("aapcs-vfp"))) 41 | #define XRAPI_CALL 42 | #define XRAPI_PTR XRAPI_ATTR 43 | #else 44 | // On other platforms, use the default calling convention 45 | #define XRAPI_ATTR 46 | #define XRAPI_CALL 47 | #define XRAPI_PTR 48 | #endif 49 | 50 | #include 51 | 52 | #if !defined(XR_NO_STDINT_H) 53 | #if defined(_MSC_VER) && (_MSC_VER < 1600) 54 | typedef signed __int8 int8_t; 55 | typedef unsigned __int8 uint8_t; 56 | typedef signed __int16 int16_t; 57 | typedef unsigned __int16 uint16_t; 58 | typedef signed __int32 int32_t; 59 | typedef unsigned __int32 uint32_t; 60 | typedef signed __int64 int64_t; 61 | typedef unsigned __int64 uint64_t; 62 | #else 63 | #include 64 | #endif 65 | #endif // !defined( XR_NO_STDINT_H ) 66 | 67 | // XR_PTR_SIZE (in bytes) 68 | #if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)) 69 | #define XR_PTR_SIZE 8 70 | #else 71 | #define XR_PTR_SIZE 4 72 | #endif 73 | 74 | // Needed so we can use clang __has_feature portably. 75 | #if !defined(XR_COMPILER_HAS_FEATURE) 76 | #if defined(__clang__) 77 | #define XR_COMPILER_HAS_FEATURE(x) __has_feature(x) 78 | #else 79 | #define XR_COMPILER_HAS_FEATURE(x) 0 80 | #endif 81 | #endif 82 | 83 | // Identifies if the current compiler has C++11 support enabled. 84 | // Does not by itself identify if any given C++11 feature is present. 85 | #if !defined(XR_CPP11_ENABLED) && defined(__cplusplus) 86 | #if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) 87 | #define XR_CPP11_ENABLED 1 88 | #elif defined(_MSC_VER) && (_MSC_VER >= 1600) 89 | #define XR_CPP11_ENABLED 1 90 | #elif (__cplusplus >= 201103L) // 201103 is the first C++11 version. 91 | #define XR_CPP11_ENABLED 1 92 | #endif 93 | #endif 94 | 95 | // Identifies if the current compiler supports C++11 nullptr. 96 | #if !defined(XR_CPP_NULLPTR_SUPPORTED) 97 | #if defined(XR_CPP11_ENABLED) && \ 98 | ((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \ 99 | (defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \ 100 | (defined(_MSC_VER) && (_MSC_VER >= 1600)) || \ 101 | (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403))) 102 | #define XR_CPP_NULLPTR_SUPPORTED 1 103 | #endif 104 | #endif 105 | 106 | #if !defined(XR_CPP_NULLPTR_SUPPORTED) 107 | #define XR_CPP_NULLPTR_SUPPORTED 0 108 | #endif // !defined(XR_CPP_NULLPTR_SUPPORTED) 109 | 110 | #ifdef __cplusplus 111 | } 112 | #endif 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /src/main/jni/stdio_is.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // 9 | // Created by maks on 17.02.21. 10 | // 11 | static JavaVM *_______jvm; 12 | static volatile jmethodID _______method; 13 | static volatile jobject _______obj; 14 | static int pfd[2]; 15 | static pthread_t logger; 16 | static void *logger_thread() { 17 | JNIEnv *env; 18 | jstring str; 19 | (*_______jvm)->AttachCurrentThread(_______jvm,&env,NULL); 20 | ssize_t rsize; 21 | char buf[2048]; 22 | while((rsize = read(pfd[0], buf, sizeof(buf)-1)) > 0) { 23 | if(buf[rsize-1]=='\n') { 24 | rsize=rsize-1; 25 | } 26 | buf[rsize]=0x00; 27 | str = (*env)->NewStringUTF(env,buf); 28 | (*env)->CallVoidMethod(env,_______obj,_______method,str); 29 | (*env)->DeleteLocalRef(env,str); 30 | } 31 | (*env)->DeleteGlobalRef(env,_______method); 32 | (*env)->DeleteGlobalRef(env,_______obj); 33 | (*_______jvm)->DetachCurrentThread(_______jvm); 34 | } 35 | JNIEXPORT void JNICALL 36 | Java_pojlib_util_JREUtils_logToLogger(JNIEnv *env, jclass clazz, jobject javaLogger) { 37 | // TODO: implement logToActivity() 38 | jclass loggableActivityClass = (*env)->FindClass(env,"pojlib/util/Logger"); 39 | _______method = (*env)->GetMethodID(env,loggableActivityClass,"appendToLog", "(Ljava/lang/String;)V"); 40 | (*env)->GetJavaVM(env,&_______jvm); 41 | _______obj = (*env)->NewGlobalRef(env, javaLogger); 42 | 43 | setvbuf(stdout, 0, _IOLBF, 0); // make stdout line-buffered 44 | setvbuf(stderr, 0, _IONBF, 0); // make stderr unbuffered 45 | 46 | /* create the pipe and redirect stdout and stderr */ 47 | pipe(pfd); 48 | dup2(pfd[1], 1); 49 | dup2(pfd[1], 2); 50 | 51 | /* spawn the logging thread */ 52 | if(pthread_create(&logger, 0, logger_thread, 0) == -1) { 53 | jstring str = (*env)->NewStringUTF(env,"Failed to start logging!"); 54 | (*env)->CallVoidMethod(env,_______obj,_______method,str); 55 | (*env)->DeleteLocalRef(env,str); 56 | (*env)->DeleteGlobalRef(env,_______method); 57 | (*env)->DeleteGlobalRef(env,_______obj); 58 | } 59 | pthread_detach(logger); 60 | 61 | } -------------------------------------------------------------------------------- /src/main/jni/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "log.h" 8 | 9 | #include "utils.h" 10 | 11 | typedef int (*Main_Function_t)(int, char**); 12 | typedef void (*android_update_LD_LIBRARY_PATH_t)(char*); 13 | 14 | char** convert_to_char_array(JNIEnv *env, jobjectArray jstringArray) { 15 | int num_rows = (*env)->GetArrayLength(env, jstringArray); 16 | char **cArray = (char **) malloc(num_rows * sizeof(char*)); 17 | jstring row; 18 | 19 | for (int i = 0; i < num_rows; i++) { 20 | row = (jstring) (*env)->GetObjectArrayElement(env, jstringArray, i); 21 | cArray[i] = (char*)(*env)->GetStringUTFChars(env, row, 0); 22 | } 23 | 24 | return cArray; 25 | } 26 | 27 | void free_char_array(JNIEnv *env, jobjectArray jstringArray, const char **charArray) { 28 | int num_rows = (*env)->GetArrayLength(env, jstringArray); 29 | jstring row; 30 | 31 | for (int i = 0; i < num_rows; i++) { 32 | row = (jstring) (*env)->GetObjectArrayElement(env, jstringArray, i); 33 | (*env)->ReleaseStringUTFChars(env, row, charArray[i]); 34 | } 35 | } 36 | 37 | jstring convertStringJVM(JNIEnv* srcEnv, JNIEnv* dstEnv, jstring srcStr) { 38 | if (srcStr == NULL) { 39 | return NULL; 40 | } 41 | 42 | const char* srcStrC = (*srcEnv)->GetStringUTFChars(srcEnv, srcStr, 0); 43 | jstring dstStr = (*dstEnv)->NewStringUTF(dstEnv, srcStrC); 44 | (*srcEnv)->ReleaseStringUTFChars(srcEnv, srcStr, srcStrC); 45 | return dstStr; 46 | } 47 | 48 | JNIEXPORT jint JNICALL Java_android_os_OpenJDKNativeRegister_nativeRegisterNatives(JNIEnv *env, jclass clazz, jstring registerSymbol) { 49 | const char *register_symbol_c = (*env)->GetStringUTFChars(env, registerSymbol, 0); 50 | void *symbol = dlsym(RTLD_DEFAULT, register_symbol_c); 51 | if (symbol == NULL) { 52 | printf("dlsym %s failed: %s\n", register_symbol_c, dlerror()); 53 | return -1; 54 | } 55 | 56 | int (*registerNativesForClass)(JNIEnv*) = symbol; 57 | int result = registerNativesForClass(env); 58 | (*env)->ReleaseStringUTFChars(env, registerSymbol, register_symbol_c); 59 | 60 | return (jint) result; 61 | } 62 | 63 | JNIEXPORT void JNICALL Java_pojlib_util_JREUtils_setLdLibraryPath(JNIEnv *env, jclass clazz, jstring ldLibraryPath) { 64 | android_update_LD_LIBRARY_PATH_t android_update_LD_LIBRARY_PATH; 65 | 66 | void *libdl_handle = dlopen("libdl.so", RTLD_LAZY); 67 | void *updateLdLibPath = dlsym(libdl_handle, "android_update_LD_LIBRARY_PATH"); 68 | if (updateLdLibPath == NULL) { 69 | updateLdLibPath = dlsym(libdl_handle, "__loader_android_update_LD_LIBRARY_PATH"); 70 | if (updateLdLibPath == NULL) { 71 | char *dl_error_c = dlerror(); 72 | LOGE("Error getting symbol android_update_LD_LIBRARY_PATH: %s", dl_error_c); 73 | } 74 | } 75 | 76 | android_update_LD_LIBRARY_PATH = (android_update_LD_LIBRARY_PATH_t) updateLdLibPath; 77 | const char* ldLibPathUtf = (*env)->GetStringUTFChars(env, ldLibraryPath, 0); 78 | android_update_LD_LIBRARY_PATH(ldLibPathUtf); 79 | (*env)->ReleaseStringUTFChars(env, ldLibraryPath, ldLibPathUtf); 80 | } 81 | 82 | JNIEXPORT jboolean JNICALL Java_pojlib_util_JREUtils_dlopen(JNIEnv *env, jclass clazz, jstring name) { 83 | const char *nameUtf = (*env)->GetStringUTFChars(env, name, 0); 84 | void* handle = dlopen(nameUtf, RTLD_GLOBAL | RTLD_LAZY); 85 | if (!handle) { 86 | LOGE("dlopen %s failed: %s", nameUtf, dlerror()); 87 | } else { 88 | LOGD("dlopen %s success", nameUtf); 89 | } 90 | (*env)->ReleaseStringUTFChars(env, name, nameUtf); 91 | return handle != NULL; 92 | } 93 | 94 | JNIEXPORT jint JNICALL Java_pojlib_util_JREUtils_chdir(JNIEnv *env, jclass clazz, jstring nameStr) { 95 | const char *name = (*env)->GetStringUTFChars(env, nameStr, NULL); 96 | int retval = chdir(name); 97 | (*env)->ReleaseStringUTFChars(env, nameStr, name); 98 | return retval; 99 | } 100 | 101 | JNIEXPORT jint JNICALL Java_pojlib_util_JREUtils_executeBinary(JNIEnv *env, jclass clazz, jobjectArray cmdArgs) { 102 | jclass exception_cls = (*env)->FindClass(env, "java/lang/UnsatisfiedLinkError"); 103 | jstring execFile = (*env)->GetObjectArrayElement(env, cmdArgs, 0); 104 | 105 | char *exec_file_c = (char*) (*env)->GetStringUTFChars(env, execFile, 0); 106 | void *exec_binary_handle = dlopen(exec_file_c, RTLD_LAZY); 107 | 108 | (*env)->ReleaseStringUTFChars(env, execFile, exec_file_c); 109 | 110 | char *exec_error_c = dlerror(); 111 | if (exec_error_c != NULL) { 112 | LOGE("Error: %s", exec_error_c); 113 | (*env)->ThrowNew(env, exception_cls, exec_error_c); 114 | return -1; 115 | } 116 | 117 | Main_Function_t Main_Function; 118 | Main_Function = (Main_Function_t) dlsym(exec_binary_handle, "main"); 119 | 120 | exec_error_c = dlerror(); 121 | if (exec_error_c != NULL) { 122 | LOGE("Error: %s", exec_error_c); 123 | (*env)->ThrowNew(env, exception_cls, exec_error_c); 124 | return -1; 125 | } 126 | 127 | int cmd_argv = (*env)->GetArrayLength(env, cmdArgs); 128 | char **cmd_args_c = convert_to_char_array(env, cmdArgs); 129 | int result = Main_Function(cmd_argv, cmd_args_c); 130 | free_char_array(env, cmdArgs, cmd_args_c); 131 | return result; 132 | } 133 | 134 | -------------------------------------------------------------------------------- /src/main/jni/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | static JavaVM* runtimeJavaVMPtr; 6 | static JNIEnv* runtimeJNIEnvPtr_ANDROID; 7 | static JNIEnv* runtimeJNIEnvPtr_JRE; 8 | 9 | static JavaVM* dalvikJavaVMPtr; 10 | static JNIEnv* dalvikJNIEnvPtr_ANDROID; 11 | static JNIEnv* dalvikJNIEnvPtr_JRE; 12 | 13 | static long showingWindow; 14 | 15 | static bool isInputReady, isCursorEntered, isPrepareGrabPos, isUseStackQueueCall; 16 | 17 | static int savedWidth, savedHeight; 18 | 19 | jboolean attachThread(bool isAndroid, JNIEnv** secondJNIEnvPtr); 20 | char** convert_to_char_array(JNIEnv *env, jobjectArray jstringArray); 21 | jobjectArray convert_from_char_array(JNIEnv *env, char **charArray, int num_rows); 22 | void free_char_array(JNIEnv *env, jobjectArray jstringArray, const char **charArray); 23 | jstring convertStringJVM(JNIEnv* srcEnv, JNIEnv* dstEnv, jstring srcStr); 24 | 25 | void hookExec(); 26 | void installLinkerBugMitigation(); 27 | void installEMUIIteratorMititgation(); 28 | JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jbyteArray copySrc); -------------------------------------------------------------------------------- /src/main/jni/vloader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Judge on 12/23/2021. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "log.h" 18 | 19 | extern "C" 20 | JNIEXPORT jlong JNICALL 21 | Java_org_vivecraft_util_VLoader_getEGLDisplay(JNIEnv* env, jclass clazz) { 22 | return reinterpret_cast(eglGetCurrentDisplay()); 23 | } 24 | 25 | extern "C" 26 | JNIEXPORT jlong JNICALL 27 | Java_org_vivecraft_util_VLoader_getEGLContext(JNIEnv* env, jclass clazz) { 28 | return reinterpret_cast(eglGetCurrentContext()); 29 | } 30 | 31 | extern "C" 32 | JNIEXPORT jlong JNICALL 33 | Java_org_vivecraft_util_VLoader_getEGLConfig(JNIEnv* env, jclass clazz) { 34 | EGLConfig cfg; 35 | EGLint num_configs; 36 | 37 | static const EGLint attribs[] = { 38 | EGL_RED_SIZE, 8, 39 | EGL_GREEN_SIZE, 8, 40 | EGL_BLUE_SIZE, 8, 41 | EGL_ALPHA_SIZE, 8, 42 | // Minecraft required on initial 24 43 | EGL_DEPTH_SIZE, 24, 44 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, 45 | EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 46 | EGL_NONE 47 | }; 48 | 49 | eglChooseConfig(eglGetCurrentDisplay(), attribs, &cfg, 1, &num_configs); 50 | return reinterpret_cast(cfg); 51 | } 52 | 53 | extern "C" 54 | JNIEXPORT jlong JNICALL 55 | Java_org_vivecraft_util_VLoader_getDalvikVM(JNIEnv* env, jclass clazz) { 56 | return reinterpret_cast(pojav_environ->dalvikJavaVMPtr); 57 | } 58 | 59 | extern "C" 60 | JNIEXPORT jlong JNICALL 61 | Java_org_vivecraft_util_VLoader_getDalvikActivity(JNIEnv* env, jclass clazz) { 62 | return reinterpret_cast(pojav_environ->activity); 63 | } 64 | 65 | extern "C" 66 | JNIEXPORT void JNICALL 67 | Java_org_vivecraft_util_VLoader_setupAndroid(JNIEnv* env, jclass clazz) { 68 | JNIEnv *newEnv; 69 | pojav_environ->dalvikJavaVMPtr->AttachCurrentThread(&newEnv, NULL); 70 | jclass apiClass = pojav_environ->apiClass; 71 | jfieldID fieldID = newEnv->GetStaticFieldID(apiClass, "gameReady", "Z"); 72 | newEnv->SetStaticBooleanField(apiClass, fieldID, true); 73 | } 74 | 75 | extern "C" 76 | JNIEXPORT void JNICALL 77 | Java_pojlib_util_VLoader_setAndroidInitInfo(JNIEnv *env, jclass clazz, jobject ctx) { 78 | pojav_environ->activity = env->NewGlobalRef(ctx); 79 | } -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/libjnidispatch.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:96ea410702b52fb37ff219e7a5faba41945b17e95aa11193dee0c95003aa4996 3 | size 168176 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/libltw.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f495e7827cc5ffb5d50c2c32b9df735089cff8475662ca32bd41c239784737ee 3 | size 1633600 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7cd38e1550505f47a941476a8ba8be0e2341822d1d66309fc7c8afb8b6ab5c37 3 | size 495456 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl_lmdb.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:990c87ca3e8b6895a8b8b4994bca5b3bc9f7652253bc35160270683134f1bf35 3 | size 88040 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl_nanovg.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c599b785f8d871635a53c17efdf0c3e47a7135af4bf79f1a58fc82d319ab346c 3 | size 351376 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl_opengl.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2e5b83ed440507a928306f955db73d48261a33d55f131d665df329ecb7b664e7 3 | size 360280 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl_opengles.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:437f171d392ba1d8153ba4a53d4e81cc9e5c8f89f4a70e9b26d97472cf3bd398 3 | size 149144 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl_openvr.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4bda7698fcb065a5bd9d43f6132b333431c176a1c4ee73366d06b30418c13c5c 3 | size 5552 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl_stb.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fbc9fb88310268f14150734a360c4e1839bd2bf81245d67b2bd4b38e63f43c46 3 | size 347408 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/liblwjgl_tinyfd.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0da99be886e3b7f22f36616ea3425a512cf5ebdeceb40ff250ef1efb427d7f43 3 | size 81912 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/libopenal.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2d218342fd1cb08080d708a8a4104b69cfc1209b47773bf41e9bb9126cb9ef8e 3 | size 15914936 4 | -------------------------------------------------------------------------------- /src/main/jniLibs/arm64-v8a/libsqlitejdbc.so: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ef6d472ec0713a6e457804e33c605d797729bc02cc859dab7f7b1bd01be170c2 3 | size 1144552 4 | -------------------------------------------------------------------------------- /supportedVersions.json: -------------------------------------------------------------------------------- 1 | { 2 | "supportedVersions": [ 3 | "1.21.5", 4 | "1.21.4", 5 | "1.21.1", 6 | "1.20.6", 7 | "1.20.4", 8 | "1.20.1", 9 | "1.19.4", 10 | "1.19.2" 11 | ] 12 | } 13 | --------------------------------------------------------------------------------