├── .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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | true
19 | true
20 | false
21 | false
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
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 | [](https://www.gnu.org/licenses/gpl-3.0)
3 | [](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 | acceptTextures ip mc.xrcraftmc.com name &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 extends ZipEntry> 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 extends ZipEntry> 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 |
--------------------------------------------------------------------------------