mirror of
https://github.com/2009scape/2009Scape-mobile.git
synced 2025-12-21 09:01:56 -07:00
Merge
This commit is contained in:
commit
21cfe0515a
110 changed files with 1490 additions and 780 deletions
26
README.md
26
README.md
|
|
@ -10,13 +10,13 @@
|
||||||
---------
|
---------
|
||||||
* From [Boardwalk](https://github.com/zhuowei/Boardwalk)'s ashes here comes PojavLauncher!
|
* From [Boardwalk](https://github.com/zhuowei/Boardwalk)'s ashes here comes PojavLauncher!
|
||||||
|
|
||||||
* PojavLauncher is a launcher that allows you to play Minecraft:Java Edition on your Android device!
|
* PojavLauncher is a launcher that allows you to play Minecraft: Java Edition on your Android device!
|
||||||
|
|
||||||
* It can run almost every version of the Minecraft, allowing you to use .jar only installers to install modloaders like [forge](https://files.minecraftforge.net/), [fabric](http://fabricmc.net/), [optifine](https://optifine.net); Utility and hack clients like [LabyMod](https://www.labymod.net/en), [Wurst](https://www.wurstclient.net/) and much more!
|
* It can run almost every version of the Minecraft, allowing you to use .jar only installers to install modloaders like [forge](https://files.minecraftforge.net/), [fabric](http://fabricmc.net/), [optifine](https://optifine.net); Utility and hack clients like [LabyMod](https://www.labymod.net/en), [Wurst](https://www.wurstclient.net/) and much more!
|
||||||
|
|
||||||
* For more details [check out our wiki](https://github.com/PojavLauncherTeam/PojavLauncher/wiki)
|
* For more details [check out our wiki](https://github.com/PojavLauncherTeam/PojavLauncher/wiki)
|
||||||
## Some notes to start with
|
## Some notes to start with
|
||||||
- We do not exist on TikTok. No one from the dev team makes TikTok videos.
|
- We do not have an official TikTok account. No one from the dev team makes TikTok videos.
|
||||||
- The official Twitter for PojavLauncher is [@PLaunchTeam](https://twitter.com/PLaunchTeam). Any others (most notably @PojavLauncher) are fake, please report them to Twitter's moderation team.
|
- The official Twitter for PojavLauncher is [@PLaunchTeam](https://twitter.com/PLaunchTeam). Any others (most notably @PojavLauncher) are fake, please report them to Twitter's moderation team.
|
||||||
|
|
||||||
## Navigation
|
## Navigation
|
||||||
|
|
@ -37,21 +37,21 @@
|
||||||
|
|
||||||
## Getting PojavLauncher
|
## Getting PojavLauncher
|
||||||
|
|
||||||
Getting PojavLauncher is divided into 3 parts.
|
You can get PojavLauncher via three methods:
|
||||||
|
|
||||||
1. You can get prebuilt app from [stable releases](https://github.com/PojavLauncherTeam/PojavLauncher/releases) or [automatic builds](https://github.com/PojavLauncherTeam/PojavLauncher/actions).
|
1. You can get the prebuilt app from [stable releases](https://github.com/PojavLauncherTeam/PojavLauncher/releases) or [automatic builds](https://github.com/PojavLauncherTeam/PojavLauncher/actions).
|
||||||
|
|
||||||
2. You can get it from Google Play by clicking:
|
2. You can get it from Google Play by clicking on this badge:
|
||||||
[](https://play.google.com/store/apps/details?id=net.kdt.pojavlaunch)
|
[](https://play.google.com/store/apps/details?id=net.kdt.pojavlaunch)
|
||||||
|
|
||||||
3. You can [build](#building) from source.
|
3. You can [build](#building) from source.
|
||||||
## Building
|
## Building
|
||||||
If you want to build after launcher code changes, follow the steps below.
|
If you want to build from source code, follow the steps below.
|
||||||
### Java Runtime Environment (JRE)
|
### Java Runtime Environment (JRE)
|
||||||
- JRE for Android is [here](https://github.com/PojavLauncherTeam/openjdk-multiarch-jdk8u), and the build script is [here](https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch).
|
- JRE for Android is [here](https://github.com/PojavLauncherTeam/openjdk-multiarch-jdk8u), and the build script is [here](https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch).
|
||||||
- Follow build instruction on build script [README.md](https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch/blob/buildjre8/README.md).
|
- Follow build instruction on build script [README.md](https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch/blob/buildjre8/README.md).
|
||||||
- You can also get [CI auto builds](https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch/actions) if you are lazy or failing it for some reason.
|
- You can also get [CI auto builds](https://github.com/PojavLauncherTeam/android-openjdk-build-multiarch/actions) if you are lazy or are failing to build it for some reason.
|
||||||
* Either get `jre8-pojav` artifact from auto builds, or do splitting by yourself:</br>
|
* Either get the `jre8-pojav` artifact from auto builds, or split all artifacts by yourself:</br>
|
||||||
- Get JREs for all of 4 supported architectures (arm, arm64, x86, x86_64) </br>
|
- Get JREs for all of 4 supported architectures (arm, arm64, x86, x86_64) </br>
|
||||||
- Split JRE into parts:</br>
|
- Split JRE into parts:</br>
|
||||||
Platform-independent: .jar files, libraries, configs, etc...</br>
|
Platform-independent: .jar files, libraries, configs, etc...</br>
|
||||||
|
|
@ -59,14 +59,14 @@ If you want to build after launcher code changes, follow the steps below.
|
||||||
- Create:</br>
|
- Create:</br>
|
||||||
A file named `universal.tar.xz` with all platform-independent files</br>
|
A file named `universal.tar.xz` with all platform-independent files</br>
|
||||||
4 files named `bin-<arch>.tar.xz` with all platform-dependent files per-architecture</br>
|
4 files named `bin-<arch>.tar.xz` with all platform-dependent files per-architecture</br>
|
||||||
- Put these in `assets/components/jre/` folder</br>
|
- Put these in the `assets/components/jre/` folder</br>
|
||||||
- (If needed) update the Version file with the current date</br>
|
- (If needed) update the Version file with the current date</br>
|
||||||
|
|
||||||
### LWJGL
|
### LWJGL
|
||||||
- **Coming soon**
|
- **Coming soon**
|
||||||
|
|
||||||
### The Launcher
|
### The Launcher
|
||||||
- Because languages are auto added by Crowdin, you need to run language list generator before building. In the project directory, run:
|
- Because languages are auto-added by Crowdin, you need to run the language list generator before building. In the project directory, run:
|
||||||
|
|
||||||
* On Linux, Mac OS:
|
* On Linux, Mac OS:
|
||||||
```
|
```
|
||||||
|
|
@ -87,13 +87,13 @@ Then, run these commands ~~or build using Android Studio~~.
|
||||||
```
|
```
|
||||||
./gradlew :app_pojavlauncher:assembleDebug
|
./gradlew :app_pojavlauncher:assembleDebug
|
||||||
```
|
```
|
||||||
(Replace `gradlew` to `gradlew.bat` if you are building on Windows).
|
(Replace `gradlew` with `gradlew.bat` if you are building on Windows).
|
||||||
|
|
||||||
## Current status
|
## Current status
|
||||||
- [x] ~~OpenJDK 9 Mobile port: ARM32, ARM64, x86, x86_64.~~ Replaced by JRE8.
|
- [x] ~~OpenJDK 9 Mobile port: ARM32, ARM64, x86, x86_64.~~ Replaced by JRE8.
|
||||||
- [x] OpenJDK 8 Mobile port: ARM32, ARM64, x86, x86_64
|
- [x] OpenJDK 8 Mobile port: ARM32, ARM64, x86, x86_64
|
||||||
- [x] OpenJDK 17 Mobile port: ARM32, ARM64, x86, x86_64
|
- [x] OpenJDK 17 Mobile port: ARM32, ARM64, x86, x86_64
|
||||||
- [x] Mod installer headless
|
- [x] Headless mod installer
|
||||||
- [x] Mod installer with GUI. Used `Caciocavallo` project for AWT without X11.
|
- [x] Mod installer with GUI. Used `Caciocavallo` project for AWT without X11.
|
||||||
- [x] OpenGL in OpenJDK environment
|
- [x] OpenGL in OpenJDK environment
|
||||||
- [x] OpenAL (works on most devices)
|
- [x] OpenAL (works on most devices)
|
||||||
|
|
@ -107,7 +107,7 @@ Then, run these commands ~~or build using Android Studio~~.
|
||||||
|
|
||||||
## Known Issues
|
## Known Issues
|
||||||
- Controller mods aren't working.
|
- Controller mods aren't working.
|
||||||
- Random crashes could happen very often on Android 5.x during game load or join world.
|
- Random crashes could happen very often on Android 5.x when loading the game or joining a world.
|
||||||
- With big modpacks textures could be messed up
|
- With big modpacks textures could be messed up
|
||||||
- Probably more, that's why we have a bug tracker ;)
|
- Probably more, that's why we have a bug tracker ;)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ android {
|
||||||
shrinkResources false
|
shrinkResources false
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
signingConfig signingConfigs.customDebug
|
signingConfig signingConfigs.customDebug
|
||||||
|
resValue 'string', 'application_package', 'net.kdt.pojavlaunch.debug'
|
||||||
resValue 'string', 'storageProviderAuthorities', 'net.kdt.pojavlaunch.scoped.gamefolder.debug'
|
resValue 'string', 'storageProviderAuthorities', 'net.kdt.pojavlaunch.scoped.gamefolder.debug'
|
||||||
resValue 'string', 'shareProviderAuthority', 'net.kdt.pojavlaunch.scoped.controlfolder.debug'
|
resValue 'string', 'shareProviderAuthority', 'net.kdt.pojavlaunch.scoped.controlfolder.debug'
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +95,7 @@ android {
|
||||||
// multiDexEnabled = true
|
// multiDexEnabled = true
|
||||||
// debuggable = true
|
// debuggable = true
|
||||||
resValue 'string', 'storageProviderAuthorities', 'net.kdt.pojavlaunch.scoped.gamefolder'
|
resValue 'string', 'storageProviderAuthorities', 'net.kdt.pojavlaunch.scoped.gamefolder'
|
||||||
|
resValue 'string', 'application_package', 'net.kdt.pojavlaunch'
|
||||||
}
|
}
|
||||||
gplay {
|
gplay {
|
||||||
initWith release
|
initWith release
|
||||||
|
|
@ -133,8 +135,8 @@ dependencies {
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.2"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.2"
|
||||||
|
|
||||||
implementation 'com.github.duanhong169:checkerboarddrawable:1.0.2'
|
implementation 'com.github.duanhong169:checkerboarddrawable:1.0.2'
|
||||||
implementation 'com.intuit.sdp:sdp-android:1.1.0'
|
implementation 'com.github.PojavLauncherTeam:portrait-sdp:ed33e89cbc'
|
||||||
implementation 'com.intuit.ssp:ssp-android:1.1.0'
|
implementation 'com.github.PojavLauncherTeam:portrait-ssp:6c02fd739b'
|
||||||
implementation 'com.github.Mathias-Boulay:ExtendedView:1.0.0'
|
implementation 'com.github.Mathias-Boulay:ExtendedView:1.0.0'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,87 +3,106 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="net.kdt.pojavlaunch">
|
package="net.kdt.pojavlaunch">
|
||||||
|
|
||||||
<uses-feature android:glEsVersion="0x00020000"/>
|
<uses-feature android:glEsVersion="0x00020000" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
|
<uses-feature
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
|
android:name="android.hardware.type.pc"
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
android:required="false" />
|
||||||
|
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="28" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="28" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
|
||||||
android:name=".PojavApplication"
|
android:name=".PojavApplication"
|
||||||
android:theme="@style/AppTheme"
|
android:allowBackup="true"
|
||||||
android:label="@string/app_name"
|
android:allowNativeHeapPointerTagging="false"
|
||||||
|
android:appCategory="game"
|
||||||
|
android:hasFragileUserData="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:isGame="true"
|
||||||
|
android:label="@string/app_name"
|
||||||
android:process=":launcher"
|
android:process=":launcher"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
android:hasFragileUserData="true"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:allowNativeHeapPointerTagging="false">
|
android:theme="@style/AppTheme">
|
||||||
|
<activity
|
||||||
|
android:name=".MissingStorageActivity"
|
||||||
|
android:exported="false" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.max_aspect"
|
android:name="android.max_aspect"
|
||||||
android:value="ratio_float"/>
|
android:value="ratio_float" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
android:name=".TestStorageActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTop"
|
|
||||||
android:label="@string/app_short_name"
|
android:label="@string/app_short_name"
|
||||||
android:name=".LauncherActivity">
|
android:launchMode="singleTop">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
<activity android:name=".ImportControlActivity"
|
android:name=".LauncherActivity"
|
||||||
android:exported="true"
|
android:label="@string/app_short_name" />
|
||||||
android:windowSoftInputMode="stateVisible"
|
<activity
|
||||||
android:launchMode="singleInstance"
|
android:name=".ImportControlActivity"
|
||||||
android:configChanges="keyboard|keyboardHidden"
|
android:configChanges="keyboard|keyboardHidden"
|
||||||
>
|
android:exported="true"
|
||||||
|
android:launchMode="singleInstance"
|
||||||
<intent-filter android:scheme="content"
|
android:windowSoftInputMode="stateVisible">
|
||||||
|
<intent-filter
|
||||||
android:label="@string/import_control_label"
|
android:label="@string/import_control_label"
|
||||||
|
android:scheme="content"
|
||||||
tools:ignore="AppLinkUrlError">
|
tools:ignore="AppLinkUrlError">
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<action android:name="android.intent.action.SEND"/>
|
<action android:name="android.intent.action.SEND" />
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
|
||||||
<data android:mimeType="application/json"/>
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:mimeType="text/json"/>
|
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="application/json" />
|
||||||
|
<data android:mimeType="text/json" />
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:theme="@style/Theme.AppCompat.DayNight.Dialog"
|
|
||||||
android:screenOrientation="sensorLandscape"
|
|
||||||
android:name=".FatalErrorActivity"
|
android:name=".FatalErrorActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"/>
|
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
|
||||||
|
android:theme="@style/Theme.AppCompat.DayNight.Dialog" />
|
||||||
<activity
|
<activity
|
||||||
android:theme="@style/Theme.AppCompat.DayNight.Dialog"
|
|
||||||
android:screenOrientation="sensorLandscape"
|
|
||||||
android:name=".ExitActivity"
|
android:name=".ExitActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"/>
|
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
|
||||||
|
android:theme="@style/Theme.AppCompat.DayNight.Dialog" />
|
||||||
<activity
|
<activity
|
||||||
android:screenOrientation="sensorLandscape"
|
|
||||||
android:name=".JavaGUILauncherActivity"
|
android:name=".JavaGUILauncherActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"/>
|
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
|
||||||
|
android:screenOrientation="sensorLandscape" />
|
||||||
<activity
|
<activity
|
||||||
android:screenOrientation="sensorLandscape"
|
|
||||||
android:name=".CustomControlsActivity"
|
android:name=".CustomControlsActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"/>
|
android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="sensorLandscape">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name=".CustomControlsActivity" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:process=":game"
|
|
||||||
android:launchMode="standard"
|
|
||||||
android:screenOrientation="sensorLandscape"
|
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation"/>
|
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation|uiMode"
|
||||||
|
android:launchMode="standard"
|
||||||
|
android:process=":game"
|
||||||
|
android:screenOrientation="sensorLandscape" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".scoped.FolderProvider"
|
android:name=".scoped.FolderProvider"
|
||||||
|
|
@ -96,9 +115,10 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<service android:name=".services.ProgressService"/>
|
<service android:name=".services.ProgressService" />
|
||||||
<service android:name=".services.GameService" android:process=":game"/>
|
<service
|
||||||
|
android:name=".services.GameService"
|
||||||
|
android:process=":game" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
HEllo People
|
HEllo PeopLE
|
||||||
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
20220831
|
20230118
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
1668936448354
|
1677612008557
|
||||||
|
|
@ -39,6 +39,8 @@ public class LauncherMenuButton extends ExtendedButton {
|
||||||
setPaddingRelative(padding, 0, 0, 0);
|
setPaddingRelative(padding, 0, 0, 0);
|
||||||
setGravity(Gravity.CENTER_VERTICAL);
|
setGravity(Gravity.CENTER_VERTICAL);
|
||||||
|
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen._12ssp));
|
||||||
|
|
||||||
// Set drawable size
|
// Set drawable size
|
||||||
int[] sizes = getExtendedViewData().getSizeCompounds();
|
int[] sizes = getExtendedViewData().getSizeCompounds();
|
||||||
sizes[0] = resources.getDimensionPixelSize(R.dimen._30sdp);
|
sizes[0] = resources.getDimensionPixelSize(R.dimen._30sdp);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ public class MineButton extends androidx.appcompat.widget.AppCompatButton {
|
||||||
public void init() {
|
public void init() {
|
||||||
setTypeface(ResourcesCompat.getFont(getContext(), R.font.noto_sans_bold));
|
setTypeface(ResourcesCompat.getFont(getContext(), R.font.noto_sans_bold));
|
||||||
setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.mine_button_background, null));
|
setBackground(ResourcesCompat.getDrawable(getResources(), R.drawable.mine_button_background, null));
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen._13ssp));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ public class ProgressLayout extends ConstraintLayout implements View.OnClickList
|
||||||
public static final String DOWNLOAD_VERSION_LIST = "download_verlist";
|
public static final String DOWNLOAD_VERSION_LIST = "download_verlist";
|
||||||
public static final String AUTHENTICATE_MICROSOFT = "authenticate_microsoft";
|
public static final String AUTHENTICATE_MICROSOFT = "authenticate_microsoft";
|
||||||
public static final String INSTALL_MODPACK = "install_modpack";
|
public static final String INSTALL_MODPACK = "install_modpack";
|
||||||
|
public static final String EXTRACT_COMPONENTS = "extract_components";
|
||||||
|
public static final String EXTRACT_SINGLE_FILES = "extract_single_files";
|
||||||
|
|
||||||
public ProgressLayout(@NonNull Context context) {
|
public ProgressLayout(@NonNull Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ package com.kdt.mcgui;
|
||||||
|
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
|
@ -30,11 +29,11 @@ import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.authenticator.listener.DoneListener;
|
import net.kdt.pojavlaunch.authenticator.listener.DoneListener;
|
||||||
import net.kdt.pojavlaunch.authenticator.listener.ErrorListener;
|
import net.kdt.pojavlaunch.authenticator.listener.ErrorListener;
|
||||||
import net.kdt.pojavlaunch.authenticator.listener.ProgressListener;
|
import net.kdt.pojavlaunch.authenticator.listener.ProgressListener;
|
||||||
|
import net.kdt.pojavlaunch.authenticator.microsoft.PresentedException;
|
||||||
import net.kdt.pojavlaunch.authenticator.microsoft.MicrosoftBackgroundLogin;
|
import net.kdt.pojavlaunch.authenticator.microsoft.MicrosoftBackgroundLogin;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraCore;
|
import net.kdt.pojavlaunch.extra.ExtraCore;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraListener;
|
import net.kdt.pojavlaunch.extra.ExtraListener;
|
||||||
import net.kdt.pojavlaunch.services.ProgressService;
|
|
||||||
import net.kdt.pojavlaunch.value.MinecraftAccount;
|
import net.kdt.pojavlaunch.value.MinecraftAccount;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -93,7 +92,12 @@ public class mcAccountSpinner extends AppCompatSpinner implements AdapterView.On
|
||||||
|
|
||||||
private final ErrorListener mErrorListener = errorMessage -> {
|
private final ErrorListener mErrorListener = errorMessage -> {
|
||||||
mLoginBarPaint.setColor(Color.RED);
|
mLoginBarPaint.setColor(Color.RED);
|
||||||
Tools.showError(getContext(), errorMessage);
|
if(errorMessage instanceof PresentedException) {
|
||||||
|
PresentedException exception = (PresentedException) errorMessage;
|
||||||
|
Tools.showError(getContext(), exception.toString(getContext()), exception.getCause());
|
||||||
|
}else {
|
||||||
|
Tools.showError(getContext(), errorMessage);
|
||||||
|
}
|
||||||
invalidate();
|
invalidate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -284,11 +288,16 @@ public class mcAccountSpinner extends AppCompatSpinner implements AdapterView.On
|
||||||
ExtendedTextView view = ((ExtendedTextView) getSelectedView());
|
ExtendedTextView view = ((ExtendedTextView) getSelectedView());
|
||||||
if(view != null){
|
if(view != null){
|
||||||
Bitmap bitmap = mSelectecAccount.getSkinFace();
|
Bitmap bitmap = mSelectecAccount.getSkinFace();
|
||||||
mHeadDrawable = new BitmapDrawable(bitmap);
|
if(bitmap != null) {
|
||||||
mHeadDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
mHeadDrawable = new BitmapDrawable(bitmap);
|
||||||
|
mHeadDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||||
|
|
||||||
view.setCompoundDrawables(mHeadDrawable, null, null, null);
|
view.setCompoundDrawables(mHeadDrawable, null, null, null);
|
||||||
view.postProcessDrawables();
|
view.postProcessDrawables();
|
||||||
|
}else{
|
||||||
|
view.setCompoundDrawables(null, null, null, null);
|
||||||
|
view.postProcessDrawables();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.transition.Slide;
|
import android.transition.Slide;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -74,6 +75,7 @@ public class mcVersionSpinner extends ExtendedTextView {
|
||||||
/** Initialize various behaviors */
|
/** Initialize various behaviors */
|
||||||
private void init(){
|
private void init(){
|
||||||
// Setup various attributes
|
// Setup various attributes
|
||||||
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen._12ssp));
|
||||||
setGravity(Gravity.CENTER_VERTICAL);
|
setGravity(Gravity.CENTER_VERTICAL);
|
||||||
int startPadding = getContext().getResources().getDimensionPixelOffset(R.dimen._17sdp);
|
int startPadding = getContext().getResources().getDimensionPixelOffset(R.dimen._17sdp);
|
||||||
int endPadding = getContext().getResources().getDimensionPixelOffset(R.dimen._5sdp);
|
int endPadding = getContext().getResources().getDimensionPixelOffset(R.dimen._5sdp);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,12 @@ import net.kdt.pojavlaunch.utils.*;
|
||||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_IGNORE_NOTCH;
|
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_IGNORE_NOTCH;
|
||||||
|
|
||||||
public abstract class BaseActivity extends AppCompatActivity {
|
public abstract class BaseActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void attachBaseContext(Context newBase) {
|
||||||
|
super.attachBaseContext(LocaleUtils.setLocale(newBase));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
@ -28,9 +34,19 @@ public abstract class BaseActivity extends AppCompatActivity {
|
||||||
//new Throwable("StartActivity").printStackTrace();
|
//new Throwable("StartActivity").printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if(!Tools.checkStorageRoot(this)) {
|
||||||
|
startActivity(new Intent(this, MissingStorageActivity.class));
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostResume() {
|
protected void onPostResume() {
|
||||||
super.onPostResume();
|
super.onPostResume();
|
||||||
|
Tools.setFullscreen(this, setFullscreen());
|
||||||
Tools.ignoreNotch(PREF_IGNORE_NOTCH,this);
|
Tools.ignoreNotch(PREF_IGNORE_NOTCH,this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ public class CustomControlsActivity extends BaseActivity {
|
||||||
private static void setDefaultControlJson(String path,ControlLayout ctrlLayout) {
|
private static void setDefaultControlJson(String path,ControlLayout ctrlLayout) {
|
||||||
// Load before save to make sure control is not error
|
// Load before save to make sure control is not error
|
||||||
try {
|
try {
|
||||||
ctrlLayout.loadLayout(Tools.GLOBAL_GSON.fromJson(Tools.read(path), CustomControls.class));
|
ctrlLayout.loadLayout(path);
|
||||||
LauncherPreferences.DEFAULT_PREF.edit().putString("defaultCtrl", path).apply();
|
LauncherPreferences.DEFAULT_PREF.edit().putString("defaultCtrl", path).apply();
|
||||||
LauncherPreferences.PREF_DEFAULTCTRL_PATH = path;
|
LauncherPreferences.PREF_DEFAULTCTRL_PATH = path;
|
||||||
} catch (IOException| JsonSyntaxException exception) {
|
} catch (IOException| JsonSyntaxException exception) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
package net.kdt.pojavlaunch;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEvent;
|
||||||
|
import android.hardware.SensorEventListener;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
|
import android.view.OrientationEventListener;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.CallbackBridge;
|
||||||
|
|
||||||
|
public class GyroControl implements SensorEventListener, GrabListener{
|
||||||
|
private final WindowManager mWindowManager;
|
||||||
|
private int mSurfaceRotation;
|
||||||
|
private final SensorManager mSensorManager;
|
||||||
|
private final Sensor mSensor;
|
||||||
|
private final OrientationCorrectionListener mCorrectionListener;
|
||||||
|
private boolean mShouldHandleEvents;
|
||||||
|
private boolean mFirstPass;
|
||||||
|
private float xFactor; // -1 or 1 depending on device orientation
|
||||||
|
private float yFactor;
|
||||||
|
private boolean mSwapXY;
|
||||||
|
|
||||||
|
private final float[] mPreviousRotation = new float[16];
|
||||||
|
private final float[] mCurrentRotation = new float[16];
|
||||||
|
private final float[] mAngleDifference = new float[3];
|
||||||
|
|
||||||
|
public GyroControl(Activity activity) {
|
||||||
|
mWindowManager = activity.getWindowManager();
|
||||||
|
mSurfaceRotation = -10;
|
||||||
|
mSensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
|
||||||
|
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
|
||||||
|
mCorrectionListener = new OrientationCorrectionListener(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enable() {
|
||||||
|
if(mSensor == null) return;
|
||||||
|
mFirstPass = true;
|
||||||
|
mSensorManager.registerListener(this, mSensor, 1000 * LauncherPreferences.PREF_GYRO_SAMPLE_RATE);
|
||||||
|
mCorrectionListener.enable();
|
||||||
|
mShouldHandleEvents = CallbackBridge.isGrabbing();
|
||||||
|
CallbackBridge.addGrabListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
if(mSensor == null) return;
|
||||||
|
mSensorManager.unregisterListener(this);
|
||||||
|
mCorrectionListener.disable();
|
||||||
|
CallbackBridge.removeGrabListener(this);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onSensorChanged(SensorEvent sensorEvent) {
|
||||||
|
if (!mShouldHandleEvents) return;
|
||||||
|
// Copy the old array content
|
||||||
|
System.arraycopy(mCurrentRotation, 0, mPreviousRotation, 0, 16);
|
||||||
|
SensorManager.getRotationMatrixFromVector(mCurrentRotation, sensorEvent.values);
|
||||||
|
|
||||||
|
if(mFirstPass){ // Setup initial position
|
||||||
|
mFirstPass = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SensorManager.getAngleChange(mAngleDifference, mCurrentRotation, mPreviousRotation);
|
||||||
|
|
||||||
|
CallbackBridge.mouseX -= (mAngleDifference[mSwapXY ? 2 : 1] * 1000 * LauncherPreferences.PREF_GYRO_SENSITIVITY * xFactor);
|
||||||
|
CallbackBridge.mouseY += (mAngleDifference[mSwapXY ? 1 : 2] * 1000 * LauncherPreferences.PREF_GYRO_SENSITIVITY * yFactor);
|
||||||
|
CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccuracyChanged(Sensor sensor, int i) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGrabState(boolean isGrabbing) {
|
||||||
|
mFirstPass = true;
|
||||||
|
mShouldHandleEvents = isGrabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
class OrientationCorrectionListener extends OrientationEventListener {
|
||||||
|
|
||||||
|
public OrientationCorrectionListener(Context context) {
|
||||||
|
super(context, SensorManager.SENSOR_DELAY_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOrientationChanged(int i) {
|
||||||
|
// Force to wait to be in game before setting factors
|
||||||
|
// Theoretically, one could use the whole interface in portrait...
|
||||||
|
if(!mShouldHandleEvents) return;
|
||||||
|
int surfaceRotation = mWindowManager.getDefaultDisplay().getRotation();
|
||||||
|
if(surfaceRotation == mSurfaceRotation) return;
|
||||||
|
|
||||||
|
if(i == OrientationEventListener.ORIENTATION_UNKNOWN) {
|
||||||
|
return; //change nothing
|
||||||
|
}
|
||||||
|
mSurfaceRotation = surfaceRotation;
|
||||||
|
|
||||||
|
if((315 < i && i <= 360) || (i < 45) ) {
|
||||||
|
mSwapXY = true;
|
||||||
|
xFactor = 1;
|
||||||
|
yFactor = 1;
|
||||||
|
}else if(45 < i && i < 135) {
|
||||||
|
mSwapXY = false;
|
||||||
|
xFactor = 1;
|
||||||
|
yFactor = -1;
|
||||||
|
}else if(135 < i && i < 225) {
|
||||||
|
mSwapXY = true;
|
||||||
|
xFactor = -1;
|
||||||
|
yFactor = -1;
|
||||||
|
}else if(225 < i && i < 315) {
|
||||||
|
mSwapXY = false;
|
||||||
|
xFactor = -1;
|
||||||
|
yFactor = 1;
|
||||||
|
}
|
||||||
|
if(LauncherPreferences.PREF_GYRO_INVERT_X) xFactor *= -1;
|
||||||
|
if(LauncherPreferences.PREF_GYRO_INVERT_Y) yFactor *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -67,7 +67,11 @@ public class ImportControlActivity extends Activity {
|
||||||
if(!mHasIntentChanged) return;
|
if(!mHasIntentChanged) return;
|
||||||
mIsFileVerified = false;
|
mIsFileVerified = false;
|
||||||
getUriData();
|
getUriData();
|
||||||
mEditText.setText(getNameFromURI(mUriData));
|
if(mUriData == null) {
|
||||||
|
finishAndRemoveTask();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mEditText.setText(trimFileName(Tools.getFileName(this, mUriData)));
|
||||||
mHasIntentChanged = false;
|
mHasIntentChanged = false;
|
||||||
|
|
||||||
//Import and verify thread
|
//Import and verify thread
|
||||||
|
|
@ -189,12 +193,4 @@ public class ImportControlActivity extends Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNameFromURI(Uri uri) {
|
|
||||||
Cursor c = getContentResolver().query(uri, null, null, null, null);
|
|
||||||
c.moveToFirst();
|
|
||||||
String fileName = c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
|
||||||
c.close();
|
|
||||||
return trimFileName(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ public class JMinecraftVersionList {
|
||||||
public String mainClass;
|
public String mainClass;
|
||||||
public String minecraftArguments;
|
public String minecraftArguments;
|
||||||
public int minimumLauncherVersion;
|
public int minimumLauncherVersion;
|
||||||
public DependentLibrary optifineLib;
|
|
||||||
public String releaseTime;
|
public String releaseTime;
|
||||||
public String time;
|
public String time;
|
||||||
public String type;
|
public String type;
|
||||||
|
|
|
||||||
|
|
@ -262,7 +262,7 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
|
||||||
|
|
||||||
// Enable Caciocavallo
|
// Enable Caciocavallo
|
||||||
JREUtils.jreReleaseList = JREUtils.readJREReleaseProperties(LauncherPreferences.PREF_DEFAULT_RUNTIME);
|
JREUtils.jreReleaseList = JREUtils.readJREReleaseProperties(LauncherPreferences.PREF_DEFAULT_RUNTIME);
|
||||||
Tools.getCacioJavaArgs(javaArgList,JREUtils.jreReleaseList.get("JAVA_VERSION").equals("1.8.0"));
|
Tools.getCacioJavaArgs(javaArgList,JREUtils.jreReleaseList.get("JAVA_VERSION").startsWith("1.8.0"));
|
||||||
|
|
||||||
if (javaArgs != null) {
|
if (javaArgs != null) {
|
||||||
javaArgList.addAll(Arrays.asList(javaArgs.split(" ")));
|
javaArgList.addAll(Arrays.asList(javaArgs.split(" ")));
|
||||||
|
|
@ -271,16 +271,18 @@ public class JavaGUILauncherActivity extends BaseActivity implements View.OnTouc
|
||||||
javaArgList.add(modFile.getAbsolutePath());
|
javaArgList.add(modFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (LauncherPreferences.PREF_JAVA_SANDBOX) {
|
||||||
|
Collections.reverse(javaArgList);
|
||||||
|
javaArgList.add("-Xbootclasspath/a:" + Tools.DIR_DATA + "/security/pro-grade.jar");
|
||||||
|
javaArgList.add("-Djava.security.manager=net.sourceforge.prograde.sm.ProGradeJSM");
|
||||||
|
javaArgList.add("-Djava.security.policy=" + Tools.DIR_DATA + "/security/java_sandbox.policy");
|
||||||
|
Collections.reverse(javaArgList);
|
||||||
|
}
|
||||||
|
|
||||||
Logger.getInstance().appendToLog("Info: Java arguments: " + Arrays.toString(javaArgList.toArray(new String[0])));
|
Logger.getInstance().appendToLog("Info: Java arguments: " + Arrays.toString(javaArgList.toArray(new String[0])));
|
||||||
|
|
||||||
// Run java on sandbox, non-overrideable.
|
return JREUtils.launchJavaVM(this, null,javaArgList);
|
||||||
Collections.reverse(javaArgList);
|
|
||||||
javaArgList.add("-Xbootclasspath/a:" + Tools.DIR_DATA + "/security/pro-grade.jar");
|
|
||||||
javaArgList.add("-Djava.security.manager=net.sourceforge.prograde.sm.ProGradeJSM");
|
|
||||||
javaArgList.add("-Djava.security.policy=" + Tools.DIR_DATA + "/security/java_sandbox.policy");
|
|
||||||
Collections.reverse(javaArgList);
|
|
||||||
|
|
||||||
return JREUtils.launchJavaVM(this, javaArgList);
|
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
Tools.showError(this, th, true);
|
Tools.showError(this, th, true);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
package net.kdt.pojavlaunch;
|
package net.kdt.pojavlaunch;
|
||||||
|
|
||||||
import static android.os.Build.VERSION_CODES.P;
|
|
||||||
|
|
||||||
import static net.kdt.pojavlaunch.MainActivity.INTENT_MINECRAFT_VERSION;
|
import static net.kdt.pojavlaunch.MainActivity.INTENT_MINECRAFT_VERSION;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
@ -23,14 +20,10 @@ import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentContainerView;
|
import androidx.fragment.app.FragmentContainerView;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.Lifecycle;
|
|
||||||
import androidx.lifecycle.LifecycleEventObserver;
|
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
|
||||||
|
|
||||||
import com.kdt.mcgui.ProgressLayout;
|
import com.kdt.mcgui.ProgressLayout;
|
||||||
import com.kdt.mcgui.mcAccountSpinner;
|
import com.kdt.mcgui.mcAccountSpinner;
|
||||||
|
|
||||||
import net.kdt.pojavlaunch.fragments.LocalLoginFragment;
|
|
||||||
import net.kdt.pojavlaunch.fragments.MainMenuFragment;
|
import net.kdt.pojavlaunch.fragments.MainMenuFragment;
|
||||||
import net.kdt.pojavlaunch.fragments.MicrosoftLoginFragment;
|
import net.kdt.pojavlaunch.fragments.MicrosoftLoginFragment;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
||||||
|
|
@ -43,14 +36,11 @@ import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
import net.kdt.pojavlaunch.prefs.screens.LauncherPreferenceFragment;
|
import net.kdt.pojavlaunch.prefs.screens.LauncherPreferenceFragment;
|
||||||
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||||
import net.kdt.pojavlaunch.services.ProgressServiceKeeper;
|
import net.kdt.pojavlaunch.services.ProgressServiceKeeper;
|
||||||
import net.kdt.pojavlaunch.tasks.AsyncAssetManager;
|
|
||||||
import net.kdt.pojavlaunch.tasks.AsyncMinecraftDownloader;
|
import net.kdt.pojavlaunch.tasks.AsyncMinecraftDownloader;
|
||||||
import net.kdt.pojavlaunch.tasks.AsyncVersionList;
|
import net.kdt.pojavlaunch.tasks.AsyncVersionList;
|
||||||
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
|
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
|
||||||
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class LauncherActivity extends BaseActivity {
|
public class LauncherActivity extends BaseActivity {
|
||||||
public static final String SETTING_FRAGMENT_TAG = "SETTINGS_FRAGMENT";
|
public static final String SETTING_FRAGMENT_TAG = "SETTINGS_FRAGMENT";
|
||||||
|
|
||||||
|
|
@ -81,10 +71,10 @@ public class LauncherActivity extends BaseActivity {
|
||||||
|
|
||||||
/* Listener for the auth method selection screen */
|
/* Listener for the auth method selection screen */
|
||||||
private final ExtraListener<Boolean> mSelectAuthMethod = (key, value) -> {
|
private final ExtraListener<Boolean> mSelectAuthMethod = (key, value) -> {
|
||||||
if(isFragmentVisible(SelectAuthFragment.TAG)
|
Fragment fragment = getSupportFragmentManager().findFragmentById(mFragmentView.getId());
|
||||||
|| isFragmentVisible(LocalLoginFragment.TAG)
|
// Allow starting the add account only from the main menu, should it be moved to fragment itself ?
|
||||||
|| isFragmentVisible(MicrosoftLoginFragment.TAG)
|
if(!(fragment instanceof MainMenuFragment)) return false;
|
||||||
) return false;
|
|
||||||
Tools.swapFragment(this, SelectAuthFragment.class, SelectAuthFragment.TAG, true, null);
|
Tools.swapFragment(this, SelectAuthFragment.class, SelectAuthFragment.TAG, true, null);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
@ -116,13 +106,12 @@ public class LauncherActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
String selectedProfile = LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE,"");
|
String selectedProfile = LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE,"");
|
||||||
if (LauncherProfiles.mainProfileJson == null || LauncherProfiles.mainProfileJson.profiles == null
|
if (LauncherProfiles.mainProfileJson == null || !LauncherProfiles.mainProfileJson.profiles.containsKey(selectedProfile)){
|
||||||
|| !LauncherProfiles.mainProfileJson.profiles.containsKey(selectedProfile)){
|
|
||||||
Toast.makeText(this, R.string.error_no_version, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.error_no_version, Toast.LENGTH_LONG).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MinecraftProfile prof = LauncherProfiles.mainProfileJson.profiles.get(selectedProfile);
|
MinecraftProfile prof = LauncherProfiles.mainProfileJson.profiles.get(selectedProfile);
|
||||||
if (prof == null || prof.lastVersionId == null){
|
if (prof == null || prof.lastVersionId == null || "Unknown".equals(prof.lastVersionId)){
|
||||||
Toast.makeText(this, R.string.error_no_version, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.error_no_version, Toast.LENGTH_LONG).show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -134,18 +123,28 @@ public class LauncherActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
String normalizedVersionId = AsyncMinecraftDownloader.normalizeVersionId(prof.lastVersionId);
|
String normalizedVersionId = AsyncMinecraftDownloader.normalizeVersionId(prof.lastVersionId);
|
||||||
JMinecraftVersionList.Version mcVersion = AsyncMinecraftDownloader.getListedVersion(normalizedVersionId);
|
JMinecraftVersionList.Version mcVersion = AsyncMinecraftDownloader.getListedVersion(normalizedVersionId);
|
||||||
new AsyncMinecraftDownloader(this, mcVersion, normalizedVersionId, () -> runOnUiThread(() -> {
|
new AsyncMinecraftDownloader(this, mcVersion, normalizedVersionId, new AsyncMinecraftDownloader.DoneListener() {
|
||||||
try {
|
@Override
|
||||||
Intent mainIntent = new Intent(getBaseContext(), MainActivity.class);
|
public void onDownloadDone() {
|
||||||
mainIntent.putExtra(INTENT_MINECRAFT_VERSION, normalizedVersionId);
|
ProgressKeeper.waitUntilDone(()-> runOnUiThread(() -> {
|
||||||
mainIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
try {
|
||||||
startActivity(mainIntent);
|
Intent mainIntent = new Intent(getBaseContext(), MainActivity.class);
|
||||||
finish();
|
mainIntent.putExtra(INTENT_MINECRAFT_VERSION, normalizedVersionId);
|
||||||
android.os.Process.killProcess(android.os.Process.myPid()); //You should kill yourself, NOW!
|
mainIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
} catch (Throwable e) {
|
startActivity(mainIntent);
|
||||||
Tools.showError(getBaseContext(), e);
|
finish();
|
||||||
|
android.os.Process.killProcess(android.os.Process.myPid()); //You should kill yourself, NOW!
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Tools.showError(getBaseContext(), e);
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}));
|
|
||||||
|
@Override
|
||||||
|
public void onDownloadFailed(Throwable th) {
|
||||||
|
if(th != null) Tools.showError(LauncherActivity.this, R.string.mc_download_failed, th);
|
||||||
|
}
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,10 @@ import android.content.res.Configuration;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
|
import android.provider.DocumentsContract;
|
||||||
import android.util.*;
|
import android.util.*;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -44,7 +46,7 @@ import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
||||||
import org.lwjgl.glfw.*;
|
import org.lwjgl.glfw.*;
|
||||||
import android.net.*;
|
import android.net.*;
|
||||||
|
|
||||||
public class MainActivity extends BaseActivity {
|
public class MainActivity extends BaseActivity implements ControlButtonMenuListener{
|
||||||
public static volatile ClipboardManager GLOBAL_CLIPBOARD;
|
public static volatile ClipboardManager GLOBAL_CLIPBOARD;
|
||||||
public static final String INTENT_MINECRAFT_VERSION = "intent_version";
|
public static final String INTENT_MINECRAFT_VERSION = "intent_version";
|
||||||
|
|
||||||
|
|
@ -60,6 +62,7 @@ public class MainActivity extends BaseActivity {
|
||||||
private DrawerLayout drawerLayout;
|
private DrawerLayout drawerLayout;
|
||||||
private ListView navDrawer;
|
private ListView navDrawer;
|
||||||
private View mDrawerPullButton;
|
private View mDrawerPullButton;
|
||||||
|
private GyroControl mGyroControl = null;
|
||||||
public static ControlLayout mControlLayout;
|
public static ControlLayout mControlLayout;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -71,7 +74,7 @@ public class MainActivity extends BaseActivity {
|
||||||
public ArrayAdapter<String> ingameControlsEditorArrayAdapter;
|
public ArrayAdapter<String> ingameControlsEditorArrayAdapter;
|
||||||
public AdapterView.OnItemClickListener ingameControlsEditorListener;
|
public AdapterView.OnItemClickListener ingameControlsEditorListener;
|
||||||
|
|
||||||
protected volatile JMinecraftVersionList.Version mVersionInfo;
|
protected volatile String mVersionId;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
@ -85,6 +88,7 @@ public class MainActivity extends BaseActivity {
|
||||||
initLayout(R.layout.activity_basemain);
|
initLayout(R.layout.activity_basemain);
|
||||||
CallbackBridge.addGrabListener(touchpad);
|
CallbackBridge.addGrabListener(touchpad);
|
||||||
CallbackBridge.addGrabListener(minecraftGLView);
|
CallbackBridge.addGrabListener(minecraftGLView);
|
||||||
|
if(LauncherPreferences.PREF_ENALBE_GYRO) mGyroControl = new GyroControl(this);
|
||||||
|
|
||||||
// Enabling this on TextureView results in a broken white result
|
// Enabling this on TextureView results in a broken white result
|
||||||
if(PREF_USE_ALTERNATE_SURFACE) getWindow().setBackgroundDrawable(null);
|
if(PREF_USE_ALTERNATE_SURFACE) getWindow().setBackgroundDrawable(null);
|
||||||
|
|
@ -116,8 +120,9 @@ public class MainActivity extends BaseActivity {
|
||||||
protected void initLayout(int resId) {
|
protected void initLayout(int resId) {
|
||||||
setContentView(resId);
|
setContentView(resId);
|
||||||
bindValues();
|
bindValues();
|
||||||
|
mControlLayout.setMenuListener(this);
|
||||||
|
|
||||||
mDrawerPullButton.setOnClickListener(v -> drawerLayout.openDrawer(navDrawer));
|
mDrawerPullButton.setOnClickListener(v -> onClickedMenu());
|
||||||
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -147,8 +152,8 @@ public class MainActivity extends BaseActivity {
|
||||||
String version = getIntent().getStringExtra(INTENT_MINECRAFT_VERSION);
|
String version = getIntent().getStringExtra(INTENT_MINECRAFT_VERSION);
|
||||||
version = version == null ? minecraftProfile.lastVersionId : version;
|
version = version == null ? minecraftProfile.lastVersionId : version;
|
||||||
|
|
||||||
mVersionInfo = Tools.getVersionInfo(version);
|
mVersionId = version;
|
||||||
isInputStackCall = mVersionInfo.arguments != null;
|
isInputStackCall = Tools.getVersionInfo(mVersionId).arguments != null;
|
||||||
|
|
||||||
Tools.getDisplayMetrics(this);
|
Tools.getDisplayMetrics(this);
|
||||||
windowWidth = Tools.getDisplayFriendlyRes(currentDisplayMetrics.widthPixels, scaleFactor);
|
windowWidth = Tools.getDisplayFriendlyRes(currentDisplayMetrics.widthPixels, scaleFactor);
|
||||||
|
|
@ -165,7 +170,8 @@ public class MainActivity extends BaseActivity {
|
||||||
case 2: minecraftGLView.togglepointerDebugging(); break;
|
case 2: minecraftGLView.togglepointerDebugging(); break;
|
||||||
case 3: dialogSendCustomKey(); break;
|
case 3: dialogSendCustomKey(); break;
|
||||||
case 4: adjustMouseSpeedLive(); break;
|
case 4: adjustMouseSpeedLive(); break;
|
||||||
case 5: openCustomControls(); break;
|
case 5: adjustGyroSensitivityLive(); break;
|
||||||
|
case 6: openCustomControls(); break;
|
||||||
}
|
}
|
||||||
drawerLayout.closeDrawers();
|
drawerLayout.closeDrawers();
|
||||||
};
|
};
|
||||||
|
|
@ -178,8 +184,9 @@ public class MainActivity extends BaseActivity {
|
||||||
minecraftGLView.setSurfaceReadyListener(() -> {
|
minecraftGLView.setSurfaceReadyListener(() -> {
|
||||||
try {
|
try {
|
||||||
// Setup virtual mouse right before launching
|
// Setup virtual mouse right before launching
|
||||||
if (PREF_VIRTUAL_MOUSE_START)
|
if (PREF_VIRTUAL_MOUSE_START) {
|
||||||
touchpad.switchState();
|
touchpad.post(() -> touchpad.switchState());
|
||||||
|
}
|
||||||
|
|
||||||
runCraft();
|
runCraft();
|
||||||
}catch (Throwable e){
|
}catch (Throwable e){
|
||||||
|
|
@ -210,6 +217,7 @@ public class MainActivity extends BaseActivity {
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
Tools.showError(this, th);
|
Tools.showError(this, th);
|
||||||
}
|
}
|
||||||
|
mDrawerPullButton.setVisibility(mControlLayout.hasMenuButton() ? View.GONE : View.VISIBLE);
|
||||||
mControlLayout.toggleControlVisible();
|
mControlLayout.toggleControlVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,14 +244,13 @@ public class MainActivity extends BaseActivity {
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mIsResuming = true;
|
mIsResuming = true;
|
||||||
final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
if(mGyroControl != null) mGyroControl.enable();
|
||||||
final View decorView = getWindow().getDecorView();
|
|
||||||
decorView.setSystemUiVisibility(uiOptions);
|
|
||||||
CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_HOVERED, 1);
|
CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_HOVERED, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
|
if(mGyroControl != null) mGyroControl.disable();
|
||||||
if (CallbackBridge.isGrabbing()){
|
if (CallbackBridge.isGrabbing()){
|
||||||
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ESCAPE);
|
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ESCAPE);
|
||||||
}
|
}
|
||||||
|
|
@ -326,15 +333,13 @@ public class MainActivity extends BaseActivity {
|
||||||
checkJavaArgsIsLaunchable(JREUtils.jreReleaseList.get("JAVA_VERSION"));
|
checkJavaArgsIsLaunchable(JREUtils.jreReleaseList.get("JAVA_VERSION"));
|
||||||
// appendlnToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\"");
|
// appendlnToLog("Info: Custom Java arguments: \"" + LauncherPreferences.PREF_CUSTOM_JAVA_ARGS + "\"");
|
||||||
|
|
||||||
Logger.getInstance().appendToLog("Info: Selected Minecraft version: " + mVersionInfo.id +
|
Logger.getInstance().appendToLog("Info: Selected Minecraft version: " + mVersionId);
|
||||||
((mVersionInfo.inheritsFrom == null || mVersionInfo.inheritsFrom.equals(mVersionInfo.id)) ?
|
|
||||||
"" : " (" + mVersionInfo.inheritsFrom + ")"));
|
|
||||||
|
|
||||||
|
|
||||||
JREUtils.redirectAndPrintJRELog();
|
JREUtils.redirectAndPrintJRELog();
|
||||||
|
|
||||||
LauncherProfiles.update();
|
LauncherProfiles.update();
|
||||||
Tools.launchMinecraft(this, mProfile, minecraftProfile);
|
Tools.launchMinecraft(this, mProfile, minecraftProfile, mVersionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkJavaArgsIsLaunchable(String jreVersion) throws Throwable {
|
private void checkJavaArgsIsLaunchable(String jreVersion) throws Throwable {
|
||||||
|
|
@ -395,6 +400,7 @@ public class MainActivity extends BaseActivity {
|
||||||
mControlLayout.setModifiable(true);
|
mControlLayout.setModifiable(true);
|
||||||
navDrawer.setAdapter(ingameControlsEditorArrayAdapter);
|
navDrawer.setAdapter(ingameControlsEditorArrayAdapter);
|
||||||
navDrawer.setOnItemClickListener(ingameControlsEditorListener);
|
navDrawer.setOnItemClickListener(ingameControlsEditorListener);
|
||||||
|
mDrawerPullButton.setVisibility(View.VISIBLE);
|
||||||
isInEditor = true;
|
isInEditor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,6 +413,7 @@ public class MainActivity extends BaseActivity {
|
||||||
minecraftProfile.controlFile == null
|
minecraftProfile.controlFile == null
|
||||||
? LauncherPreferences.PREF_DEFAULTCTRL_PATH
|
? LauncherPreferences.PREF_DEFAULTCTRL_PATH
|
||||||
: Tools.CTRLMAP_PATH + "/" + minecraftProfile.controlFile);
|
: Tools.CTRLMAP_PATH + "/" + minecraftProfile.controlFile);
|
||||||
|
mDrawerPullButton.setVisibility(mControlLayout.hasMenuButton() ? View.GONE : View.VISIBLE);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Tools.showError(this,e);
|
Tools.showError(this,e);
|
||||||
}
|
}
|
||||||
|
|
@ -505,16 +512,99 @@ public class MainActivity extends BaseActivity {
|
||||||
b.show();
|
b.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tmpGyroSensitivity;
|
||||||
|
public void adjustGyroSensitivityLive() {
|
||||||
|
if(!LauncherPreferences.PREF_ENALBE_GYRO) {
|
||||||
|
Toast.makeText(this, R.string.toast_turn_on_gyro, Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AlertDialog.Builder b = new AlertDialog.Builder(this);
|
||||||
|
b.setTitle(R.string.preference_gyro_sensitivity_title);
|
||||||
|
View v = LayoutInflater.from(this).inflate(R.layout.dialog_live_mouse_speed_editor,null);
|
||||||
|
final SeekBar sb = v.findViewById(R.id.mouseSpeed);
|
||||||
|
final TextView tv = v.findViewById(R.id.mouseSpeedTV);
|
||||||
|
sb.setMax(275);
|
||||||
|
tmpGyroSensitivity = (int) ((LauncherPreferences.PREF_GYRO_SENSITIVITY*100));
|
||||||
|
sb.setProgress(tmpGyroSensitivity -25);
|
||||||
|
tv.setText(tmpGyroSensitivity +" %");
|
||||||
|
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
|
||||||
|
tmpGyroSensitivity = i+25;
|
||||||
|
tv.setText(tmpGyroSensitivity +" %");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {}
|
||||||
|
});
|
||||||
|
b.setView(v);
|
||||||
|
b.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
||||||
|
LauncherPreferences.PREF_GYRO_SENSITIVITY = ((float) tmpGyroSensitivity)/100f;
|
||||||
|
LauncherPreferences.DEFAULT_PREF.edit().putInt("gyroSensitivity", tmpGyroSensitivity).commit();
|
||||||
|
dialogInterface.dismiss();
|
||||||
|
System.gc();
|
||||||
|
});
|
||||||
|
b.setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> {
|
||||||
|
dialogInterface.dismiss();
|
||||||
|
System.gc();
|
||||||
|
});
|
||||||
|
b.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setUri(Context context, String input, Intent intent) {
|
||||||
|
if(input.startsWith("file:")) {
|
||||||
|
int truncLength = 5;
|
||||||
|
if(input.startsWith("file://")) truncLength = 7;
|
||||||
|
input = input.substring(truncLength);
|
||||||
|
Log.i("MainActivity", input);
|
||||||
|
boolean isDirectory = new File(input).isDirectory();
|
||||||
|
if(isDirectory) {
|
||||||
|
intent.setType(DocumentsContract.Document.MIME_TYPE_DIR);
|
||||||
|
}else{
|
||||||
|
String type = null;
|
||||||
|
String extension = MimeTypeMap.getFileExtensionFromUrl(input);
|
||||||
|
if(extension != null) type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||||
|
if(type == null) type = "*/*";
|
||||||
|
intent.setType(type);
|
||||||
|
}
|
||||||
|
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
|
intent.setData(DocumentsContract.buildDocumentUri(
|
||||||
|
context.getString(R.string.storageProviderAuthorities), input
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
intent.setDataAndType(Uri.parse(input), "*/*");
|
||||||
|
}
|
||||||
|
|
||||||
public static void openLink(String link) {
|
public static void openLink(String link) {
|
||||||
Context ctx = touchpad.getContext(); // no more better way to obtain a context statically
|
Context ctx = touchpad.getContext(); // no more better way to obtain a context statically
|
||||||
((Activity)ctx).runOnUiThread(() -> {
|
((Activity)ctx).runOnUiThread(() -> {
|
||||||
try {
|
try {
|
||||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setDataAndType(Uri.parse(link.replace("file://", "content://")), "*/*");
|
setUri(ctx, link, intent);
|
||||||
ctx.startActivity(intent);
|
ctx.startActivity(intent);
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
Tools.showError(ctx, th);
|
Tools.showError(ctx, th);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
public static void openPath(String path) {
|
||||||
|
Context ctx = touchpad.getContext(); // no more better way to obtain a context statically
|
||||||
|
((Activity)ctx).runOnUiThread(() -> {
|
||||||
|
try {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
|
intent.setDataAndType(DocumentsContract.buildDocumentUri(ctx.getString(R.string.storageProviderAuthorities), path), "*/*");
|
||||||
|
ctx.startActivity(intent);
|
||||||
|
} catch (Throwable th) {
|
||||||
|
Tools.showError(ctx, th);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClickedMenu() {
|
||||||
|
drawerLayout.openDrawer(navDrawer);
|
||||||
|
navDrawer.requestLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ import org.lwjgl.glfw.CallbackBridge;
|
||||||
* Class dealing with showing minecraft surface and taking inputs to dispatch them to minecraft
|
* Class dealing with showing minecraft surface and taking inputs to dispatch them to minecraft
|
||||||
*/
|
*/
|
||||||
public class MinecraftGLSurface extends View implements GrabListener{
|
public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
Handler uiThreadHandler = new Handler();
|
|
||||||
/* Gamepad object for gamepad inputs, instantiated on need */
|
/* Gamepad object for gamepad inputs, instantiated on need */
|
||||||
private Gamepad mGamepad = null;
|
private Gamepad mGamepad = null;
|
||||||
/* Pointer Debug textview, used to show info about the pointer state */
|
/* Pointer Debug textview, used to show info about the pointer state */
|
||||||
|
|
@ -168,6 +167,7 @@ public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
}else{
|
}else{
|
||||||
TextureView textureView = new TextureView(getContext());
|
TextureView textureView = new TextureView(getContext());
|
||||||
textureView.setOpaque(true);
|
textureView.setOpaque(true);
|
||||||
|
textureView.setAlpha(1.0f);
|
||||||
mSurface = textureView;
|
mSurface = textureView;
|
||||||
|
|
||||||
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
|
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
|
||||||
|
|
@ -388,7 +388,6 @@ public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event for mouse/joystick movements
|
* The event for mouse/joystick movements
|
||||||
* We don't do the gamepad right now.
|
|
||||||
*/
|
*/
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -411,6 +410,10 @@ public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(mouseCursorIndex == -1) return false; // we cant consoom that, theres no mice!
|
if(mouseCursorIndex == -1) return false; // we cant consoom that, theres no mice!
|
||||||
|
|
||||||
|
// Make sure we grabbed the mouse if necessary
|
||||||
|
updateGrabState(CallbackBridge.isGrabbing());
|
||||||
|
|
||||||
switch(event.getActionMasked()) {
|
switch(event.getActionMasked()) {
|
||||||
case MotionEvent.ACTION_HOVER_MOVE:
|
case MotionEvent.ACTION_HOVER_MOVE:
|
||||||
CallbackBridge.mouseX = (event.getX(mouseCursorIndex) * mScaleFactor);
|
CallbackBridge.mouseX = (event.getX(mouseCursorIndex) * mScaleFactor);
|
||||||
|
|
@ -420,7 +423,7 @@ public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
CallbackBridge.DEBUG_STRING.setLength(0);
|
CallbackBridge.DEBUG_STRING.setLength(0);
|
||||||
return true;
|
return true;
|
||||||
case MotionEvent.ACTION_SCROLL:
|
case MotionEvent.ACTION_SCROLL:
|
||||||
CallbackBridge.sendScroll((double) event.getAxisValue(MotionEvent.AXIS_VSCROLL), (double) event.getAxisValue(MotionEvent.AXIS_HSCROLL));
|
CallbackBridge.sendScroll((double) event.getAxisValue(MotionEvent.AXIS_HSCROLL), (double) event.getAxisValue(MotionEvent.AXIS_VSCROLL));
|
||||||
return true;
|
return true;
|
||||||
case MotionEvent.ACTION_BUTTON_PRESS:
|
case MotionEvent.ACTION_BUTTON_PRESS:
|
||||||
return sendMouseButtonUnconverted(event.getActionButton(),true);
|
return sendMouseButtonUnconverted(event.getActionButton(),true);
|
||||||
|
|
@ -634,10 +637,12 @@ public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(200);
|
// Wait until the listener is attached
|
||||||
if(mSurfaceReadyListener != null){
|
while (mSurfaceReadyListener == null){
|
||||||
mSurfaceReadyListener.isReady();
|
Thread.sleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSurfaceReadyListener.isReady();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Tools.showError(getContext(), e, true);
|
Tools.showError(getContext(), e, true);
|
||||||
}
|
}
|
||||||
|
|
@ -646,20 +651,24 @@ public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGrabState(boolean isGrabbing) {
|
public void onGrabState(boolean isGrabbing) {
|
||||||
uiThreadHandler.post(()->updateGrabState(isGrabbing));
|
post(()->updateGrabState(isGrabbing));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGrabState(boolean isGrabbing) {
|
private void updateGrabState(boolean isGrabbing) {
|
||||||
if(MainActivity.isAndroid8OrHigher()) {
|
if(!MainActivity.isAndroid8OrHigher()) return;
|
||||||
if (isGrabbing && !hasPointerCapture()) {
|
|
||||||
|
boolean hasPointerCapture = hasPointerCapture();
|
||||||
|
if(isGrabbing){
|
||||||
|
if(!hasPointerCapture) {
|
||||||
requestFocus();
|
requestFocus();
|
||||||
requestPointerCapture();
|
requestPointerCapture();
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isGrabbing && hasPointerCapture()) {
|
if(hasPointerCapture) {
|
||||||
releasePointerCapture();
|
releasePointerCapture();
|
||||||
clearFocus();
|
clearFocus();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -670,5 +679,6 @@ public class MinecraftGLSurface extends View implements GrabListener{
|
||||||
|
|
||||||
public void setSurfaceReadyListener(SurfaceReadyListener listener){
|
public void setSurfaceReadyListener(SurfaceReadyListener listener){
|
||||||
mSurfaceReadyListener = listener;
|
mSurfaceReadyListener = listener;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package net.kdt.pojavlaunch;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class MissingStorageActivity extends AppCompatActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.storage_test_no_sdcard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package net.kdt.pojavlaunch;
|
package net.kdt.pojavlaunch;
|
||||||
|
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
|
|
||||||
import android.app.*;
|
import android.app.*;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.content.pm.*;
|
import android.content.pm.*;
|
||||||
|
|
@ -21,13 +23,13 @@ import net.kdt.pojavlaunch.utils.*;
|
||||||
|
|
||||||
public class PojavApplication extends Application {
|
public class PojavApplication extends Application {
|
||||||
public static String CRASH_REPORT_TAG = "PojavCrashReport";
|
public static String CRASH_REPORT_TAG = "PojavCrashReport";
|
||||||
public static ExecutorService sExecutorService = new ThreadPoolExecutor(0, 4, 500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
|
public static ExecutorService sExecutorService = new ThreadPoolExecutor(4, 4, 500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> {
|
Thread.setDefaultUncaughtExceptionHandler((thread, th) -> {
|
||||||
boolean storagePermAllowed = Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 29 ||
|
boolean storagePermAllowed = (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 29 ||
|
||||||
ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) && Tools.checkStorageRoot(PojavApplication.this);
|
||||||
File crashFile = new File(storagePermAllowed ? Tools.DIR_GAME_HOME : Tools.DIR_DATA, "latestcrash.txt");
|
File crashFile = new File(storagePermAllowed ? Tools.DIR_GAME_HOME : Tools.DIR_DATA, "latestcrash.txt");
|
||||||
try {
|
try {
|
||||||
// Write to file, since some devices may not able to show error
|
// Write to file, since some devices may not able to show error
|
||||||
|
|
@ -73,11 +75,10 @@ public class PojavApplication extends Application {
|
||||||
.concat("/x86");
|
.concat("/x86");
|
||||||
}
|
}
|
||||||
AsyncAssetManager.unpackRuntime(getAssets(), false);
|
AsyncAssetManager.unpackRuntime(getAssets(), false);
|
||||||
AsyncAssetManager.unpackComponents(this);
|
|
||||||
AsyncAssetManager.unpackSingleFiles(this);
|
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
Intent ferrorIntent = new Intent(this, FatalErrorActivity.class);
|
Intent ferrorIntent = new Intent(this, FatalErrorActivity.class);
|
||||||
ferrorIntent.putExtra("throwable", throwable);
|
ferrorIntent.putExtra("throwable", throwable);
|
||||||
|
ferrorIntent.setFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(ferrorIntent);
|
startActivity(ferrorIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package net.kdt.pojavlaunch;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.tasks.AsyncAssetManager;
|
||||||
|
|
||||||
|
public class TestStorageActivity extends Activity {
|
||||||
|
private final int REQUEST_STORAGE_REQUEST_CODE = 1;
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if(Build.VERSION.SDK_INT >= 23 && Build.VERSION.SDK_INT < 29 && !isStorageAllowed(this)) requestStoragePermission();
|
||||||
|
else exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
if(requestCode == REQUEST_STORAGE_REQUEST_CODE) {
|
||||||
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
exit();
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, R.string.toast_permission_denied, Toast.LENGTH_LONG).show();
|
||||||
|
requestStoragePermission();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isStorageAllowed(Context context) {
|
||||||
|
//Getting the permission status
|
||||||
|
int result1 = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||||
|
int result2 = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||||
|
|
||||||
|
|
||||||
|
//If permission is granted returning true
|
||||||
|
return result1 == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
result2 == PackageManager.PERMISSION_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestStoragePermission() {
|
||||||
|
|
||||||
|
ActivityCompat.requestPermissions(this, new String[]{
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_STORAGE_REQUEST_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void exit() {
|
||||||
|
if(!Tools.checkStorageRoot(this)) {
|
||||||
|
startActivity(new Intent(this, MissingStorageActivity.class));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Only run them once we get a definitive green light to use storage
|
||||||
|
AsyncAssetManager.unpackComponents(this);
|
||||||
|
AsyncAssetManager.unpackSingleFiles(this);
|
||||||
|
|
||||||
|
Intent intent = new Intent(this, LauncherActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package net.kdt.pojavlaunch;
|
||||||
|
|
||||||
import android.app.*;
|
import android.app.*;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.*;
|
import android.net.*;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
|
|
@ -85,6 +86,26 @@ public final class Tools {
|
||||||
public static final String LIBNAME_OPTIFINE = "optifine:OptiFine";
|
public static final String LIBNAME_OPTIFINE = "optifine:OptiFine";
|
||||||
public static final int RUN_MOD_INSTALLER = 2050;
|
public static final int RUN_MOD_INSTALLER = 2050;
|
||||||
|
|
||||||
|
|
||||||
|
private static File getPojavStorageRoot(Context ctx) {
|
||||||
|
if(SDK_INT >= 29) {
|
||||||
|
return ctx.getExternalFilesDir(null);
|
||||||
|
}else{
|
||||||
|
return new File(Environment.getExternalStorageDirectory(),"games/PojavLauncher");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the Pojav's storage root is accessible and read-writable
|
||||||
|
* @param context context to get the storage root if it's not set yet
|
||||||
|
* @return true if storage is fine, false if storage is not accessible
|
||||||
|
*/
|
||||||
|
public static boolean checkStorageRoot(Context context) {
|
||||||
|
File externalFilesDir = DIR_GAME_HOME == null ? Tools.getPojavStorageRoot(context) : new File(DIR_GAME_HOME);
|
||||||
|
//externalFilesDir == null when the storage is not mounted if it was obtained with the context call
|
||||||
|
return externalFilesDir != null && Environment.getExternalStorageState(externalFilesDir).equals(Environment.MEDIA_MOUNTED);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Since some constant requires the use of the Context object
|
* Since some constant requires the use of the Context object
|
||||||
* You can call this function to initialize them.
|
* You can call this function to initialize them.
|
||||||
|
|
@ -93,11 +114,7 @@ public final class Tools {
|
||||||
public static void initContextConstants(Context ctx){
|
public static void initContextConstants(Context ctx){
|
||||||
DIR_DATA = ctx.getFilesDir().getParent();
|
DIR_DATA = ctx.getFilesDir().getParent();
|
||||||
MULTIRT_HOME = DIR_DATA+"/runtimes";
|
MULTIRT_HOME = DIR_DATA+"/runtimes";
|
||||||
if(SDK_INT >= 29) {
|
DIR_GAME_HOME = getPojavStorageRoot(ctx).getAbsolutePath();
|
||||||
DIR_GAME_HOME = ctx.getExternalFilesDir(null).getAbsolutePath();
|
|
||||||
}else{
|
|
||||||
DIR_GAME_HOME = new File(Environment.getExternalStorageDirectory(),"games/PojavLauncher").getAbsolutePath();
|
|
||||||
}
|
|
||||||
DIR_GAME_NEW = DIR_GAME_HOME + "/.minecraft";
|
DIR_GAME_NEW = DIR_GAME_HOME + "/.minecraft";
|
||||||
DIR_HOME_VERSION = DIR_GAME_NEW + "/versions";
|
DIR_HOME_VERSION = DIR_GAME_NEW + "/versions";
|
||||||
DIR_HOME_LIBRARY = DIR_GAME_NEW + "/libraries";
|
DIR_HOME_LIBRARY = DIR_GAME_NEW + "/libraries";
|
||||||
|
|
@ -110,7 +127,8 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void launchMinecraft(final Activity activity, MinecraftAccount minecraftAccount, MinecraftProfile minecraftProfile) throws Throwable {
|
public static void launchMinecraft(final Activity activity, MinecraftAccount minecraftAccount,
|
||||||
|
MinecraftProfile minecraftProfile, String versionId) throws Throwable {
|
||||||
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
|
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
|
||||||
((ActivityManager)activity.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(mi);
|
((ActivityManager)activity.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryInfo(mi);
|
||||||
if(LauncherPreferences.PREF_RAM_ALLOCATION > (mi.availMem/1048576L)) {
|
if(LauncherPreferences.PREF_RAM_ALLOCATION > (mi.availMem/1048576L)) {
|
||||||
|
|
@ -126,9 +144,7 @@ public final class Tools {
|
||||||
memoryErrorLock.wait();
|
memoryErrorLock.wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(versionId);
|
||||||
JMinecraftVersionList.Version versionInfo = Tools.getVersionInfo(minecraftProfile.lastVersionId);
|
|
||||||
|
|
||||||
LauncherProfiles.update();
|
LauncherProfiles.update();
|
||||||
String gamedirPath = Tools.getGameDirPath(minecraftProfile);
|
String gamedirPath = Tools.getGameDirPath(minecraftProfile);
|
||||||
|
|
||||||
|
|
@ -143,24 +159,11 @@ public final class Tools {
|
||||||
OldVersionsUtils.selectOpenGlVersion(versionInfo);
|
OldVersionsUtils.selectOpenGlVersion(versionInfo);
|
||||||
|
|
||||||
|
|
||||||
String launchClassPath = generateLaunchClassPath(versionInfo, minecraftProfile.lastVersionId);
|
String launchClassPath = generateLaunchClassPath(versionInfo, versionId);
|
||||||
|
|
||||||
List<String> javaArgList = new ArrayList<String>();
|
List<String> javaArgList = new ArrayList<String>();
|
||||||
|
|
||||||
getCacioJavaArgs(javaArgList, JREUtils.jreReleaseList.get("JAVA_VERSION").equals("1.8.0"));
|
getCacioJavaArgs(javaArgList, JREUtils.jreReleaseList.get("JAVA_VERSION").startsWith("1.8.0"));
|
||||||
|
|
||||||
/*
|
|
||||||
int mcReleaseDate = Integer.parseInt(versionInfo.releaseTime.substring(0, 10).replace("-", ""));
|
|
||||||
// 13w17a: 20130425
|
|
||||||
// 13w18a: 20130502
|
|
||||||
if (mcReleaseDate < 20130502 && versionInfo.minimumLauncherVersion < 9){
|
|
||||||
ctx.appendlnToLog("AWT-enabled version detected! ("+mcReleaseDate+")");
|
|
||||||
getCacioJavaArgs(javaArgList,false);
|
|
||||||
}else{
|
|
||||||
getCacioJavaArgs(javaArgList,false); // true
|
|
||||||
ctx.appendlnToLog("Headless version detected! ("+mcReleaseDate+")");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (versionInfo.logging != null) {
|
if (versionInfo.logging != null) {
|
||||||
String configFile = Tools.DIR_DATA + "/security/" + versionInfo.logging.client.file.id.replace("client", "log4j-rce-patch");
|
String configFile = Tools.DIR_DATA + "/security/" + versionInfo.logging.client.file.id.replace("client", "log4j-rce-patch");
|
||||||
|
|
@ -169,14 +172,14 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
javaArgList.add("-Dlog4j.configurationFile=" + configFile);
|
javaArgList.add("-Dlog4j.configurationFile=" + configFile);
|
||||||
}
|
}
|
||||||
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(minecraftProfile.lastVersionId, gamedirPath)));
|
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionId, gamedirPath)));
|
||||||
javaArgList.add("-cp");
|
javaArgList.add("-cp");
|
||||||
javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath);
|
javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath);
|
||||||
|
|
||||||
javaArgList.add(versionInfo.mainClass);
|
javaArgList.add(versionInfo.mainClass);
|
||||||
javaArgList.addAll(Arrays.asList(launchArgs));
|
javaArgList.addAll(Arrays.asList(launchArgs));
|
||||||
// ctx.appendlnToLog("full args: "+javaArgList.toString());
|
// ctx.appendlnToLog("full args: "+javaArgList.toString());
|
||||||
JREUtils.launchJavaVM(activity, javaArgList);
|
JREUtils.launchJavaVM(activity, gamedirPath, javaArgList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getGameDirPath(@NonNull MinecraftProfile minecraftProfile){
|
public static String getGameDirPath(@NonNull MinecraftProfile minecraftProfile){
|
||||||
|
|
@ -279,6 +282,7 @@ public final class Tools {
|
||||||
varArgMap.put("classpath_separator", ":");
|
varArgMap.put("classpath_separator", ":");
|
||||||
varArgMap.put("library_directory", strGameDir + "/libraries");
|
varArgMap.put("library_directory", strGameDir + "/libraries");
|
||||||
varArgMap.put("version_name", versionInfo.id);
|
varArgMap.put("version_name", versionInfo.id);
|
||||||
|
varArgMap.put("natives_directory", Tools.NATIVE_LIB_DIR);
|
||||||
|
|
||||||
List<String> minecraftArgs = new ArrayList<String>();
|
List<String> minecraftArgs = new ArrayList<String>();
|
||||||
if (versionInfo.arguments != null) {
|
if (versionInfo.arguments != null) {
|
||||||
|
|
@ -324,7 +328,7 @@ public final class Tools {
|
||||||
varArgMap.put("auth_session", profile.accessToken); // For legacy versions of MC
|
varArgMap.put("auth_session", profile.accessToken); // For legacy versions of MC
|
||||||
varArgMap.put("auth_access_token", profile.accessToken);
|
varArgMap.put("auth_access_token", profile.accessToken);
|
||||||
varArgMap.put("auth_player_name", username);
|
varArgMap.put("auth_player_name", username);
|
||||||
varArgMap.put("auth_uuid", profile.profileId);
|
varArgMap.put("auth_uuid", profile.profileId.replace("-", ""));
|
||||||
varArgMap.put("auth_xuid", profile.xuid);
|
varArgMap.put("auth_xuid", profile.xuid);
|
||||||
varArgMap.put("assets_root", Tools.ASSETS_PATH);
|
varArgMap.put("assets_root", Tools.ASSETS_PATH);
|
||||||
varArgMap.put("assets_index_name", versionInfo.assets);
|
varArgMap.put("assets_index_name", versionInfo.assets);
|
||||||
|
|
@ -358,17 +362,6 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
minecraftArgs.add("--width");
|
|
||||||
minecraftArgs.add(Integer.toString(CallbackBridge.windowWidth));
|
|
||||||
minecraftArgs.add("--height");
|
|
||||||
minecraftArgs.add(Integer.toString(CallbackBridge.windowHeight));
|
|
||||||
|
|
||||||
minecraftArgs.add("--fullscreenWidth");
|
|
||||||
minecraftArgs.add(Integer.toString(CallbackBridge.windowWidth));
|
|
||||||
minecraftArgs.add("--fullscreenHeight");
|
|
||||||
minecraftArgs.add(Integer.toString(CallbackBridge.windowHeight));
|
|
||||||
*/
|
|
||||||
|
|
||||||
String[] argsFromJson = JSONUtils.insertJSONValueList(
|
String[] argsFromJson = JSONUtils.insertJSONValueList(
|
||||||
splitAndFilterEmpty(
|
splitAndFilterEmpty(
|
||||||
|
|
@ -438,26 +431,6 @@ public final class Tools {
|
||||||
|
|
||||||
String[] classpath = generateLibClasspath(info);
|
String[] classpath = generateLibClasspath(info);
|
||||||
|
|
||||||
// Debug: LWJGL 3 override
|
|
||||||
// File lwjgl2Folder = new File(Tools.MAIN_PATH, "lwjgl2");
|
|
||||||
|
|
||||||
/*
|
|
||||||
File lwjgl3Folder = new File(Tools.MAIN_PATH, "lwjgl3");
|
|
||||||
if (lwjgl3Folder.exists()) {
|
|
||||||
for (File file: lwjgl3Folder.listFiles()) {
|
|
||||||
if (file.getName().endsWith(".jar")) {
|
|
||||||
libStr.append(file.getAbsolutePath() + ":");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (lwjgl2Folder.exists()) {
|
|
||||||
for (File file: lwjgl2Folder.listFiles()) {
|
|
||||||
if (file.getName().endsWith(".jar")) {
|
|
||||||
libStr.append(file.getAbsolutePath() + ":");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (isClientFirst) {
|
if (isClientFirst) {
|
||||||
libStr.append(getPatchedFile(actualname));
|
libStr.append(getPatchedFile(actualname));
|
||||||
}
|
}
|
||||||
|
|
@ -484,18 +457,18 @@ public final class Tools {
|
||||||
}else{
|
}else{
|
||||||
if (SDK_INT >= Build.VERSION_CODES.R) {
|
if (SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
activity.getDisplay().getRealMetrics(displayMetrics);
|
activity.getDisplay().getRealMetrics(displayMetrics);
|
||||||
} else if(SDK_INT >= P) {
|
} else { // Removed the clause for devices with unofficial notch support, since it also ruins all devices with virtual nav bars before P
|
||||||
activity.getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
|
activity.getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
|
||||||
}else{ // Some old devices can have a notch despite it not being officially supported
|
|
||||||
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
|
||||||
}
|
}
|
||||||
if(!PREF_IGNORE_NOTCH){
|
if(!PREF_IGNORE_NOTCH){
|
||||||
//Remove notch width when it isn't ignored.
|
//Remove notch width when it isn't ignored.
|
||||||
displayMetrics.widthPixels -= PREF_NOTCH_SIZE;
|
if(activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
|
||||||
|
displayMetrics.heightPixels -= PREF_NOTCH_SIZE;
|
||||||
|
else
|
||||||
|
displayMetrics.widthPixels -= PREF_NOTCH_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentDisplayMetrics = displayMetrics;
|
currentDisplayMetrics = displayMetrics;
|
||||||
|
|
||||||
return displayMetrics;
|
return displayMetrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -550,27 +523,45 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
File destinationFile = new File(output, outputName);
|
File destinationFile = new File(output, outputName);
|
||||||
if(!destinationFile.exists() || overwrite){
|
if(!destinationFile.exists() || overwrite){
|
||||||
IOUtils.copy(ctx.getAssets().open(fileName), new FileOutputStream(destinationFile));
|
try(InputStream inputStream = ctx.getAssets().open(fileName)) {
|
||||||
|
try (OutputStream outputStream = new FileOutputStream(destinationFile)){
|
||||||
|
IOUtils.copy(inputStream, outputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String printToString(Throwable throwable) {
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
PrintWriter printWriter = new PrintWriter(stringWriter);
|
||||||
|
throwable.printStackTrace(printWriter);
|
||||||
|
printWriter.close();
|
||||||
|
return stringWriter.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public static void showError(Context ctx, Throwable e) {
|
public static void showError(Context ctx, Throwable e) {
|
||||||
showError(ctx, e, false);
|
showError(ctx, e, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showError(final Context ctx, final Throwable e, final boolean exitIfOk) {
|
public static void showError(final Context ctx, final Throwable e, final boolean exitIfOk) {
|
||||||
showError(ctx, R.string.global_error, e, exitIfOk, false);
|
showError(ctx, R.string.global_error, null ,e, exitIfOk, false);
|
||||||
|
}
|
||||||
|
public static void showError(final Context ctx, final int rolledMessage, final Throwable e) {
|
||||||
|
showError(ctx, R.string.global_error, ctx.getString(rolledMessage), e, false, false);
|
||||||
|
}
|
||||||
|
public static void showError(final Context ctx, final String rolledMessage, final Throwable e) {
|
||||||
|
showError(ctx, R.string.global_error, rolledMessage, e, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showError(final Context ctx, final int titleId, final Throwable e, final boolean exitIfOk) {
|
public static void showError(final Context ctx, final int titleId, final Throwable e, final boolean exitIfOk) {
|
||||||
showError(ctx, titleId, e, exitIfOk, false);
|
showError(ctx, titleId, null, e, exitIfOk, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void showError(final Context ctx, final int titleId, final Throwable e, final boolean exitIfOk, final boolean showMore) {
|
private static void showError(final Context ctx, final int titleId, final String rolledMessage, final Throwable e, final boolean exitIfOk, final boolean showMore) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
||||||
Runnable runnable = () -> {
|
Runnable runnable = () -> {
|
||||||
final String errMsg = showMore ? Log.getStackTraceString(e): e.getMessage();
|
final String errMsg = showMore ? printToString(e) : rolledMessage != null ? rolledMessage : e.getMessage();
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder((Context) ctx)
|
AlertDialog.Builder builder = new AlertDialog.Builder((Context) ctx)
|
||||||
.setTitle(titleId)
|
.setTitle(titleId)
|
||||||
.setMessage(errMsg)
|
.setMessage(errMsg)
|
||||||
|
|
@ -583,7 +574,7 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton(showMore ? R.string.error_show_less : R.string.error_show_more, (DialogInterface.OnClickListener) (p1, p2) -> showError(ctx, titleId, e, exitIfOk, !showMore))
|
.setNegativeButton(showMore ? R.string.error_show_less : R.string.error_show_more, (DialogInterface.OnClickListener) (p1, p2) -> showError(ctx, titleId, rolledMessage, e, exitIfOk, !showMore))
|
||||||
.setNeutralButton(android.R.string.copy, (DialogInterface.OnClickListener) (p1, p2) -> {
|
.setNeutralButton(android.R.string.copy, (DialogInterface.OnClickListener) (p1, p2) -> {
|
||||||
ClipboardManager mgr = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
|
ClipboardManager mgr = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
mgr.setPrimaryClip(ClipData.newPlainText("error", Log.getStackTraceString(e)));
|
mgr.setPrimaryClip(ClipData.newPlainText("error", Log.getStackTraceString(e)));
|
||||||
|
|
@ -674,11 +665,6 @@ public final class Tools {
|
||||||
public static JMinecraftVersionList.Version getVersionInfo(String versionName, boolean skipInheriting) {
|
public static JMinecraftVersionList.Version getVersionInfo(String versionName, boolean skipInheriting) {
|
||||||
try {
|
try {
|
||||||
JMinecraftVersionList.Version customVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + versionName + "/" + versionName + ".json"), JMinecraftVersionList.Version.class);
|
JMinecraftVersionList.Version customVer = Tools.GLOBAL_GSON.fromJson(read(DIR_HOME_VERSION + "/" + versionName + "/" + versionName + ".json"), JMinecraftVersionList.Version.class);
|
||||||
for (DependentLibrary lib : customVer.libraries) {
|
|
||||||
if (lib.name.startsWith(LIBNAME_OPTIFINE)) {
|
|
||||||
customVer.optifineLib = lib;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (skipInheriting || customVer.inheritsFrom == null || customVer.inheritsFrom.equals(customVer.id)) {
|
if (skipInheriting || customVer.inheritsFrom == null || customVer.inheritsFrom.equals(customVer.id)) {
|
||||||
return customVer;
|
return customVer;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -698,7 +684,7 @@ public final class Tools {
|
||||||
insertSafety(inheritsVer, customVer,
|
insertSafety(inheritsVer, customVer,
|
||||||
"assetIndex", "assets", "id",
|
"assetIndex", "assets", "id",
|
||||||
"mainClass", "minecraftArguments",
|
"mainClass", "minecraftArguments",
|
||||||
"optifineLib", "releaseTime", "time", "type"
|
"releaseTime", "time", "type"
|
||||||
);
|
);
|
||||||
|
|
||||||
List<DependentLibrary> libList = new ArrayList<DependentLibrary>(Arrays.asList(inheritsVer.libraries));
|
List<DependentLibrary> libList = new ArrayList<DependentLibrary>(Arrays.asList(inheritsVer.libraries));
|
||||||
|
|
@ -719,7 +705,7 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
libList.add(lib);
|
libList.add(0, lib);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inheritsVer.libraries = libList.toArray(new DependentLibrary[0]);
|
inheritsVer.libraries = libList.toArray(new DependentLibrary[0]);
|
||||||
|
|
@ -785,87 +771,20 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String convertStream(InputStream inputStream) throws IOException {
|
|
||||||
return convertStream(inputStream, Charset.forName("UTF-8"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String convertStream(InputStream inputStream, Charset charset) throws IOException {
|
|
||||||
StringBuilder out = new StringBuilder();
|
|
||||||
int len;
|
|
||||||
byte[] buf = new byte[512];
|
|
||||||
while((len = inputStream.read(buf))!=-1) {
|
|
||||||
out.append(new String(buf, 0, len, charset));
|
|
||||||
}
|
|
||||||
return out.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File lastFileModified(String dir) {
|
|
||||||
File fl = new File(dir);
|
|
||||||
|
|
||||||
File[] files = fl.listFiles(File::isFile);
|
|
||||||
if(files == null) {
|
|
||||||
return null;
|
|
||||||
// The patch was a bit wrong...
|
|
||||||
// So, this may be null, why? Because this folder may not exist yet
|
|
||||||
// Or it may not have any files...
|
|
||||||
// Doesn't matter. We must check for that in the crash fragment.
|
|
||||||
}
|
|
||||||
long lastMod = Long.MIN_VALUE;
|
|
||||||
File choice = null;
|
|
||||||
for (File file : files) {
|
|
||||||
if (file.lastModified() > lastMod) {
|
|
||||||
choice = file;
|
|
||||||
lastMod = file.lastModified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return choice;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static String read(InputStream is) throws IOException {
|
public static String read(InputStream is) throws IOException {
|
||||||
StringBuilder out = new StringBuilder();
|
String readResult = IOUtils.toString(is, StandardCharsets.UTF_8);
|
||||||
int len;
|
is.close();
|
||||||
byte[] buf = new byte[512];
|
return readResult;
|
||||||
while((len = is.read(buf))!=-1) {
|
|
||||||
out.append(new String(buf, 0, len));
|
|
||||||
}
|
|
||||||
return out.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String read(String path) throws IOException {
|
public static String read(String path) throws IOException {
|
||||||
return read(new FileInputStream(path));
|
return read(new FileInputStream(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void write(String path, byte[] content) throws IOException
|
|
||||||
{
|
|
||||||
File outPath = new File(path);
|
|
||||||
outPath.getParentFile().mkdirs();
|
|
||||||
outPath.createNewFile();
|
|
||||||
|
|
||||||
BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(path));
|
|
||||||
fos.write(content, 0, content.length);
|
|
||||||
fos.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void write(String path, String content) throws IOException {
|
public static void write(String path, String content) throws IOException {
|
||||||
write(path, content.getBytes());
|
try(FileOutputStream outStream = new FileOutputStream(path)) {
|
||||||
}
|
IOUtils.write(content, outStream);
|
||||||
|
|
||||||
public static byte[] loadFromAssetToByte(Context ctx, String inFile) {
|
|
||||||
byte[] buffer = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
InputStream stream = ctx.getAssets().open(inFile);
|
|
||||||
|
|
||||||
int size = stream.available();
|
|
||||||
buffer = new byte[size];
|
|
||||||
stream.read(buffer);
|
|
||||||
stream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Handle exceptions here
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void downloadFile(String urlInput, String nameOutput) throws IOException {
|
public static void downloadFile(String urlInput, String nameOutput) throws IOException {
|
||||||
|
|
@ -927,22 +846,14 @@ public final class Tools {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getFileName(Context ctx, Uri uri) {
|
public static String getFileName(Context ctx, Uri uri) {
|
||||||
String result = null;
|
Cursor c = ctx.getContentResolver().query(uri, null, null, null, null);
|
||||||
if (uri.getScheme().equals("content")) {
|
if(c == null) return uri.getLastPathSegment(); // idk myself but it happens on asus file manager
|
||||||
try (Cursor cursor = ctx.getContentResolver().query(uri, null, null, null, null)) {
|
c.moveToFirst();
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
int columnIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
||||||
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
if(columnIndex == -1) return uri.getLastPathSegment();
|
||||||
}
|
String fileName = c.getString(columnIndex);
|
||||||
}
|
c.close();
|
||||||
}
|
return fileName;
|
||||||
if (result == null) {
|
|
||||||
result = uri.getPath();
|
|
||||||
int cut = result.lastIndexOf('/');
|
|
||||||
if (cut != -1) {
|
|
||||||
result = result.substring(cut + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Swap the main fragment with another */
|
/** Swap the main fragment with another */
|
||||||
|
|
@ -1019,7 +930,9 @@ public final class Tools {
|
||||||
final String name = getFileName(activity, uri);
|
final String name = getFileName(activity, uri);
|
||||||
final File modInstallerFile = new File(activity.getCacheDir(), name);
|
final File modInstallerFile = new File(activity.getCacheDir(), name);
|
||||||
FileOutputStream fos = new FileOutputStream(modInstallerFile);
|
FileOutputStream fos = new FileOutputStream(modInstallerFile);
|
||||||
IOUtils.copy(activity.getContentResolver().openInputStream(uri), fos);
|
InputStream input = activity.getContentResolver().openInputStream(uri);
|
||||||
|
IOUtils.copy(input, fos);
|
||||||
|
input.close();
|
||||||
fos.close();
|
fos.close();
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
alertDialog.dismiss();
|
alertDialog.dismiss();
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ public class Touchpad extends FrameLayout implements GrabListener{
|
||||||
private final ImageView mMousePointerImageView = new ImageView(getContext());
|
private final ImageView mMousePointerImageView = new ImageView(getContext());
|
||||||
/* Detect a classic android Tap */
|
/* Detect a classic android Tap */
|
||||||
private final GestureDetector mSingleTapDetector = new GestureDetector(getContext(), new SingleTapConfirm());
|
private final GestureDetector mSingleTapDetector = new GestureDetector(getContext(), new SingleTapConfirm());
|
||||||
private final Handler uiThreadHandler = new Handler();
|
|
||||||
/* Resolution scaler option, allow downsizing a window */
|
/* Resolution scaler option, allow downsizing a window */
|
||||||
private final float mScaleFactor = DEFAULT_PREF.getInt("resolutionRatio",100)/100f;
|
private final float mScaleFactor = DEFAULT_PREF.getInt("resolutionRatio",100)/100f;
|
||||||
/* Current pointer ID to move the mouse */
|
/* Current pointer ID to move the mouse */
|
||||||
|
|
@ -181,7 +180,7 @@ public class Touchpad extends FrameLayout implements GrabListener{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGrabState(boolean isGrabbing) {
|
public void onGrabState(boolean isGrabbing) {
|
||||||
uiThreadHandler.post(()->updateGrabState(isGrabbing));
|
post(()->updateGrabState(isGrabbing));
|
||||||
}
|
}
|
||||||
private void updateGrabState(boolean isGrabbing) {
|
private void updateGrabState(boolean isGrabbing) {
|
||||||
if(!isGrabbing) {
|
if(!isGrabbing) {
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,14 @@ package net.kdt.pojavlaunch.authenticator.microsoft;
|
||||||
import static net.kdt.pojavlaunch.PojavApplication.sExecutorService;
|
import static net.kdt.pojavlaunch.PojavApplication.sExecutorService;
|
||||||
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.kdt.mcgui.ProgressLayout;
|
import com.kdt.mcgui.ProgressLayout;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.value.MinecraftAccount;
|
import net.kdt.pojavlaunch.value.MinecraftAccount;
|
||||||
import net.kdt.pojavlaunch.authenticator.listener.*;
|
import net.kdt.pojavlaunch.authenticator.listener.*;
|
||||||
|
|
@ -39,6 +41,15 @@ public class MicrosoftBackgroundLogin {
|
||||||
private final boolean mIsRefresh;
|
private final boolean mIsRefresh;
|
||||||
private final String mAuthCode;
|
private final String mAuthCode;
|
||||||
private final android.os.Handler mHandler = new android.os.Handler(Looper.getMainLooper());
|
private final android.os.Handler mHandler = new android.os.Handler(Looper.getMainLooper());
|
||||||
|
private static final Map<Long, Integer> XSTS_ERRORS;
|
||||||
|
static {
|
||||||
|
XSTS_ERRORS = new ArrayMap<>();
|
||||||
|
XSTS_ERRORS.put(2148916233L, R.string.xerr_no_account);
|
||||||
|
XSTS_ERRORS.put(2148916235L, R.string.xerr_not_available);
|
||||||
|
XSTS_ERRORS.put(2148916236L ,R.string.xerr_adult_verification);
|
||||||
|
XSTS_ERRORS.put(2148916237L ,R.string.xerr_adult_verification);
|
||||||
|
XSTS_ERRORS.put(2148916238L ,R.string.xerr_child);
|
||||||
|
}
|
||||||
|
|
||||||
/* Fields used to fill the account */
|
/* Fields used to fill the account */
|
||||||
public boolean isRefresh;
|
public boolean isRefresh;
|
||||||
|
|
@ -211,6 +222,15 @@ public class MicrosoftBackgroundLogin {
|
||||||
Log.i("MicrosoftLogin","Xbl Xsts = " + token + "; Uhs = " + uhs);
|
Log.i("MicrosoftLogin","Xbl Xsts = " + token + "; Uhs = " + uhs);
|
||||||
return new String[]{uhs, token};
|
return new String[]{uhs, token};
|
||||||
//acquireMinecraftToken(uhs,jo.getString("Token"));
|
//acquireMinecraftToken(uhs,jo.getString("Token"));
|
||||||
|
}else if(conn.getResponseCode() == 401) {
|
||||||
|
String responseContents = Tools.read(conn.getErrorStream());
|
||||||
|
JSONObject jo = new JSONObject(responseContents);
|
||||||
|
long xerr = jo.optLong("XErr", -1);
|
||||||
|
Integer locale_id = XSTS_ERRORS.get(xerr);
|
||||||
|
if(locale_id != null) {
|
||||||
|
throw new PresentedException(new RuntimeException(responseContents), locale_id);
|
||||||
|
}
|
||||||
|
throw new PresentedException(new RuntimeException(responseContents), R.string.xerr_unknown, xerr);
|
||||||
}else{
|
}else{
|
||||||
throwResponseError(conn);
|
throwResponseError(conn);
|
||||||
}
|
}
|
||||||
|
|
@ -274,8 +294,8 @@ public class MicrosoftBackgroundLogin {
|
||||||
}else{
|
}else{
|
||||||
Log.i("MicrosoftLogin","It seems that this Microsoft Account does not own the game.");
|
Log.i("MicrosoftLogin","It seems that this Microsoft Account does not own the game.");
|
||||||
doesOwnGame = false;
|
doesOwnGame = false;
|
||||||
|
throw new PresentedException(new RuntimeException(conn.getResponseMessage()), R.string.minecraft_not_owned);
|
||||||
throwResponseError(conn);
|
//throwResponseError(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,7 +309,7 @@ public class MicrosoftBackgroundLogin {
|
||||||
|
|
||||||
|
|
||||||
/** Set common properties, and enable interactivity if desired */
|
/** Set common properties, and enable interactivity if desired */
|
||||||
private static void setCommonProperties(HttpURLConnection conn, String formData, boolean interactive){
|
private static void setCommonProperties(HttpURLConnection conn, String formData, boolean interactive) {
|
||||||
conn.setRequestProperty("Content-Type", "application/json");
|
conn.setRequestProperty("Content-Type", "application/json");
|
||||||
conn.setRequestProperty("Accept", "application/json");
|
conn.setRequestProperty("Accept", "application/json");
|
||||||
conn.setRequestProperty("charset", "utf-8");
|
conn.setRequestProperty("charset", "utf-8");
|
||||||
|
|
@ -321,6 +341,9 @@ public class MicrosoftBackgroundLogin {
|
||||||
|
|
||||||
private void throwResponseError(HttpURLConnection conn) throws IOException {
|
private void throwResponseError(HttpURLConnection conn) throws IOException {
|
||||||
Log.i("MicrosoftLogin", "Error code: " + conn.getResponseCode() + ": " + conn.getResponseMessage());
|
Log.i("MicrosoftLogin", "Error code: " + conn.getResponseCode() + ": " + conn.getResponseMessage());
|
||||||
|
if(conn.getResponseCode() == 429) {
|
||||||
|
throw new PresentedException(R.string.microsoft_login_retry_later);
|
||||||
|
}
|
||||||
throw new RuntimeException(conn.getResponseMessage());
|
throw new RuntimeException(conn.getResponseMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package net.kdt.pojavlaunch.authenticator.microsoft;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class PresentedException extends RuntimeException {
|
||||||
|
final int localizationStringId;
|
||||||
|
final Object[] extraArgs;
|
||||||
|
|
||||||
|
public PresentedException(int localizationStringId, Object... extraArgs) {
|
||||||
|
this.localizationStringId = localizationStringId;
|
||||||
|
this.extraArgs = extraArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PresentedException(Throwable throwable, int localizationStringId, Object... extraArgs) {
|
||||||
|
super(throwable);
|
||||||
|
this.localizationStringId = localizationStringId;
|
||||||
|
this.extraArgs = extraArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString(Context context) {
|
||||||
|
return context.getString(localizationStringId, extraArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -160,6 +160,7 @@ public class ColorSelector implements HueSelectionListener, RectangleSelectionLi
|
||||||
public void setAlphaEnabled(boolean alphaEnabled){
|
public void setAlphaEnabled(boolean alphaEnabled){
|
||||||
mAlphaEnabled = alphaEnabled;
|
mAlphaEnabled = alphaEnabled;
|
||||||
mAlphaView.setVisibility(alphaEnabled ? View.VISIBLE : View.GONE);
|
mAlphaView.setVisibility(alphaEnabled ? View.VISIBLE : View.GONE);
|
||||||
|
mAlphaView.setAlpha(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyColorSelector(int color){
|
private void notifyColorSelector(int color){
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package net.kdt.pojavlaunch.customcontrols;
|
||||||
|
|
||||||
|
public interface ControlButtonMenuListener {
|
||||||
|
void onClickedMenu();
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,7 @@ public class ControlData {
|
||||||
public static final int SPECIALBTN_MOUSEMID = -6;
|
public static final int SPECIALBTN_MOUSEMID = -6;
|
||||||
public static final int SPECIALBTN_SCROLLUP = -7;
|
public static final int SPECIALBTN_SCROLLUP = -7;
|
||||||
public static final int SPECIALBTN_SCROLLDOWN = -8;
|
public static final int SPECIALBTN_SCROLLDOWN = -8;
|
||||||
|
public static final int SPECIALBTN_MENU = -9;
|
||||||
|
|
||||||
private static ControlData[] SPECIAL_BUTTONS;
|
private static ControlData[] SPECIAL_BUTTONS;
|
||||||
private static String[] SPECIAL_BUTTON_NAME_ARRAY;
|
private static String[] SPECIAL_BUTTON_NAME_ARRAY;
|
||||||
|
|
@ -65,7 +66,8 @@ public class ControlData {
|
||||||
|
|
||||||
new ControlData("MID", new int[]{SPECIALBTN_MOUSEMID}, "${margin}", "${margin}"),
|
new ControlData("MID", new int[]{SPECIALBTN_MOUSEMID}, "${margin}", "${margin}"),
|
||||||
new ControlData("SCROLLUP", new int[]{SPECIALBTN_SCROLLUP}, "${margin}", "${margin}"),
|
new ControlData("SCROLLUP", new int[]{SPECIALBTN_SCROLLUP}, "${margin}", "${margin}"),
|
||||||
new ControlData("SCROLLDOWN", new int[]{SPECIALBTN_SCROLLDOWN}, "${margin}", "${margin}")
|
new ControlData("SCROLLDOWN", new int[]{SPECIALBTN_SCROLLDOWN}, "${margin}", "${margin}"),
|
||||||
|
new ControlData("MENU", new int[]{SPECIALBTN_MENU}, "${margin}", "${margin}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import com.google.gson.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
import net.kdt.pojavlaunch.*;
|
import net.kdt.pojavlaunch.*;
|
||||||
|
|
@ -26,12 +27,18 @@ import net.kdt.pojavlaunch.prefs.*;
|
||||||
|
|
||||||
public class ControlLayout extends FrameLayout {
|
public class ControlLayout extends FrameLayout {
|
||||||
protected CustomControls mLayout;
|
protected CustomControls mLayout;
|
||||||
|
/* Accessible when inside the game by ControlInterface implementations, cached for perf. */
|
||||||
|
private MinecraftGLSurface mGameSurface = null;
|
||||||
|
|
||||||
|
/* Cache to buttons for performance purposes */
|
||||||
|
private List<ControlInterface> mButtons;
|
||||||
private boolean mModifiable = false;
|
private boolean mModifiable = false;
|
||||||
private CustomControlsActivity mActivity;
|
private CustomControlsActivity mActivity;
|
||||||
private boolean mControlVisible = false;
|
private boolean mControlVisible = false;
|
||||||
|
|
||||||
private EditControlPopup mControlPopup = null;
|
private EditControlPopup mControlPopup = null;
|
||||||
private ControlHandleView mHandleView;
|
private ControlHandleView mHandleView;
|
||||||
|
private ControlButtonMenuListener mMenuListener;
|
||||||
public ActionRow actionRow = null;
|
public ActionRow actionRow = null;
|
||||||
|
|
||||||
public ControlLayout(Context ctx) {
|
public ControlLayout(Context ctx) {
|
||||||
|
|
@ -87,6 +94,8 @@ public class ControlLayout extends FrameLayout {
|
||||||
mLayout.scaledAt = LauncherPreferences.PREF_BUTTONSIZE;
|
mLayout.scaledAt = LauncherPreferences.PREF_BUTTONSIZE;
|
||||||
|
|
||||||
setModified(false);
|
setModified(false);
|
||||||
|
mButtons = null;
|
||||||
|
getButtonChildren(); // Force refresh
|
||||||
} // loadLayout
|
} // loadLayout
|
||||||
|
|
||||||
//CONTROL BUTTON
|
//CONTROL BUTTON
|
||||||
|
|
@ -222,14 +231,17 @@ public class ControlLayout extends FrameLayout {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<ControlInterface> getButtonChildren(){
|
public List<ControlInterface> getButtonChildren(){
|
||||||
ArrayList<ControlInterface> children = new ArrayList<>();
|
if(mModifiable || mButtons == null){
|
||||||
for(int i=0; i<getChildCount(); ++i){
|
mButtons = new ArrayList<>();
|
||||||
View v = getChildAt(i);
|
for(int i=0; i<getChildCount(); ++i){
|
||||||
if(v instanceof ControlInterface)
|
View v = getChildAt(i);
|
||||||
children.add(((ControlInterface) v));
|
if(v instanceof ControlInterface)
|
||||||
|
mButtons.add(((ControlInterface) v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return children;
|
|
||||||
|
return mButtons;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshControlButtonPositions(){
|
public void refreshControlButtonPositions(){
|
||||||
|
|
@ -287,48 +299,42 @@ public class ControlLayout extends FrameLayout {
|
||||||
|
|
||||||
|
|
||||||
HashMap<View, ControlInterface> mapTable = new HashMap<>();
|
HashMap<View, ControlInterface> mapTable = new HashMap<>();
|
||||||
|
int[] location = new int[2];
|
||||||
//While this is called onTouch, this should only be called from a ControlButton.
|
//While this is called onTouch, this should only be called from a ControlButton.
|
||||||
public boolean onTouch(View v, MotionEvent ev) {
|
public boolean onTouch(View v, MotionEvent ev) {
|
||||||
ControlInterface lastControlButton = mapTable.get(v);
|
|
||||||
|
|
||||||
//Check if the action is cancelling, reset the lastControl button associated to the view
|
//Check if the action is cancelling, reset the lastControl button associated to the view
|
||||||
if(ev.getActionMasked() == MotionEvent.ACTION_UP || ev.getActionMasked() == MotionEvent.ACTION_CANCEL){
|
if(ev.getActionMasked() == MotionEvent.ACTION_UP || ev.getActionMasked() == MotionEvent.ACTION_CANCEL){
|
||||||
if(lastControlButton != null) lastControlButton.sendKeyPresses(false);
|
for(ControlInterface control : mapTable.values()){
|
||||||
mapTable.put(v, null);
|
control.sendKeyPresses(false);
|
||||||
|
}
|
||||||
|
mapTable.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ev.getActionMasked() != MotionEvent.ACTION_MOVE) return false;
|
if(ev.getActionMasked() != MotionEvent.ACTION_MOVE) return false;
|
||||||
|
|
||||||
//Optimization pass to avoid looking at all children again
|
getLocationOnScreen(location);
|
||||||
if(lastControlButton != null){
|
// Update the state of all swipeable buttons
|
||||||
if( ev.getRawX() > lastControlButton.getControlView().getX() && ev.getRawX() < lastControlButton.getControlView().getX() + lastControlButton.getControlView().getWidth() &&
|
|
||||||
ev.getRawY() > lastControlButton.getControlView().getY() && ev.getRawY() < lastControlButton.getControlView().getY() + lastControlButton.getControlView().getHeight()){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Release last keys
|
|
||||||
if (lastControlButton != null) lastControlButton.sendKeyPresses(false);
|
|
||||||
mapTable.put(v, null);
|
|
||||||
|
|
||||||
//Look for another SWIPEABLE button
|
|
||||||
for(ControlInterface button : getButtonChildren()){
|
for(ControlInterface button : getButtonChildren()){
|
||||||
if(!button.getProperties().isSwipeable) continue;
|
if(!button.getProperties().isSwipeable) continue;
|
||||||
|
|
||||||
if( ev.getRawX() > button.getControlView().getX() && ev.getRawX() < button.getControlView().getX() + button.getControlView().getWidth() &&
|
if( ev.getRawX() > button.getControlView().getX() + location[0]
|
||||||
ev.getRawY() > button.getControlView().getY() && ev.getRawY() < button.getControlView().getY() + button.getControlView().getHeight()){
|
&& ev.getRawX() - getGameSurface().getX() < button.getControlView().getX() + button.getControlView().getWidth() + location[0]
|
||||||
|
&& ev.getRawY() > button.getControlView().getY()
|
||||||
|
&& ev.getRawY() < button.getControlView().getY() + button.getControlView().getHeight()){
|
||||||
|
|
||||||
//Press the new key
|
if(mapTable.get(button.getControlView()) == null){
|
||||||
if(!button.equals(lastControlButton)){
|
|
||||||
button.sendKeyPresses(true);
|
button.sendKeyPresses(true);
|
||||||
|
mapTable.put(button.getControlView(), button);
|
||||||
mapTable.put(v, button);
|
}
|
||||||
|
}else{
|
||||||
|
if(mapTable.get(button.getControlView()) != null){
|
||||||
|
button.sendKeyPresses(false);
|
||||||
|
mapTable.remove(button.getControlView());
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -367,4 +373,30 @@ public class ControlLayout extends FrameLayout {
|
||||||
mLayout.save(path);
|
mLayout.save(path);
|
||||||
} catch (IOException e) {Log.e("ControlLayout", "Failed to save the layout at:" + path);}
|
} catch (IOException e) {Log.e("ControlLayout", "Failed to save the layout at:" + path);}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean hasMenuButton() {
|
||||||
|
for(ControlInterface controlInterface : getButtonChildren()){
|
||||||
|
for (int keycode : controlInterface.getProperties().keycodes) {
|
||||||
|
if (keycode == ControlData.SPECIALBTN_MENU) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMenuListener(ControlButtonMenuListener menuListener) {
|
||||||
|
this.mMenuListener = menuListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyAppMenu() {
|
||||||
|
if(mMenuListener != null) mMenuListener.onClickedMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Cached getter for perf purposes */
|
||||||
|
public MinecraftGLSurface getGameSurface(){
|
||||||
|
if(mGameSurface == null){
|
||||||
|
mGameSurface = findViewById(R.id.main_game_render_view);
|
||||||
|
}
|
||||||
|
return mGameSurface;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,22 @@ import com.google.gson.JsonSyntaxException;
|
||||||
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
|
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.lwjgl.glfw.CallbackBridge;
|
import org.lwjgl.glfw.CallbackBridge;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class LayoutConverter {
|
public class LayoutConverter {
|
||||||
public static boolean convertLookType = false; //false = flat; true = classic
|
public static boolean convertLookType = false; //false = flat; true = classic
|
||||||
public static CustomControls loadAndConvertIfNecessary(String jsonPath) throws IOException, JsonSyntaxException {
|
public static CustomControls loadAndConvertIfNecessary(String jsonPath) throws IOException, JsonSyntaxException {
|
||||||
|
|
||||||
String jsonLayoutData = Tools.read(jsonPath);
|
String jsonLayoutData = Tools.read(jsonPath);
|
||||||
try {
|
try {
|
||||||
JSONObject layoutJobj = new JSONObject(jsonLayoutData);
|
JSONObject layoutJobj = new JSONObject(jsonLayoutData);
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ import android.view.*;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
|
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.customcontrols.ControlButtonMenuListener;
|
||||||
import net.kdt.pojavlaunch.customcontrols.ControlData;
|
import net.kdt.pojavlaunch.customcontrols.ControlData;
|
||||||
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
|
import net.kdt.pojavlaunch.customcontrols.ControlLayout;
|
||||||
import net.kdt.pojavlaunch.customcontrols.handleview.*;
|
import net.kdt.pojavlaunch.customcontrols.handleview.*;
|
||||||
import net.kdt.pojavlaunch.*;
|
import net.kdt.pojavlaunch.*;
|
||||||
|
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
|
|
||||||
import org.lwjgl.glfw.*;
|
import org.lwjgl.glfw.*;
|
||||||
|
|
||||||
|
|
@ -22,16 +24,19 @@ import static org.lwjgl.glfw.CallbackBridge.sendMouseButton;
|
||||||
public class ControlButton extends TextView implements ControlInterface {
|
public class ControlButton extends TextView implements ControlInterface {
|
||||||
private final Paint mRectPaint = new Paint();
|
private final Paint mRectPaint = new Paint();
|
||||||
protected ControlData mProperties;
|
protected ControlData mProperties;
|
||||||
|
private final ControlLayout mControlLayout;
|
||||||
|
|
||||||
protected boolean mIsToggled = false;
|
protected boolean mIsToggled = false;
|
||||||
protected boolean mIsPointerOutOfBounds = false;
|
protected boolean mIsPointerOutOfBounds = false;
|
||||||
|
|
||||||
public ControlButton(ControlLayout layout, ControlData properties) {
|
public ControlButton(ControlLayout layout, ControlData properties) {
|
||||||
super(layout.getContext());
|
super(layout.getContext());
|
||||||
|
mControlLayout = layout;
|
||||||
setGravity(Gravity.CENTER);
|
setGravity(Gravity.CENTER);
|
||||||
setAllCaps(true);
|
setAllCaps(LauncherPreferences.PREF_BUTTON_ALL_CAPS);
|
||||||
setTextColor(Color.WHITE);
|
setTextColor(Color.WHITE);
|
||||||
setPadding(4, 4, 4, 4);
|
setPadding(4, 4, 4, 4);
|
||||||
|
setTextSize(14); // Nullify the default size setting
|
||||||
|
|
||||||
//setOnLongClickListener(this);
|
//setOnLongClickListener(this);
|
||||||
|
|
||||||
|
|
@ -104,8 +109,8 @@ public class ControlButton extends TextView implements ControlInterface {
|
||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE:
|
||||||
//Send the event to be taken as a mouse action
|
//Send the event to be taken as a mouse action
|
||||||
if(getProperties().passThruEnabled && CallbackBridge.isGrabbing()){
|
if(getProperties().passThruEnabled && CallbackBridge.isGrabbing()){
|
||||||
MinecraftGLSurface v = getControlLayoutParent().findViewById(R.id.main_game_render_view);
|
View gameSurface = getControlLayoutParent().getGameSurface();
|
||||||
if (v != null) v.dispatchTouchEvent(event);
|
if(gameSurface != null) gameSurface.dispatchTouchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
//If out of bounds
|
//If out of bounds
|
||||||
|
|
@ -144,8 +149,8 @@ public class ControlButton extends TextView implements ControlInterface {
|
||||||
case MotionEvent.ACTION_CANCEL: // 3
|
case MotionEvent.ACTION_CANCEL: // 3
|
||||||
case MotionEvent.ACTION_POINTER_UP: // 6
|
case MotionEvent.ACTION_POINTER_UP: // 6
|
||||||
if(getProperties().passThruEnabled){
|
if(getProperties().passThruEnabled){
|
||||||
MinecraftGLSurface v = getControlLayoutParent().findViewById(R.id.main_game_render_view);
|
View gameSurface = getControlLayoutParent().getGameSurface();
|
||||||
if (v != null) v.dispatchTouchEvent(event);
|
if(gameSurface != null) gameSurface.dispatchTouchEvent(event);
|
||||||
}
|
}
|
||||||
if(mIsPointerOutOfBounds) getControlLayoutParent().onTouch(this, event);
|
if(mIsPointerOutOfBounds) getControlLayoutParent().onTouch(this, event);
|
||||||
mIsPointerOutOfBounds = false;
|
mIsPointerOutOfBounds = false;
|
||||||
|
|
@ -182,6 +187,7 @@ public class ControlButton extends TextView implements ControlInterface {
|
||||||
sendKeyPress(keycode, CallbackBridge.getCurrentMods(), isDown);
|
sendKeyPress(keycode, CallbackBridge.getCurrentMods(), isDown);
|
||||||
CallbackBridge.setModifiers(keycode, isDown);
|
CallbackBridge.setModifiers(keycode, isDown);
|
||||||
}else{
|
}else{
|
||||||
|
Log.i("punjabilauncher", "sendSpecialKey("+keycode+","+isDown+")");
|
||||||
sendSpecialKey(keycode, isDown);
|
sendSpecialKey(keycode, isDown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -220,6 +226,9 @@ public class ControlButton extends TextView implements ControlInterface {
|
||||||
case ControlData.SPECIALBTN_SCROLLUP:
|
case ControlData.SPECIALBTN_SCROLLUP:
|
||||||
if (!isDown) CallbackBridge.sendScroll(0, -1d);
|
if (!isDown) CallbackBridge.sendScroll(0, -1d);
|
||||||
break;
|
break;
|
||||||
|
case ControlData.SPECIALBTN_MENU:
|
||||||
|
mControlLayout.notifyAppMenu();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ public interface ControlInterface extends View.OnLongClickListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
default void injectProperties(){
|
default void injectProperties(){
|
||||||
getControlView().setTranslationZ(10);
|
getControlView().post(() -> getControlView().setTranslationZ(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Inject a touch listener on the view to make editing controls straight forward */
|
/** Inject a touch listener on the view to make editing controls straight forward */
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import android.widget.Toast;
|
||||||
import androidx.core.content.res.ResourcesCompat;
|
import androidx.core.content.res.ResourcesCompat;
|
||||||
import androidx.core.math.MathUtils;
|
import androidx.core.math.MathUtils;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.GrabListener;
|
||||||
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
|
import net.kdt.pojavlaunch.LwjglGlfwKeycode;
|
||||||
import net.kdt.pojavlaunch.R;
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
|
|
@ -37,7 +38,7 @@ import static net.kdt.pojavlaunch.utils.MCOptionUtils.getMcScale;
|
||||||
import static org.lwjgl.glfw.CallbackBridge.sendKeyPress;
|
import static org.lwjgl.glfw.CallbackBridge.sendKeyPress;
|
||||||
import static org.lwjgl.glfw.CallbackBridge.sendMouseButton;
|
import static org.lwjgl.glfw.CallbackBridge.sendMouseButton;
|
||||||
|
|
||||||
public class Gamepad {
|
public class Gamepad implements GrabListener {
|
||||||
|
|
||||||
/* Resolution scaler option, allow downsizing a window */
|
/* Resolution scaler option, allow downsizing a window */
|
||||||
private final float mScaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f;
|
private final float mScaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f;
|
||||||
|
|
@ -67,7 +68,8 @@ public class Gamepad {
|
||||||
private final GamepadMap mMenuMap = GamepadMap.getDefaultMenuMap();
|
private final GamepadMap mMenuMap = GamepadMap.getDefaultMenuMap();
|
||||||
private GamepadMap mCurrentMap = mGameMap;
|
private GamepadMap mCurrentMap = mGameMap;
|
||||||
|
|
||||||
private boolean mLastGrabbingState = true;
|
// The negation is to force trigger the onGrabState
|
||||||
|
private boolean isGrabbing = !CallbackBridge.isGrabbing();
|
||||||
//private final boolean mModifierDigitalTriggers;
|
//private final boolean mModifierDigitalTriggers;
|
||||||
private final boolean mModifierAnalogTriggers;
|
private final boolean mModifierAnalogTriggers;
|
||||||
private boolean mModifierSwappedAxis = true; //Triggers and right stick axis are swapped.
|
private boolean mModifierSwappedAxis = true; //Triggers and right stick axis are swapped.
|
||||||
|
|
@ -84,7 +86,6 @@ public class Gamepad {
|
||||||
Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() {
|
Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void doFrame(long frameTimeNanos) {
|
public void doFrame(long frameTimeNanos) {
|
||||||
updateGrabbingState();
|
|
||||||
tick(frameTimeNanos);
|
tick(frameTimeNanos);
|
||||||
mScreenChoreographer.postFrameCallback(this);
|
mScreenChoreographer.postFrameCallback(this);
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +130,8 @@ public class Gamepad {
|
||||||
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
|
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
|
||||||
|
|
||||||
((ViewGroup)contextView.getParent()).addView(mPointerImageView);
|
((ViewGroup)contextView.getParent()).addView(mPointerImageView);
|
||||||
|
|
||||||
|
CallbackBridge.addGrabListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -278,7 +281,7 @@ public class Gamepad {
|
||||||
private void tick(long frameTimeNanos){
|
private void tick(long frameTimeNanos){
|
||||||
//update mouse position
|
//update mouse position
|
||||||
if(mLastHorizontalValue != 0 || mLastVerticalValue != 0){
|
if(mLastHorizontalValue != 0 || mLastVerticalValue != 0){
|
||||||
GamepadJoystick currentJoystick = mLastGrabbingState ? mLeftJoystick : mRightJoystick;
|
GamepadJoystick currentJoystick = isGrabbing ? mLeftJoystick : mRightJoystick;
|
||||||
|
|
||||||
double acceleration = (mMouseMagnitude - currentJoystick.getDeadzone()) / (1 - currentJoystick.getDeadzone());
|
double acceleration = (mMouseMagnitude - currentJoystick.getDeadzone()) / (1 - currentJoystick.getDeadzone());
|
||||||
acceleration = Math.pow(acceleration, MOUSE_MAX_ACCELERATION);
|
acceleration = Math.pow(acceleration, MOUSE_MAX_ACCELERATION);
|
||||||
|
|
@ -294,7 +297,7 @@ public class Gamepad {
|
||||||
CallbackBridge.mouseX += deltaX;
|
CallbackBridge.mouseX += deltaX;
|
||||||
CallbackBridge.mouseY -= deltaY;
|
CallbackBridge.mouseY -= deltaY;
|
||||||
|
|
||||||
if(!mLastGrabbingState){
|
if(!isGrabbing){
|
||||||
CallbackBridge.mouseX = MathUtils.clamp(CallbackBridge.mouseX, 0, CallbackBridge.windowWidth);
|
CallbackBridge.mouseX = MathUtils.clamp(CallbackBridge.mouseX, 0, CallbackBridge.windowWidth);
|
||||||
CallbackBridge.mouseY = MathUtils.clamp(CallbackBridge.mouseY, 0, CallbackBridge.windowHeight);
|
CallbackBridge.mouseY = MathUtils.clamp(CallbackBridge.mouseY, 0, CallbackBridge.windowHeight);
|
||||||
placePointerView((int) (CallbackBridge.mouseX / mScaleFactor), (int) (CallbackBridge.mouseY/ mScaleFactor));
|
placePointerView((int) (CallbackBridge.mouseX / mScaleFactor), (int) (CallbackBridge.mouseY/ mScaleFactor));
|
||||||
|
|
@ -311,36 +314,8 @@ public class Gamepad {
|
||||||
mLastFrameTime = frameTimeNanos;
|
mLastFrameTime = frameTimeNanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update the grabbing state, and change the currentMap, mouse position and sensibility */
|
|
||||||
private void updateGrabbingState() {
|
|
||||||
boolean lastGrabbingValue = mLastGrabbingState;
|
|
||||||
mLastGrabbingState = CallbackBridge.isGrabbing();
|
|
||||||
if(lastGrabbingValue == mLastGrabbingState) return;
|
|
||||||
|
|
||||||
// Switch grabbing state then
|
|
||||||
mCurrentMap.resetPressedState();
|
|
||||||
if(mLastGrabbingState){
|
|
||||||
mCurrentMap = mGameMap;
|
|
||||||
mPointerImageView.setVisibility(View.INVISIBLE);
|
|
||||||
mMouseSensitivity = 18;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurrentMap = mMenuMap;
|
|
||||||
sendDirectionalKeycode(mCurrentJoystickDirection, false, mGameMap); // removing what we were doing
|
|
||||||
|
|
||||||
mMouse_x = CallbackBridge.windowWidth/2;
|
|
||||||
mMouse_y = CallbackBridge.windowHeight/2;
|
|
||||||
CallbackBridge.sendCursorPos(mMouse_x, mMouse_y);
|
|
||||||
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
|
|
||||||
mPointerImageView.setVisibility(View.VISIBLE);
|
|
||||||
// Sensitivity in menu is MC and HARDWARE resolution dependent
|
|
||||||
mMouseSensitivity = 19 * mScaleFactor / mSensitivityFactor;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateMouseJoystick(MotionEvent event){
|
private void updateMouseJoystick(MotionEvent event){
|
||||||
GamepadJoystick currentJoystick = mLastGrabbingState ? mRightJoystick : mLeftJoystick;
|
GamepadJoystick currentJoystick = isGrabbing ? mRightJoystick : mLeftJoystick;
|
||||||
float horizontalValue = currentJoystick.getHorizontalAxis(event);
|
float horizontalValue = currentJoystick.getHorizontalAxis(event);
|
||||||
float verticalValue = currentJoystick.getVerticalAxis(event);
|
float verticalValue = currentJoystick.getVerticalAxis(event);
|
||||||
if(horizontalValue != mLastHorizontalValue || verticalValue != mLastVerticalValue){
|
if(horizontalValue != mLastHorizontalValue || verticalValue != mLastVerticalValue){
|
||||||
|
|
@ -362,7 +337,7 @@ public class Gamepad {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDirectionalJoystick(MotionEvent event){
|
private void updateDirectionalJoystick(MotionEvent event){
|
||||||
GamepadJoystick currentJoystick = mLastGrabbingState ? mLeftJoystick : mRightJoystick;
|
GamepadJoystick currentJoystick = isGrabbing ? mLeftJoystick : mRightJoystick;
|
||||||
|
|
||||||
int lastJoystickDirection = mCurrentJoystickDirection;
|
int lastJoystickDirection = mCurrentJoystickDirection;
|
||||||
mCurrentJoystickDirection = currentJoystick.getHeightDirection(event);
|
mCurrentJoystickDirection = currentJoystick.getHeightDirection(event);
|
||||||
|
|
@ -446,4 +421,32 @@ public class Gamepad {
|
||||||
mPointerImageView.setX(x - mPointerImageView.getWidth()/2);
|
mPointerImageView.setX(x - mPointerImageView.getWidth()/2);
|
||||||
mPointerImageView.setY(y - mPointerImageView.getHeight()/2);
|
mPointerImageView.setY(y - mPointerImageView.getHeight()/2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Update the grabbing state, and change the currentMap, mouse position and sensibility */
|
||||||
|
@Override
|
||||||
|
public void onGrabState(boolean isGrabbing) {
|
||||||
|
boolean lastGrabbingValue = this.isGrabbing;
|
||||||
|
this.isGrabbing = isGrabbing;
|
||||||
|
if(lastGrabbingValue == isGrabbing) return;
|
||||||
|
|
||||||
|
// Switch grabbing state then
|
||||||
|
mCurrentMap.resetPressedState();
|
||||||
|
if(isGrabbing){
|
||||||
|
mCurrentMap = mGameMap;
|
||||||
|
mPointerImageView.setVisibility(View.INVISIBLE);
|
||||||
|
mMouseSensitivity = 18;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentMap = mMenuMap;
|
||||||
|
sendDirectionalKeycode(mCurrentJoystickDirection, false, mGameMap); // removing what we were doing
|
||||||
|
|
||||||
|
mMouse_x = CallbackBridge.windowWidth/2;
|
||||||
|
mMouse_y = CallbackBridge.windowHeight/2;
|
||||||
|
CallbackBridge.sendCursorPos(mMouse_x, mMouse_y);
|
||||||
|
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
|
||||||
|
mPointerImageView.setVisibility(View.VISIBLE);
|
||||||
|
// Sensitivity in menu is MC and HARDWARE resolution dependent
|
||||||
|
mMouseSensitivity = 19 * mScaleFactor / mSensitivityFactor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ public class ControlHandleView extends View {
|
||||||
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(size, size);
|
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(size, size);
|
||||||
setLayoutParams(params);
|
setLayoutParams(params);
|
||||||
setBackground(mDrawable);
|
setBackground(mDrawable);
|
||||||
setElevation(3);
|
setTranslationZ(10.5F);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setControlButton(ControlInterface controlInterface){
|
public void setControlButton(ControlInterface controlInterface){
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
@ -63,10 +64,13 @@ public class EditControlPopup {
|
||||||
if(internalChanges) return;
|
if(internalChanges) return;
|
||||||
|
|
||||||
internalChanges = true;
|
internalChanges = true;
|
||||||
if(right != (int)safeParseFloat(mWidthEditText.getText().toString())){
|
int width = (int)(safeParseFloat(mWidthEditText.getText().toString()));
|
||||||
|
|
||||||
|
if(width >= 0 && Math.abs(right - width) > 1){
|
||||||
mWidthEditText.setText(String.valueOf(right - left));
|
mWidthEditText.setText(String.valueOf(right - left));
|
||||||
}
|
}
|
||||||
if(bottom != (int) safeParseFloat(mHeightEditText.getText().toString())){
|
int height = (int)(safeParseFloat(mHeightEditText.getText().toString()));
|
||||||
|
if(height >= 0 && Math.abs(bottom - height) > 1){
|
||||||
mHeightEditText.setText(String.valueOf(bottom - top));
|
mHeightEditText.setText(String.valueOf(bottom - top));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,7 +102,8 @@ public class EditControlPopup {
|
||||||
|
|
||||||
mColorSelector = new ColorSelector(context, parent, null);
|
mColorSelector = new ColorSelector(context, parent, null);
|
||||||
mColorSelector.getRootView().setElevation(11);
|
mColorSelector.getRootView().setElevation(11);
|
||||||
mColorSelector.getRootView().setX(-context.getResources().getDimensionPixelOffset(R.dimen._230sdp));
|
mColorSelector.getRootView().setTranslationZ(11);
|
||||||
|
mColorSelector.getRootView().setX(-context.getResources().getDimensionPixelOffset(R.dimen._280sdp));
|
||||||
|
|
||||||
mEditPopupAnimator = ObjectAnimator.ofFloat(mScrollView, "x", 0).setDuration(1000);
|
mEditPopupAnimator = ObjectAnimator.ofFloat(mScrollView, "x", 0).setDuration(1000);
|
||||||
mColorEditorAnimator = ObjectAnimator.ofFloat(mColorSelector.getRootView(), "x", 0).setDuration(1000);
|
mColorEditorAnimator = ObjectAnimator.ofFloat(mColorSelector.getRootView(), "x", 0).setDuration(1000);
|
||||||
|
|
@ -107,7 +112,8 @@ public class EditControlPopup {
|
||||||
mColorEditorAnimator.setInterpolator(decelerate);
|
mColorEditorAnimator.setInterpolator(decelerate);
|
||||||
|
|
||||||
mScrollView.setElevation(10);
|
mScrollView.setElevation(10);
|
||||||
mScrollView.setX(-context.getResources().getDimensionPixelOffset(R.dimen._230sdp));
|
mScrollView.setTranslationZ(10);
|
||||||
|
mScrollView.setX(-context.getResources().getDimensionPixelOffset(R.dimen._280sdp));
|
||||||
|
|
||||||
bindLayout();
|
bindLayout();
|
||||||
loadAdapter();
|
loadAdapter();
|
||||||
|
|
@ -163,8 +169,7 @@ public class EditControlPopup {
|
||||||
}
|
}
|
||||||
|
|
||||||
mDisplayingColor = true;
|
mDisplayingColor = true;
|
||||||
if(color != -1)
|
mColorSelector.show(color == -1 ? Color.WHITE : color);
|
||||||
mColorSelector.show(color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Slide out the layout */
|
/** Slide out the layout */
|
||||||
|
|
@ -211,7 +216,6 @@ public class EditControlPopup {
|
||||||
mAdapter = new ArrayAdapter<>(mRootView.getContext(), R.layout.item_centered_textview);
|
mAdapter = new ArrayAdapter<>(mRootView.getContext(), R.layout.item_centered_textview);
|
||||||
mSpecialArray = ControlData.buildSpecialButtonArray();
|
mSpecialArray = ControlData.buildSpecialButtonArray();
|
||||||
for (int i = 0; i < mSpecialArray.length; i++) {
|
for (int i = 0; i < mSpecialArray.length; i++) {
|
||||||
//TODO this will break for sure
|
|
||||||
mSpecialArray[i] = "SPECIAL_" + mSpecialArray[i];
|
mSpecialArray[i] = "SPECIAL_" + mSpecialArray[i];
|
||||||
}
|
}
|
||||||
Collections.reverse(Arrays.asList(mSpecialArray));
|
Collections.reverse(Arrays.asList(mSpecialArray));
|
||||||
|
|
@ -386,8 +390,11 @@ public class EditControlPopup {
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
if(internalChanges) return;
|
if(internalChanges) return;
|
||||||
|
|
||||||
mCurrentlyEditedButton.getProperties().setWidth(safeParseFloat(s.toString()));
|
float width = safeParseFloat(s.toString());
|
||||||
mCurrentlyEditedButton.updateProperties();
|
if(width >= 0){
|
||||||
|
mCurrentlyEditedButton.getProperties().setWidth(width);
|
||||||
|
mCurrentlyEditedButton.updateProperties();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -401,8 +408,11 @@ public class EditControlPopup {
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
if(internalChanges) return;
|
if(internalChanges) return;
|
||||||
|
|
||||||
mCurrentlyEditedButton.getProperties().setHeight(safeParseFloat(s.toString()));
|
float height = safeParseFloat(s.toString());
|
||||||
mCurrentlyEditedButton.updateProperties();
|
if(height >= 0){
|
||||||
|
mCurrentlyEditedButton.getProperties().setHeight(height);
|
||||||
|
mCurrentlyEditedButton.updateProperties();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -522,7 +532,7 @@ public class EditControlPopup {
|
||||||
}
|
}
|
||||||
|
|
||||||
private float safeParseFloat(String string){
|
private float safeParseFloat(String string){
|
||||||
float out = 10; // 10 px as a fallback
|
float out = -1; // -1
|
||||||
try {
|
try {
|
||||||
out = Float.parseFloat(string);
|
out = Float.parseFloat(string);
|
||||||
}catch (NumberFormatException e){
|
}catch (NumberFormatException e){
|
||||||
|
|
|
||||||
|
|
@ -94,11 +94,8 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
|
||||||
*/
|
*/
|
||||||
public boolean switchKeyboardState(){
|
public boolean switchKeyboardState(){
|
||||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
|
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(INPUT_METHOD_SERVICE);
|
||||||
//If an hard keyboard is present, never trigger the soft one
|
// Allow, regardless of whether or not a hardware keyboard is declared
|
||||||
if(hasFocus()
|
if(hasFocus()){
|
||||||
|| (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY
|
|
||||||
&& getResources().getConfiguration().hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES)){
|
|
||||||
imm.hideSoftInputFromWindow(getWindowToken(), 0);
|
|
||||||
clear();
|
clear();
|
||||||
disable();
|
disable();
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -130,7 +127,6 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
setVisibility(VISIBLE);
|
setVisibility(VISIBLE);
|
||||||
requestFocus();
|
requestFocus();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Lose ability to exist, take focus and have some text being input */
|
/** Lose ability to exist, take focus and have some text being input */
|
||||||
|
|
@ -139,6 +135,7 @@ public class TouchCharInput extends androidx.appcompat.widget.AppCompatEditText
|
||||||
setVisibility(GONE);
|
setVisibility(GONE);
|
||||||
clearFocus();
|
clearFocus();
|
||||||
setEnabled(false);
|
setEnabled(false);
|
||||||
|
//setFocusable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send the enter key. */
|
/** Send the enter key. */
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package net.kdt.pojavlaunch.fragments;
|
package net.kdt.pojavlaunch.fragments;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.provider.DocumentsContract;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
|
|
@ -19,6 +21,8 @@ import net.kdt.pojavlaunch.extra.ExtraConstants;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraCore;
|
import net.kdt.pojavlaunch.extra.ExtraCore;
|
||||||
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
public class MainMenuFragment extends Fragment {
|
public class MainMenuFragment extends Fragment {
|
||||||
public static final String TAG = "MainMenuFragment";
|
public static final String TAG = "MainMenuFragment";
|
||||||
|
|
||||||
|
|
@ -31,6 +35,7 @@ public class MainMenuFragment extends Fragment {
|
||||||
Button mNewsButton = view.findViewById(R.id.news_button);
|
Button mNewsButton = view.findViewById(R.id.news_button);
|
||||||
Button mCustomControlButton = view.findViewById(R.id.custom_control_button);
|
Button mCustomControlButton = view.findViewById(R.id.custom_control_button);
|
||||||
Button mInstallJarButton = view.findViewById(R.id.install_jar_button);
|
Button mInstallJarButton = view.findViewById(R.id.install_jar_button);
|
||||||
|
Button mShareLogsButton = view.findViewById(R.id.share_logs_button);
|
||||||
|
|
||||||
ImageButton mEditProfileButton = view.findViewById(R.id.edit_profile_button);
|
ImageButton mEditProfileButton = view.findViewById(R.id.edit_profile_button);
|
||||||
Button mPlayButton = view.findViewById(R.id.play_button);
|
Button mPlayButton = view.findViewById(R.id.play_button);
|
||||||
|
|
@ -46,6 +51,19 @@ public class MainMenuFragment extends Fragment {
|
||||||
|
|
||||||
mPlayButton.setOnClickListener(v -> ExtraCore.setValue(ExtraConstants.LAUNCH_GAME, true));
|
mPlayButton.setOnClickListener(v -> ExtraCore.setValue(ExtraConstants.LAUNCH_GAME, true));
|
||||||
|
|
||||||
|
mShareLogsButton.setOnClickListener((v) -> {
|
||||||
|
Uri contentUri = DocumentsContract.buildDocumentUri(getString(R.string.storageProviderAuthorities), Tools.DIR_GAME_HOME + "/latestlog.txt");
|
||||||
|
|
||||||
|
Intent shareIntent = new Intent();
|
||||||
|
shareIntent.setAction(Intent.ACTION_SEND);
|
||||||
|
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
|
||||||
|
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
shareIntent.setType("text/plain");
|
||||||
|
|
||||||
|
Intent sendIntent = Intent.createChooser(shareIntent, "latestlog.txt");
|
||||||
|
startActivity(sendIntent);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
private void runInstallerWithConfirmation(boolean isCustomArgs) {
|
private void runInstallerWithConfirmation(boolean isCustomArgs) {
|
||||||
if (ProgressKeeper.getTaskCount() == 0)
|
if (ProgressKeeper.getTaskCount() == 0)
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ public class MultiRTUtils {
|
||||||
public static Runtime read(String name) {
|
public static Runtime read(String name) {
|
||||||
if(sCache.containsKey(name)) return sCache.get(name);
|
if(sCache.containsKey(name)) return sCache.get(name);
|
||||||
Runtime returnRuntime;
|
Runtime returnRuntime;
|
||||||
File release = new File(RUNTIME_FOLDER,"/"+name+"/release");
|
File release = new File(RUNTIME_FOLDER,name+"/release");
|
||||||
if(!release.exists()) {
|
if(!release.exists()) {
|
||||||
return new Runtime(name);
|
return new Runtime(name);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,127 +0,0 @@
|
||||||
package net.kdt.pojavlaunch.prefs;
|
|
||||||
|
|
||||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.DEFAULT_PREF;
|
|
||||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_CONTROL_BOTTOM_OFFSET;
|
|
||||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_CONTROL_LEFT_OFFSET;
|
|
||||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_CONTROL_RIGHT_OFFSET;
|
|
||||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_CONTROL_TOP_OFFSET;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.widget.SeekBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
|
||||||
|
|
||||||
import net.kdt.pojavlaunch.R;
|
|
||||||
|
|
||||||
/** Custom preference class displaying a dialog */
|
|
||||||
public class ControlOffsetPreference extends Preference {
|
|
||||||
|
|
||||||
private AlertDialog mPreferenceDialog;
|
|
||||||
|
|
||||||
public ControlOffsetPreference(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControlOffsetPreference(Context context) {
|
|
||||||
super(context);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onClick() {
|
|
||||||
mPreferenceDialog.show();
|
|
||||||
|
|
||||||
SeekBar topOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_top_seekbar);
|
|
||||||
SeekBar rightOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_right_seekbar);
|
|
||||||
SeekBar bottomOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_bottom_seekbar);
|
|
||||||
SeekBar leftOffsetSeekbar = mPreferenceDialog.findViewById(R.id.control_offset_left_seekbar);
|
|
||||||
|
|
||||||
TextView topOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_top_textview);
|
|
||||||
TextView rightOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_right_textview);
|
|
||||||
TextView bottomOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_bottom_textview);
|
|
||||||
TextView leftOffsetTextView = mPreferenceDialog.findViewById(R.id.control_offset_left_textview);
|
|
||||||
|
|
||||||
SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
|
|
||||||
@Override
|
|
||||||
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
|
|
||||||
if(seekBar == topOffsetSeekbar){
|
|
||||||
String text = String.format("%s %d%s", getContext().getString(R.string.control_top_offset), i, " px");
|
|
||||||
topOffsetTextView.setText(text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(seekBar == rightOffsetSeekbar){
|
|
||||||
String text = String.format("%s %d%s", getContext().getString(R.string.control_right_offset), i, " px");
|
|
||||||
rightOffsetTextView.setText(text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(seekBar == bottomOffsetSeekbar){
|
|
||||||
String text = String.format("%s %d%s", getContext().getString(R.string.control_bottom_offset), i, " px");
|
|
||||||
bottomOffsetTextView.setText(text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(seekBar == leftOffsetSeekbar){
|
|
||||||
String text = String.format("%s %d%s", getContext().getString(R.string.control_left_offset), i, " px");
|
|
||||||
leftOffsetTextView.setText(text);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {}
|
|
||||||
@Override
|
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
topOffsetSeekbar.setOnSeekBarChangeListener(seekBarChangeListener);
|
|
||||||
rightOffsetSeekbar.setOnSeekBarChangeListener(seekBarChangeListener);
|
|
||||||
bottomOffsetSeekbar.setOnSeekBarChangeListener(seekBarChangeListener);
|
|
||||||
leftOffsetSeekbar.setOnSeekBarChangeListener(seekBarChangeListener);
|
|
||||||
|
|
||||||
topOffsetSeekbar.setProgress(PREF_CONTROL_TOP_OFFSET);
|
|
||||||
rightOffsetSeekbar.setProgress(PREF_CONTROL_RIGHT_OFFSET);
|
|
||||||
bottomOffsetSeekbar.setProgress(PREF_CONTROL_BOTTOM_OFFSET);
|
|
||||||
leftOffsetSeekbar.setProgress(PREF_CONTROL_LEFT_OFFSET);
|
|
||||||
|
|
||||||
seekBarChangeListener.onProgressChanged(topOffsetSeekbar, PREF_CONTROL_TOP_OFFSET, false);
|
|
||||||
seekBarChangeListener.onProgressChanged(rightOffsetSeekbar, PREF_CONTROL_RIGHT_OFFSET, false);
|
|
||||||
seekBarChangeListener.onProgressChanged(bottomOffsetSeekbar, PREF_CONTROL_BOTTOM_OFFSET, false);
|
|
||||||
seekBarChangeListener.onProgressChanged(leftOffsetSeekbar, PREF_CONTROL_LEFT_OFFSET, false);
|
|
||||||
|
|
||||||
// Custom writing to preferences
|
|
||||||
mPreferenceDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(view -> {
|
|
||||||
DEFAULT_PREF.edit().putInt("controlTopOffset", topOffsetSeekbar.getProgress()).apply();
|
|
||||||
DEFAULT_PREF.edit().putInt("controlRightOffset", rightOffsetSeekbar.getProgress()).apply();
|
|
||||||
DEFAULT_PREF.edit().putInt("controlBottomOffset", bottomOffsetSeekbar.getProgress()).apply();
|
|
||||||
DEFAULT_PREF.edit().putInt("controlLeftOffset", leftOffsetSeekbar.getProgress()).apply();
|
|
||||||
|
|
||||||
|
|
||||||
mPreferenceDialog.dismiss();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(){
|
|
||||||
// Setup visual values
|
|
||||||
if(getTitle() == null){
|
|
||||||
setTitle(R.string.preference_control_offset_title);
|
|
||||||
setSummary(R.string.preference_control_offset_description);
|
|
||||||
}
|
|
||||||
if(getIcon() == null){
|
|
||||||
setIcon(android.R.drawable.radiobutton_off_background);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare Alert dialog
|
|
||||||
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext());
|
|
||||||
dialogBuilder.setView(R.layout.dialog_control_offset_preference);
|
|
||||||
dialogBuilder.setTitle(getContext().getString(R.string.control_offset_title));
|
|
||||||
|
|
||||||
dialogBuilder.setPositiveButton(android.R.string.ok, null);
|
|
||||||
dialogBuilder.setNegativeButton(android.R.string.cancel, null);
|
|
||||||
|
|
||||||
mPreferenceDialog = dialogBuilder.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -3,6 +3,8 @@ package net.kdt.pojavlaunch.prefs;
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static android.os.Build.VERSION_CODES.P;
|
import static android.os.Build.VERSION_CODES.P;
|
||||||
|
|
||||||
|
import static net.kdt.pojavlaunch.Architecture.is32BitsDevice;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
|
@ -41,15 +43,22 @@ public class LauncherPreferences {
|
||||||
public static float PREF_MOUSESPEED = 1f;
|
public static float PREF_MOUSESPEED = 1f;
|
||||||
public static int PREF_RAM_ALLOCATION;
|
public static int PREF_RAM_ALLOCATION;
|
||||||
public static String PREF_DEFAULT_RUNTIME;
|
public static String PREF_DEFAULT_RUNTIME;
|
||||||
public static int PREF_CONTROL_TOP_OFFSET = 0;
|
|
||||||
public static int PREF_CONTROL_RIGHT_OFFSET = 0;
|
|
||||||
public static int PREF_CONTROL_BOTTOM_OFFSET = 0;
|
|
||||||
public static int PREF_CONTROL_LEFT_OFFSET = 0;
|
|
||||||
public static boolean PREF_SUSTAINED_PERFORMANCE = false;
|
public static boolean PREF_SUSTAINED_PERFORMANCE = false;
|
||||||
public static boolean PREF_VIRTUAL_MOUSE_START = false;
|
public static boolean PREF_VIRTUAL_MOUSE_START = false;
|
||||||
public static boolean PREF_ARC_CAPES = false;
|
public static boolean PREF_ARC_CAPES = false;
|
||||||
public static boolean PREF_USE_ALTERNATE_SURFACE = true;
|
public static boolean PREF_USE_ALTERNATE_SURFACE = true;
|
||||||
|
public static boolean PREF_JAVA_SANDBOX = true;
|
||||||
public static int PREF_SCALE_FACTOR = 100;
|
public static int PREF_SCALE_FACTOR = 100;
|
||||||
|
public static boolean PREF_ENALBE_GYRO = false;
|
||||||
|
public static float PREF_GYRO_SENSITIVITY = 1f;
|
||||||
|
public static int PREF_GYRO_SAMPLE_RATE = 16;
|
||||||
|
|
||||||
|
public static boolean PREF_GYRO_INVERT_X = false;
|
||||||
|
|
||||||
|
public static boolean PREF_GYRO_INVERT_Y = false;
|
||||||
|
public static boolean PREF_FORCE_VSYNC = false;
|
||||||
|
|
||||||
|
public static boolean PREF_BUTTON_ALL_CAPS = true;
|
||||||
|
|
||||||
|
|
||||||
public static void loadPreferences(Context ctx) {
|
public static void loadPreferences(Context ctx) {
|
||||||
|
|
@ -74,15 +83,19 @@ public class LauncherPreferences {
|
||||||
PREF_DISABLE_GESTURES = DEFAULT_PREF.getBoolean("disableGestures",false);
|
PREF_DISABLE_GESTURES = DEFAULT_PREF.getBoolean("disableGestures",false);
|
||||||
PREF_RAM_ALLOCATION = DEFAULT_PREF.getInt("allocation", findBestRAMAllocation(ctx));
|
PREF_RAM_ALLOCATION = DEFAULT_PREF.getInt("allocation", findBestRAMAllocation(ctx));
|
||||||
PREF_CUSTOM_JAVA_ARGS = DEFAULT_PREF.getString("javaArgs", "");
|
PREF_CUSTOM_JAVA_ARGS = DEFAULT_PREF.getString("javaArgs", "");
|
||||||
PREF_CONTROL_TOP_OFFSET = DEFAULT_PREF.getInt("controlTopOffset", 0);
|
|
||||||
PREF_CONTROL_RIGHT_OFFSET = DEFAULT_PREF.getInt("controlRightOffset", 0);
|
|
||||||
PREF_CONTROL_BOTTOM_OFFSET = DEFAULT_PREF.getInt("controlBottomOffset", 0);
|
|
||||||
PREF_CONTROL_LEFT_OFFSET = DEFAULT_PREF.getInt("controlLeftOffset", 0);
|
|
||||||
PREF_SUSTAINED_PERFORMANCE = DEFAULT_PREF.getBoolean("sustainedPerformance", false);
|
PREF_SUSTAINED_PERFORMANCE = DEFAULT_PREF.getBoolean("sustainedPerformance", false);
|
||||||
PREF_VIRTUAL_MOUSE_START = DEFAULT_PREF.getBoolean("mouse_start", false);
|
PREF_VIRTUAL_MOUSE_START = DEFAULT_PREF.getBoolean("mouse_start", false);
|
||||||
PREF_ARC_CAPES = DEFAULT_PREF.getBoolean("arc_capes",false);
|
PREF_ARC_CAPES = DEFAULT_PREF.getBoolean("arc_capes",false);
|
||||||
PREF_USE_ALTERNATE_SURFACE = DEFAULT_PREF.getBoolean("alternate_surface", false);
|
PREF_USE_ALTERNATE_SURFACE = DEFAULT_PREF.getBoolean("alternate_surface", false);
|
||||||
|
PREF_JAVA_SANDBOX = DEFAULT_PREF.getBoolean("java_sandbox", true);
|
||||||
PREF_SCALE_FACTOR = DEFAULT_PREF.getInt("resolutionRatio", 100);
|
PREF_SCALE_FACTOR = DEFAULT_PREF.getInt("resolutionRatio", 100);
|
||||||
|
PREF_ENALBE_GYRO = DEFAULT_PREF.getBoolean("enableGyro", false);
|
||||||
|
PREF_GYRO_SENSITIVITY = ((float)DEFAULT_PREF.getInt("gyroSensitivity", 100))/100f;
|
||||||
|
PREF_GYRO_SAMPLE_RATE = DEFAULT_PREF.getInt("gyroSampleRate", 16);
|
||||||
|
PREF_GYRO_INVERT_X = DEFAULT_PREF.getBoolean("gyroInvertX", false);
|
||||||
|
PREF_GYRO_INVERT_Y = DEFAULT_PREF.getBoolean("gyroInvertY", false);
|
||||||
|
PREF_FORCE_VSYNC = DEFAULT_PREF.getBoolean("force_vsync", false);
|
||||||
|
PREF_BUTTON_ALL_CAPS = DEFAULT_PREF.getBoolean("buttonAllCaps", true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (PREF_CUSTOM_JAVA_ARGS.isEmpty()) {
|
if (PREF_CUSTOM_JAVA_ARGS.isEmpty()) {
|
||||||
|
|
@ -146,6 +159,9 @@ public class LauncherPreferences {
|
||||||
if (deviceRam < 1024) return 300;
|
if (deviceRam < 1024) return 300;
|
||||||
if (deviceRam < 1536) return 450;
|
if (deviceRam < 1536) return 450;
|
||||||
if (deviceRam < 2048) return 600;
|
if (deviceRam < 2048) return 600;
|
||||||
|
// Limit the max for 32 bits devices more harshly
|
||||||
|
if (is32BitsDevice()) return 700;
|
||||||
|
|
||||||
if (deviceRam < 3064) return 936;
|
if (deviceRam < 3064) return 936;
|
||||||
if (deviceRam < 4096) return 1148;
|
if (deviceRam < 4096) return 1148;
|
||||||
if (deviceRam < 6144) return 1536;
|
if (deviceRam < 6144) return 1536;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,29 @@
|
||||||
package net.kdt.pojavlaunch.prefs.screens;
|
package net.kdt.pojavlaunch.prefs.screens;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceCategory;
|
||||||
|
import androidx.preference.SwitchPreference;
|
||||||
|
|
||||||
import net.kdt.pojavlaunch.R;
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.prefs.CustomSeekBarPreference;
|
import net.kdt.pojavlaunch.prefs.CustomSeekBarPreference;
|
||||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
|
|
||||||
public class LauncherPreferenceControlFragment extends LauncherPreferenceFragment {
|
public class LauncherPreferenceControlFragment extends LauncherPreferenceFragment {
|
||||||
|
private boolean mGyroAvailable = false;
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle b, String str) {
|
public void onCreatePreferences(Bundle b, String str) {
|
||||||
// Get values
|
// Get values
|
||||||
int longPressTrigger = LauncherPreferences.PREF_LONGPRESS_TRIGGER;
|
int longPressTrigger = LauncherPreferences.PREF_LONGPRESS_TRIGGER;
|
||||||
int prefButtonSize = (int) LauncherPreferences.PREF_BUTTONSIZE;
|
int prefButtonSize = (int) LauncherPreferences.PREF_BUTTONSIZE;
|
||||||
int mouseScale = (int) LauncherPreferences.PREF_MOUSESCALE;
|
int mouseScale = (int) LauncherPreferences.PREF_MOUSESCALE;
|
||||||
|
int gyroSampleRate = LauncherPreferences.PREF_GYRO_SAMPLE_RATE;
|
||||||
float mouseSpeed = LauncherPreferences.PREF_MOUSESPEED;
|
float mouseSpeed = LauncherPreferences.PREF_MOUSESPEED;
|
||||||
|
float gyroSpeed = LauncherPreferences.PREF_GYRO_SENSITIVITY;
|
||||||
|
|
||||||
//Triggers a write for some reason which resets the value
|
//Triggers a write for some reason which resets the value
|
||||||
addPreferencesFromResource(R.xml.pref_control);
|
addPreferencesFromResource(R.xml.pref_control);
|
||||||
|
|
@ -40,7 +48,21 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen
|
||||||
seek6.setValue((int)(mouseSpeed *100f));
|
seek6.setValue((int)(mouseSpeed *100f));
|
||||||
seek6.setSuffix(" %");
|
seek6.setSuffix(" %");
|
||||||
|
|
||||||
|
Context context = getContext();
|
||||||
|
if(context != null) {
|
||||||
|
mGyroAvailable = ((SensorManager)context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null;
|
||||||
|
}
|
||||||
|
PreferenceCategory gyroCategory = (PreferenceCategory) findPreference("gyroCategory");
|
||||||
|
gyroCategory.setVisible(mGyroAvailable);
|
||||||
|
|
||||||
|
CustomSeekBarPreference gyroSensitivitySeek = findPreference("gyroSensitivity");
|
||||||
|
gyroSensitivitySeek.setRange(25, 300);
|
||||||
|
gyroSensitivitySeek.setValue((int) (gyroSpeed*100f));
|
||||||
|
gyroSensitivitySeek.setSuffix(" %");
|
||||||
|
CustomSeekBarPreference gyroSampleRateSeek = findPreference("gyroSampleRate");
|
||||||
|
gyroSampleRateSeek.setRange(5, 50);
|
||||||
|
gyroSampleRateSeek.setValue(gyroSampleRate);
|
||||||
|
gyroSampleRateSeek.setSuffix(" ms");
|
||||||
computeVisibility();
|
computeVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,8 +73,11 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen
|
||||||
}
|
}
|
||||||
|
|
||||||
private void computeVisibility(){
|
private void computeVisibility(){
|
||||||
CustomSeekBarPreference seek2 = findPreference("timeLongPressTrigger");
|
findPreference("timeLongPressTrigger").setVisible(!LauncherPreferences.PREF_DISABLE_GESTURES);
|
||||||
seek2.setVisible(!LauncherPreferences.PREF_DISABLE_GESTURES);
|
findPreference("gyroSensitivity").setVisible(LauncherPreferences.PREF_ENALBE_GYRO);
|
||||||
|
findPreference("gyroSampleRate").setVisible(LauncherPreferences.PREF_ENALBE_GYRO);
|
||||||
|
findPreference("gyroInvertX").setVisible(LauncherPreferences.PREF_ENALBE_GYRO);
|
||||||
|
findPreference("gyroInvertY").setVisible(LauncherPreferences.PREF_ENALBE_GYRO);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ public class LauncherPreferenceJavaFragment extends LauncherPreferenceFragment {
|
||||||
CustomSeekBarPreference seek7 = findPreference("allocation");
|
CustomSeekBarPreference seek7 = findPreference("allocation");
|
||||||
seek7.setMin(256);
|
seek7.setMin(256);
|
||||||
|
|
||||||
if(is32BitsDevice()) maxRAM = Math.min(1100, deviceRam);
|
if(is32BitsDevice() || deviceRam < 2048) maxRAM = Math.min(1000, deviceRam);
|
||||||
else maxRAM = deviceRam - (deviceRam < 3064 ? 800 : 1024); //To have a minimum for the device to breathe
|
else maxRAM = deviceRam - (deviceRam < 3064 ? 800 : 1024); //To have a minimum for the device to breathe
|
||||||
|
|
||||||
seek7.setMax(maxRAM);
|
seek7.setMax(maxRAM);
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,17 @@ package net.kdt.pojavlaunch.prefs.screens;
|
||||||
|
|
||||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
|
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_NOTCH_SIZE;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import androidx.preference.SwitchPreference;
|
import androidx.preference.SwitchPreference;
|
||||||
|
import androidx.preference.SwitchPreferenceCompat;
|
||||||
|
|
||||||
import net.kdt.pojavlaunch.R;
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.prefs.CustomSeekBarPreference;
|
import net.kdt.pojavlaunch.prefs.CustomSeekBarPreference;
|
||||||
|
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fragment for any settings video related
|
* Fragment for any settings video related
|
||||||
|
|
@ -34,5 +37,17 @@ public class LauncherPreferenceVideoFragment extends LauncherPreferenceFragment
|
||||||
// Sustained performance is only available since Nougat
|
// Sustained performance is only available since Nougat
|
||||||
SwitchPreference sustainedPerfSwitch = findPreference("sustainedPerformance");
|
SwitchPreference sustainedPerfSwitch = findPreference("sustainedPerformance");
|
||||||
sustainedPerfSwitch.setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N);
|
sustainedPerfSwitch.setVisible(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N);
|
||||||
|
computeVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences p, String s) {
|
||||||
|
super.onSharedPreferenceChanged(p, s);
|
||||||
|
computeVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeVisibility(){
|
||||||
|
SwitchPreferenceCompat preference = findPreference("force_vsync");
|
||||||
|
preference.setVisible(LauncherPreferences.PREF_USE_ALTERNATE_SURFACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ public class ProfileAdapter extends BaseAdapter {
|
||||||
mProfiles = new HashMap<>(LauncherProfiles.mainProfileJson.profiles);
|
mProfiles = new HashMap<>(LauncherProfiles.mainProfileJson.profiles);
|
||||||
if(enableCreateButton) {
|
if(enableCreateButton) {
|
||||||
mCreateProfile = new MinecraftProfile();
|
mCreateProfile = new MinecraftProfile();
|
||||||
mCreateProfile.name = "Create new profile";
|
mCreateProfile.name = context.getString(R.string.create_profile);
|
||||||
mCreateProfile.lastVersionId = null;
|
mCreateProfile.lastVersionId = null;
|
||||||
}
|
}
|
||||||
mProfileList = new ArrayList<>(Arrays.asList(mProfiles.keySet().toArray(new String[0])));
|
mProfileList = new ArrayList<>(Arrays.asList(mProfiles.keySet().toArray(new String[0])));
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
package net.kdt.pojavlaunch.progresskeeper;
|
package net.kdt.pojavlaunch.progresskeeper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.List;
|
||||||
|
|
||||||
public class ProgressKeeper {
|
public class ProgressKeeper {
|
||||||
private static final ConcurrentHashMap<String, ConcurrentLinkedQueue<ProgressListener>> sProgressListeners = new ConcurrentHashMap<>();
|
private static final HashMap<String, List<ProgressListener>> sProgressListeners = new HashMap<>();
|
||||||
private static final ConcurrentHashMap<String, ProgressState> sProgressStates = new ConcurrentHashMap<>();
|
private static final HashMap<String, ProgressState> sProgressStates = new HashMap<>();
|
||||||
private static final ArrayList<TaskCountListener> sTaskCountListeners = new ArrayList<>();
|
private static final List<TaskCountListener> sTaskCountListeners = new ArrayList<>();
|
||||||
|
|
||||||
public static void submitProgress(String progressRecord, int progress, int resid, Object... va) {
|
public static synchronized void submitProgress(String progressRecord, int progress, int resid, Object... va) {
|
||||||
ProgressState progressState = sProgressStates.get(progressRecord);
|
ProgressState progressState = sProgressStates.get(progressRecord);
|
||||||
boolean shouldCallStarted = progressState == null;
|
boolean shouldCallStarted = progressState == null;
|
||||||
boolean shouldCallEnded = resid == -1 && progress == -1;
|
boolean shouldCallEnded = resid == -1 && progress == -1;
|
||||||
|
|
@ -27,7 +27,7 @@ public class ProgressKeeper {
|
||||||
progressState.varArg = va;
|
progressState.varArg = va;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentLinkedQueue<ProgressListener> progressListeners = sProgressListeners.get(progressRecord);
|
List<ProgressListener> progressListeners = sProgressListeners.get(progressRecord);
|
||||||
if(progressListeners != null)
|
if(progressListeners != null)
|
||||||
for(ProgressListener listener : progressListeners) {
|
for(ProgressListener listener : progressListeners) {
|
||||||
if(shouldCallStarted) listener.onProgressStarted();
|
if(shouldCallStarted) listener.onProgressStarted();
|
||||||
|
|
@ -36,14 +36,14 @@ public class ProgressKeeper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateTaskCount() {
|
private static synchronized void updateTaskCount() {
|
||||||
int count = sProgressStates.size();
|
int count = sProgressStates.size();
|
||||||
for(TaskCountListener listener : sTaskCountListeners) {
|
for(TaskCountListener listener : sTaskCountListeners) {
|
||||||
listener.onUpdateTaskCount(count);
|
listener.onUpdateTaskCount(count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addListener(String progressRecord, ProgressListener listener) {
|
public static synchronized void addListener(String progressRecord, ProgressListener listener) {
|
||||||
ProgressState state = sProgressStates.get(progressRecord);
|
ProgressState state = sProgressStates.get(progressRecord);
|
||||||
if(state != null && (state.resid != -1 || state.progress != -1)) {
|
if(state != null && (state.resid != -1 || state.progress != -1)) {
|
||||||
listener.onProgressStarted();
|
listener.onProgressStarted();
|
||||||
|
|
@ -51,28 +51,53 @@ public class ProgressKeeper {
|
||||||
}else{
|
}else{
|
||||||
listener.onProgressEnded();
|
listener.onProgressEnded();
|
||||||
}
|
}
|
||||||
ConcurrentLinkedQueue<ProgressListener> listenerWeakReferenceList = sProgressListeners.get(progressRecord);
|
List<ProgressListener> listenerWeakReferenceList = sProgressListeners.get(progressRecord);
|
||||||
if(listenerWeakReferenceList == null) sProgressListeners.put(progressRecord, (listenerWeakReferenceList = new ConcurrentLinkedQueue<>()));
|
if(listenerWeakReferenceList == null) sProgressListeners.put(progressRecord, (listenerWeakReferenceList = new ArrayList<>()));
|
||||||
listenerWeakReferenceList.add(listener);
|
listenerWeakReferenceList.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeListener(String progressRecord, ProgressListener listener) {
|
public static synchronized void removeListener(String progressRecord, ProgressListener listener) {
|
||||||
ConcurrentLinkedQueue<ProgressListener> listenerWeakReferenceList = sProgressListeners.get(progressRecord);
|
List<ProgressListener> listenerWeakReferenceList = sProgressListeners.get(progressRecord);
|
||||||
if(listenerWeakReferenceList != null) listenerWeakReferenceList.remove(listener);
|
if(listenerWeakReferenceList != null) listenerWeakReferenceList.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addTaskCountListener(TaskCountListener listener) {
|
public static synchronized void addTaskCountListener(TaskCountListener listener) {
|
||||||
listener.onUpdateTaskCount(sProgressStates.size());
|
listener.onUpdateTaskCount(sProgressStates.size());
|
||||||
if(!sTaskCountListeners.contains(listener)) sTaskCountListeners.add(listener);
|
if(!sTaskCountListeners.contains(listener)) sTaskCountListeners.add(listener);
|
||||||
}
|
}
|
||||||
public static void addTaskCountListener(TaskCountListener listener, boolean runUpdate) {
|
public static synchronized void addTaskCountListener(TaskCountListener listener, boolean runUpdate) {
|
||||||
if(runUpdate) listener.onUpdateTaskCount(sProgressStates.size());
|
if(runUpdate) listener.onUpdateTaskCount(sProgressStates.size());
|
||||||
if(!sTaskCountListeners.contains(listener)) sTaskCountListeners.add(listener);
|
if(!sTaskCountListeners.contains(listener)) sTaskCountListeners.add(listener);
|
||||||
}
|
}
|
||||||
public static void removeTaskCountListener(TaskCountListener listener) {
|
public static synchronized void removeTaskCountListener(TaskCountListener listener) {
|
||||||
sTaskCountListeners.remove(listener);
|
sTaskCountListeners.remove(listener);
|
||||||
}
|
}
|
||||||
public static int getTaskCount() {
|
|
||||||
|
/**
|
||||||
|
* Waits until all tasks are done and runs the runnable, or if there were no pending process remaining
|
||||||
|
* The runnable runs from the thread that updated the task count last, and it might be the UI thread,
|
||||||
|
* so don't put long running processes in it
|
||||||
|
* @param runnable the runnable to run when no tasks are remaining
|
||||||
|
*/
|
||||||
|
public static void waitUntilDone(final Runnable runnable) {
|
||||||
|
// If we do it the other way the listener would be removed before it was added, which will cause a listener object leak
|
||||||
|
if(getTaskCount() == 0) {
|
||||||
|
runnable.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TaskCountListener listener = new TaskCountListener() {
|
||||||
|
@Override
|
||||||
|
public void onUpdateTaskCount(int taskCount) {
|
||||||
|
if(taskCount == 0) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
removeTaskCountListener(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addTaskCountListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized int getTaskCount() {
|
||||||
return sProgressStates.size();
|
return sProgressStates.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,21 @@
|
||||||
package net.kdt.pojavlaunch.scoped;
|
package net.kdt.pojavlaunch.scoped;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.res.AssetFileDescriptor;
|
import android.content.res.AssetFileDescriptor;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.MatrixCursor;
|
import android.database.MatrixCursor;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.os.CancellationSignal;
|
import android.os.CancellationSignal;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.provider.DocumentsContract;
|
||||||
import android.provider.DocumentsContract.Document;
|
import android.provider.DocumentsContract.Document;
|
||||||
import android.provider.DocumentsContract.Root;
|
import android.provider.DocumentsContract.Root;
|
||||||
import android.provider.DocumentsProvider;
|
import android.provider.DocumentsProvider;
|
||||||
|
import android.util.Log;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import net.kdt.pojavlaunch.R;
|
import net.kdt.pojavlaunch.R;
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
|
|
||||||
|
|
@ -19,8 +24,10 @@ import org.apache.commons.io.FileUtils;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A document provider for the Storage Access Framework which exposes the files in the
|
* A document provider for the Storage Access Framework which exposes the files in the
|
||||||
|
|
@ -183,6 +190,7 @@ public class FolderProvider extends DocumentsProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDocumentType(String documentId) throws FileNotFoundException {
|
public String getDocumentType(String documentId) throws FileNotFoundException {
|
||||||
|
Log.i("FolderPRovider", "getDocumentType("+documentId+")");
|
||||||
File file = getFileForDocId(documentId);
|
File file = getFileForDocId(documentId);
|
||||||
return getMimeType(file);
|
return getMimeType(file);
|
||||||
}
|
}
|
||||||
|
|
@ -300,4 +308,20 @@ public class FolderProvider extends DocumentsProvider {
|
||||||
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
|
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@TargetApi(26)
|
||||||
|
public DocumentsContract.Path findDocumentPath(@Nullable String parentDocumentId, String childDocumentId) throws FileNotFoundException {
|
||||||
|
File source = BASE_DIR;
|
||||||
|
if(parentDocumentId != null) source = getFileForDocId(parentDocumentId);
|
||||||
|
File destination = getFileForDocId(childDocumentId);
|
||||||
|
List<String> pathIds = new ArrayList<>();
|
||||||
|
while(!source.equals(destination) && destination != null) {
|
||||||
|
pathIds.add(getDocIdForFile(destination));
|
||||||
|
destination = destination.getParentFile();
|
||||||
|
}
|
||||||
|
pathIds.add(getDocIdForFile(source));
|
||||||
|
Collections.reverse(pathIds);
|
||||||
|
Log.i("FolderProvider", pathIds.toString());
|
||||||
|
return new DocumentsContract.Path(getDocIdForFile(source), pathIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Looper;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ import net.kdt.pojavlaunch.progresskeeper.TaskCountListener;
|
||||||
*/
|
*/
|
||||||
public class ProgressService extends Service implements TaskCountListener {
|
public class ProgressService extends Service implements TaskCountListener {
|
||||||
|
|
||||||
private final Handler mainThreadHandler = new Handler();
|
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
|
||||||
private NotificationManagerCompat notificationManagerCompat;
|
private NotificationManagerCompat notificationManagerCompat;
|
||||||
|
|
||||||
/** Simple wrapper to start the service */
|
/** Simple wrapper to start the service */
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,12 @@ package net.kdt.pojavlaunch.tasks;
|
||||||
import static net.kdt.pojavlaunch.Architecture.archAsString;
|
import static net.kdt.pojavlaunch.Architecture.archAsString;
|
||||||
import static net.kdt.pojavlaunch.PojavApplication.sExecutorService;
|
import static net.kdt.pojavlaunch.PojavApplication.sExecutorService;
|
||||||
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
|
|
||||||
import com.kdt.mcgui.ProgressLayout;
|
import com.kdt.mcgui.ProgressLayout;
|
||||||
|
|
||||||
import net.kdt.pojavlaunch.R;
|
|
||||||
import net.kdt.pojavlaunch.Tools;
|
import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.multirt.MultiRTUtils;
|
import net.kdt.pojavlaunch.multirt.MultiRTUtils;
|
||||||
|
|
||||||
|
|
@ -49,7 +39,8 @@ public class AsyncAssetManager {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("JREAuto", "JRE was not included on this APK.", e);
|
Log.e("JREAuto", "JRE was not included on this APK.", e);
|
||||||
}
|
}
|
||||||
if(current_rt_version == null && MultiRTUtils.getExactJreName(8) != null) return true; //Assume user maintains his own runtime
|
String exactJREName = MultiRTUtils.getExactJreName(8);
|
||||||
|
if(current_rt_version == null && exactJREName != null && !exactJREName.equals("Internal")/*this clause is for when the internal runtime is goofed*/) return true; //Assume user maintains his own runtime
|
||||||
if(rt_version == null) return otherRuntimesAvailable; // On noruntime builds, skip if there is at least 1 runtime installed (no matter if it is 8 or not)
|
if(rt_version == null) return otherRuntimesAvailable; // On noruntime builds, skip if there is at least 1 runtime installed (no matter if it is 8 or not)
|
||||||
if(rt_version.equals(current_rt_version)) return true; //If we already have an integrated one installed, check if it's up-to-date
|
if(rt_version.equals(current_rt_version)) return true; //If we already have an integrated one installed, check if it's up-to-date
|
||||||
|
|
||||||
|
|
@ -73,8 +64,8 @@ public class AsyncAssetManager {
|
||||||
|
|
||||||
/** Unpack single files, with no regard to version tracking */
|
/** Unpack single files, with no regard to version tracking */
|
||||||
public static void unpackSingleFiles(Context ctx){
|
public static void unpackSingleFiles(Context ctx){
|
||||||
|
ProgressLayout.setProgress(ProgressLayout.EXTRACT_SINGLE_FILES, 0);
|
||||||
sExecutorService.execute(() -> {
|
sExecutorService.execute(() -> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Tools.copyAssetFile(ctx, "options.txt", Tools.DIR_GAME_NEW, false);
|
Tools.copyAssetFile(ctx, "options.txt", Tools.DIR_GAME_NEW, false);
|
||||||
Tools.copyAssetFile(ctx, "default.json", Tools.CTRLMAP_PATH, false);
|
Tools.copyAssetFile(ctx, "default.json", Tools.CTRLMAP_PATH, false);
|
||||||
|
|
@ -85,11 +76,12 @@ public class AsyncAssetManager {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("AsyncAssetManager", "Failed to unpack critical components !");
|
Log.e("AsyncAssetManager", "Failed to unpack critical components !");
|
||||||
}
|
}
|
||||||
|
ProgressLayout.clearProgress(ProgressLayout.EXTRACT_SINGLE_FILES);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unpackComponents(Context ctx){
|
public static void unpackComponents(Context ctx){
|
||||||
|
ProgressLayout.setProgress(ProgressLayout.EXTRACT_COMPONENTS, 0);
|
||||||
sExecutorService.execute(() -> {
|
sExecutorService.execute(() -> {
|
||||||
try {
|
try {
|
||||||
unpackComponent(ctx, "caciocavallo", false);
|
unpackComponent(ctx, "caciocavallo", false);
|
||||||
|
|
@ -101,6 +93,7 @@ public class AsyncAssetManager {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("AsyncAssetManager", "Failed o unpack components !",e );
|
Log.e("AsyncAssetManager", "Failed o unpack components !",e );
|
||||||
}
|
}
|
||||||
|
ProgressLayout.clearProgress(ProgressLayout.EXTRACT_COMPONENTS);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import net.kdt.pojavlaunch.Tools;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
import net.kdt.pojavlaunch.extra.ExtraConstants;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraCore;
|
import net.kdt.pojavlaunch.extra.ExtraCore;
|
||||||
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
|
||||||
import net.kdt.pojavlaunch.services.ProgressService;
|
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||||
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
||||||
import net.kdt.pojavlaunch.value.DependentLibrary;
|
import net.kdt.pojavlaunch.value.DependentLibrary;
|
||||||
import net.kdt.pojavlaunch.value.MinecraftClientInfo;
|
import net.kdt.pojavlaunch.value.MinecraftClientInfo;
|
||||||
|
|
@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class AsyncMinecraftDownloader {
|
public class AsyncMinecraftDownloader {
|
||||||
|
private static final float BYTE_TO_MB = 1024 * 1024;
|
||||||
public static final String MINECRAFT_RES = "https://resources.download.minecraft.net/";
|
public static final String MINECRAFT_RES = "https://resources.download.minecraft.net/";
|
||||||
|
|
||||||
/* Allows each downloading thread to have its own RECYCLED buffer */
|
/* Allows each downloading thread to have its own RECYCLED buffer */
|
||||||
|
|
@ -48,12 +49,16 @@ public class AsyncMinecraftDownloader {
|
||||||
public AsyncMinecraftDownloader(@NonNull Activity activity, JMinecraftVersionList.Version version, String realVersion,
|
public AsyncMinecraftDownloader(@NonNull Activity activity, JMinecraftVersionList.Version version, String realVersion,
|
||||||
@NonNull DoneListener listener){ // this was there for a reason
|
@NonNull DoneListener listener){ // this was there for a reason
|
||||||
sExecutorService.execute(() -> {
|
sExecutorService.execute(() -> {
|
||||||
if(downloadGame(activity, version, realVersion))
|
try {
|
||||||
|
downloadGame(activity, version, realVersion);
|
||||||
listener.onDownloadDone();
|
listener.onDownloadDone();
|
||||||
|
}catch (DownloaderException e) {
|
||||||
|
listener.onDownloadFailed(e.getCause());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/* we do the throws DownloaderException thing to avoid blanket-catching Exception as a form of anti-lazy-developer protection */
|
||||||
private boolean downloadGame(@NonNull Activity activity, JMinecraftVersionList.Version verInfo, String versionName){
|
private void downloadGame(@NonNull Activity activity, JMinecraftVersionList.Version verInfo, String versionName) throws DownloaderException {
|
||||||
final String downVName = "/" + versionName + "/" + versionName;
|
final String downVName = "/" + versionName + "/" + versionName;
|
||||||
|
|
||||||
//Downloading libraries
|
//Downloading libraries
|
||||||
|
|
@ -61,22 +66,22 @@ public class AsyncMinecraftDownloader {
|
||||||
JAssets assets = null;
|
JAssets assets = null;
|
||||||
try {
|
try {
|
||||||
File verJsonDir = new File(Tools.DIR_HOME_VERSION + downVName + ".json");
|
File verJsonDir = new File(Tools.DIR_HOME_VERSION + downVName + ".json");
|
||||||
|
|
||||||
if (verInfo != null && verInfo.url != null) {
|
if (verInfo != null && verInfo.url != null) {
|
||||||
if(!LauncherPreferences.PREF_CHECK_LIBRARY_SHA) Log.w("Chk","Checker is off");
|
downloadVersionJson(versionName, verJsonDir, verInfo);
|
||||||
|
}
|
||||||
boolean isManifestGood = verJsonDir.exists()
|
JMinecraftVersionList.Version originalVersion = Tools.getVersionInfo(versionName, true);
|
||||||
&& (!LauncherPreferences.PREF_CHECK_LIBRARY_SHA
|
if(originalVersion.inheritsFrom != null && !originalVersion.inheritsFrom.isEmpty()) {
|
||||||
|| verInfo.sha1 == null
|
Log.i("Downloader", "probe: inheritsFrom="+originalVersion.inheritsFrom);
|
||||||
|| Tools.compareSHA1(verJsonDir, verInfo.sha1));
|
String version = originalVersion.inheritsFrom;
|
||||||
|
String downName = Tools.DIR_HOME_VERSION+"/"+version+"/"+version+".json";
|
||||||
if(!isManifestGood) {
|
JMinecraftVersionList.Version listedVersion = getListedVersion(originalVersion.inheritsFrom);
|
||||||
ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT, 0, R.string.mcl_launch_downloading, versionName + ".json");
|
if(listedVersion != null) {
|
||||||
verJsonDir.delete();
|
Log.i("Downloader", "probe: verifying "+version);
|
||||||
downloadFileMonitored(verInfo.url, verJsonDir, getByteBuffer(),
|
downloadVersionJson(version, new File(downName), listedVersion);
|
||||||
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
}else{
|
||||||
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading, versionName + ".json")
|
Log.i("Downloader", "failed to test source version before downloading.");
|
||||||
);
|
Log.i("Downloader", "Inheriting from versions not in the Mojang list?");
|
||||||
|
Log.i("Downloader", "If so, feel free to open a PR at our GitHub repository to add this feature!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,13 +89,16 @@ public class AsyncMinecraftDownloader {
|
||||||
|
|
||||||
// THIS one function need the activity in the case of an error
|
// THIS one function need the activity in the case of an error
|
||||||
if(!JRE17Util.installNewJreIfNeeded(activity, verInfo)){
|
if(!JRE17Util.installNewJreIfNeeded(activity, verInfo)){
|
||||||
return false;
|
ProgressKeeper.submitProgress(ProgressLayout.DOWNLOAD_MINECRAFT, -1, -1);
|
||||||
|
throw new DownloaderException();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
assets = downloadIndex(verInfo, new File(Tools.ASSETS_PATH, "indexes/" + verInfo.assets + ".json"));
|
if(verInfo.assets != null)
|
||||||
|
assets = downloadIndex(verInfo, new File(Tools.ASSETS_PATH, "indexes/" + verInfo.assets + ".json"));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e("AsyncMcDownloader", e.toString(), e);
|
Log.e("AsyncMcDownloader", e.toString(), e);
|
||||||
|
throw new DownloaderException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
File outLib;
|
File outLib;
|
||||||
|
|
@ -121,7 +129,7 @@ public class AsyncMinecraftDownloader {
|
||||||
downloadFileMonitored(
|
downloadFileMonitored(
|
||||||
verInfo.logging.client.file.url, outLib, getByteBuffer(),
|
verInfo.logging.client.file.url, outLib, getByteBuffer(),
|
||||||
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
||||||
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading, finalVerInfo.logging.client.file.id)
|
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading_progress, finalVerInfo.logging.client.file.id, curr/BYTE_TO_MB, max/BYTE_TO_MB)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -154,7 +162,6 @@ public class AsyncMinecraftDownloader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File minecraftMainFile = new File(minecraftMainJar);
|
File minecraftMainFile = new File(minecraftMainJar);
|
||||||
JMinecraftVersionList.Version originalVersion = Tools.getVersionInfo(versionName, true);
|
|
||||||
Log.i("Downloader", "originalVersion.inheritsFrom="+originalVersion.inheritsFrom);
|
Log.i("Downloader", "originalVersion.inheritsFrom="+originalVersion.inheritsFrom);
|
||||||
Log.i("Downloader", "originalVersion.downloads="+originalVersion.downloads);
|
Log.i("Downloader", "originalVersion.downloads="+originalVersion.downloads);
|
||||||
MinecraftClientInfo originalClientInfo;
|
MinecraftClientInfo originalClientInfo;
|
||||||
|
|
@ -178,6 +185,8 @@ public class AsyncMinecraftDownloader {
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e("AsyncMcDownloader", e.toString(),e );
|
Log.e("AsyncMcDownloader", e.toString(),e );
|
||||||
|
ProgressKeeper.submitProgress(ProgressLayout.DOWNLOAD_MINECRAFT, -1, -1);
|
||||||
|
throw new DownloaderException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT, 0, R.string.mcl_launch_cleancache);
|
ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT, 0, R.string.mcl_launch_cleancache);
|
||||||
|
|
@ -191,12 +200,14 @@ public class AsyncMinecraftDownloader {
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
downloadAssets(assets, verInfo.assets, assets.mapToResources ? new File(Tools.OBSOLETE_RESOURCES_PATH) : new File(Tools.ASSETS_PATH));
|
if(assets != null)
|
||||||
|
downloadAssets(assets, verInfo.assets, assets.mapToResources ? new File(Tools.OBSOLETE_RESOURCES_PATH) : new File(Tools.ASSETS_PATH));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("AsyncMcDownloader", e.toString(), e);
|
Log.e("AsyncMcDownloader", e.toString(), e);
|
||||||
|
ProgressKeeper.submitProgress(ProgressLayout.DOWNLOAD_MINECRAFT, -1, -1);
|
||||||
|
throw new DownloaderException(e);
|
||||||
}
|
}
|
||||||
|
ProgressKeeper.submitProgress(ProgressLayout.DOWNLOAD_MINECRAFT, -1, -1);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyAndDownloadMainJar(String url, String sha1, File destination) throws Exception{
|
public void verifyAndDownloadMainJar(String url, String sha1, File destination) throws Exception{
|
||||||
|
|
@ -204,7 +215,7 @@ public class AsyncMinecraftDownloader {
|
||||||
url,
|
url,
|
||||||
destination, getByteBuffer(),
|
destination, getByteBuffer(),
|
||||||
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
||||||
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading, destination.getName()));
|
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading_progress, destination.getName(), curr/BYTE_TO_MB, max/BYTE_TO_MB));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadAssets(final JAssets assets, String assetsVersion, final File outputDir) throws IOException {
|
public void downloadAssets(final JAssets assets, String assetsVersion, final File outputDir) throws IOException {
|
||||||
|
|
@ -258,7 +269,7 @@ public class AsyncMinecraftDownloader {
|
||||||
while ((!executor.awaitTermination(1000, TimeUnit.MILLISECONDS))&&(!localInterrupt.get()) /*&&mActivity.mIsAssetsProcessing*/) {
|
while ((!executor.awaitTermination(1000, TimeUnit.MILLISECONDS))&&(!localInterrupt.get()) /*&&mActivity.mIsAssetsProcessing*/) {
|
||||||
int DLSize = downloadedSize.get();
|
int DLSize = downloadedSize.get();
|
||||||
ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,(int) Math.max((float) DLSize/assetsSizeBytes*100, 0),
|
ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,(int) Math.max((float) DLSize/assetsSizeBytes*100, 0),
|
||||||
R.string.mcl_launch_downloading, "assets");
|
R.string.mcl_launch_downloading_progress, "assets", (float)DLSize/BYTE_TO_MB, (float)assetsSizeBytes/BYTE_TO_MB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -324,7 +335,7 @@ public class AsyncMinecraftDownloader {
|
||||||
|
|
||||||
downloadFileMonitored(libPathURL, outLib, getByteBuffer(),
|
downloadFileMonitored(libPathURL, outLib, getByteBuffer(),
|
||||||
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
||||||
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading, outLib.getName())
|
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading_progress, outLib.getName(), curr/BYTE_TO_MB, max/BYTE_TO_MB)
|
||||||
);
|
);
|
||||||
|
|
||||||
isFileGood = (libItem.downloads.artifact.sha1 == null
|
isFileGood = (libItem.downloads.artifact.sha1 == null
|
||||||
|
|
@ -356,6 +367,24 @@ public class AsyncMinecraftDownloader {
|
||||||
return Tools.GLOBAL_GSON.fromJson(Tools.read(output.getAbsolutePath()), JAssets.class);
|
return Tools.GLOBAL_GSON.fromJson(Tools.read(output.getAbsolutePath()), JAssets.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void downloadVersionJson(String versionName, File verJsonDir, JMinecraftVersionList.Version verInfo) throws IOException {
|
||||||
|
if(!LauncherPreferences.PREF_CHECK_LIBRARY_SHA) Log.w("Chk","Checker is off");
|
||||||
|
|
||||||
|
boolean isManifestGood = verJsonDir.exists()
|
||||||
|
&& (!LauncherPreferences.PREF_CHECK_LIBRARY_SHA
|
||||||
|
|| verInfo.sha1 == null
|
||||||
|
|| Tools.compareSHA1(verJsonDir, verInfo.sha1));
|
||||||
|
|
||||||
|
if(!isManifestGood) {
|
||||||
|
ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT, 0, R.string.mcl_launch_downloading, versionName + ".json");
|
||||||
|
verJsonDir.delete();
|
||||||
|
downloadFileMonitored(verInfo.url, verJsonDir, getByteBuffer(),
|
||||||
|
(curr, max) -> ProgressLayout.setProgress(ProgressLayout.DOWNLOAD_MINECRAFT,
|
||||||
|
(int) Math.max((float)curr/max*100,0), R.string.mcl_launch_downloading_progress, versionName + ".json", curr/BYTE_TO_MB, max/BYTE_TO_MB)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String normalizeVersionId(String versionString) {
|
public static String normalizeVersionId(String versionString) {
|
||||||
JMinecraftVersionList versionList = (JMinecraftVersionList) ExtraCore.getValue(ExtraConstants.RELEASE_TABLE);
|
JMinecraftVersionList versionList = (JMinecraftVersionList) ExtraCore.getValue(ExtraConstants.RELEASE_TABLE);
|
||||||
if(versionList == null || versionList.versions == null) return versionString;
|
if(versionList == null || versionList.versions == null) return versionString;
|
||||||
|
|
@ -391,6 +420,14 @@ public class AsyncMinecraftDownloader {
|
||||||
|
|
||||||
public interface DoneListener{
|
public interface DoneListener{
|
||||||
void onDownloadDone();
|
void onDownloadDone();
|
||||||
|
void onDownloadFailed(Throwable throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DownloaderException extends Exception {
|
||||||
|
public DownloaderException() {}
|
||||||
|
public DownloaderException(Throwable e) {
|
||||||
|
super(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ public class JREUtils {
|
||||||
Map<String, String> envMap = new ArrayMap<>();
|
Map<String, String> envMap = new ArrayMap<>();
|
||||||
envMap.put("POJAV_NATIVEDIR", NATIVE_LIB_DIR);
|
envMap.put("POJAV_NATIVEDIR", NATIVE_LIB_DIR);
|
||||||
envMap.put("JAVA_HOME", Tools.DIR_HOME_JRE);
|
envMap.put("JAVA_HOME", Tools.DIR_HOME_JRE);
|
||||||
envMap.put("HOME", Tools.DIR_GAME_NEW);
|
envMap.put("HOME", Tools.DIR_GAME_HOME);
|
||||||
envMap.put("TMPDIR", activity.getCacheDir().getAbsolutePath());
|
envMap.put("TMPDIR", activity.getCacheDir().getAbsolutePath());
|
||||||
envMap.put("LIBGL_MIPMAP", "3");
|
envMap.put("LIBGL_MIPMAP", "3");
|
||||||
|
|
||||||
|
|
@ -203,6 +203,8 @@ public class JREUtils {
|
||||||
// The OPEN GL version is changed according
|
// The OPEN GL version is changed according
|
||||||
envMap.put("LIBGL_ES", (String) ExtraCore.getValue(ExtraConstants.OPEN_GL_VERSION));
|
envMap.put("LIBGL_ES", (String) ExtraCore.getValue(ExtraConstants.OPEN_GL_VERSION));
|
||||||
|
|
||||||
|
envMap.put("FORCE_VSYNC", String.valueOf(LauncherPreferences.PREF_FORCE_VSYNC));
|
||||||
|
|
||||||
envMap.put("MESA_GLSL_CACHE_DIR", activity.getCacheDir().getAbsolutePath());
|
envMap.put("MESA_GLSL_CACHE_DIR", activity.getCacheDir().getAbsolutePath());
|
||||||
if (LOCAL_RENDERER != null) {
|
if (LOCAL_RENDERER != null) {
|
||||||
envMap.put("MESA_GL_VERSION_OVERRIDE", LOCAL_RENDERER.equals("opengles3_virgl")?"4.3":"4.6");
|
envMap.put("MESA_GL_VERSION_OVERRIDE", LOCAL_RENDERER.equals("opengles3_virgl")?"4.3":"4.6");
|
||||||
|
|
@ -274,7 +276,7 @@ public class JREUtils {
|
||||||
// return ldLibraryPath;
|
// return ldLibraryPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int launchJavaVM(final Activity activity,final List<String> JVMArgs) throws Throwable {
|
public static int launchJavaVM(final Activity activity, String gameDirectory, final List<String> JVMArgs) throws Throwable {
|
||||||
JREUtils.relocateLibPath();
|
JREUtils.relocateLibPath();
|
||||||
// For debugging only!
|
// For debugging only!
|
||||||
/*
|
/*
|
||||||
|
|
@ -309,7 +311,7 @@ public class JREUtils {
|
||||||
|
|
||||||
initJavaRuntime();
|
initJavaRuntime();
|
||||||
setupExitTrap(activity.getApplication());
|
setupExitTrap(activity.getApplication());
|
||||||
chdir(Tools.DIR_GAME_NEW);
|
chdir(gameDirectory == null ? Tools.DIR_GAME_NEW : gameDirectory);
|
||||||
userArgs.add(0,"java"); //argv[0] is the program name according to C standard.
|
userArgs.add(0,"java"); //argv[0] is the program name according to C standard.
|
||||||
|
|
||||||
final int exitCode = VMLauncher.launchJVM(userArgs.toArray(new String[0]));
|
final int exitCode = VMLauncher.launchJVM(userArgs.toArray(new String[0]));
|
||||||
|
|
@ -340,12 +342,13 @@ public class JREUtils {
|
||||||
ArrayList<String> overridableArguments = new ArrayList<>(Arrays.asList(
|
ArrayList<String> overridableArguments = new ArrayList<>(Arrays.asList(
|
||||||
"-Djava.home=" + Tools.DIR_HOME_JRE,
|
"-Djava.home=" + Tools.DIR_HOME_JRE,
|
||||||
"-Djava.io.tmpdir=" + ctx.getCacheDir().getAbsolutePath(),
|
"-Djava.io.tmpdir=" + ctx.getCacheDir().getAbsolutePath(),
|
||||||
"-Duser.home=" + new File(Tools.DIR_GAME_NEW).getParent(),
|
"-Duser.home=" + Tools.DIR_GAME_HOME,
|
||||||
"-Duser.language=" + System.getProperty("user.language"),
|
"-Duser.language=" + System.getProperty("user.language"),
|
||||||
"-Dos.name=Linux",
|
"-Dos.name=Linux",
|
||||||
"-Dos.version=Android-" + Build.VERSION.RELEASE,
|
"-Dos.version=Android-" + Build.VERSION.RELEASE,
|
||||||
"-Dpojav.path.minecraft=" + Tools.DIR_GAME_NEW,
|
"-Dpojav.path.minecraft=" + Tools.DIR_GAME_NEW,
|
||||||
"-Dpojav.path.private.account=" + Tools.DIR_ACCOUNT_NEW,
|
"-Dpojav.path.private.account=" + Tools.DIR_ACCOUNT_NEW,
|
||||||
|
"-Duser.timezone=" + TimeZone.getDefault().getID(),
|
||||||
|
|
||||||
//LWJGL 3 DEBUG FLAGS
|
//LWJGL 3 DEBUG FLAGS
|
||||||
//"-Dorg.lwjgl.util.Debug=true",
|
//"-Dorg.lwjgl.util.Debug=true",
|
||||||
|
|
@ -385,6 +388,45 @@ public class JREUtils {
|
||||||
return userArguments;
|
return userArguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* more better arguments parser that allows escapes and doesnt change up args
|
||||||
|
* @param _args all args as a string
|
||||||
|
* @return a list of split args
|
||||||
|
*/
|
||||||
|
/*public static ArrayList<String> parseJavaArguments(String _args) {
|
||||||
|
char bracketOpen = '\0';
|
||||||
|
char[] str = _args.toCharArray();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
ArrayList<String> ret = new ArrayList<String>();
|
||||||
|
for(int i = 0; i < str.length; i++) {
|
||||||
|
if(str[i] == '\\') {
|
||||||
|
sb.append(str[i+1]);
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(str[i] == ' ' && bracketOpen == '\0') {
|
||||||
|
if(sb.length() > 0) {
|
||||||
|
ret.add(sb.toString());
|
||||||
|
sb = new StringBuilder();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(str[i] == '"' || str[i] == '\'') {
|
||||||
|
if(bracketOpen == str[i]) {
|
||||||
|
bracketOpen = '\0';
|
||||||
|
continue;
|
||||||
|
}else if(bracketOpen == '\0') {
|
||||||
|
bracketOpen = str[i];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
sb.append(str[i]);
|
||||||
|
}
|
||||||
|
ret.add(sb.toString());
|
||||||
|
return ret;
|
||||||
|
}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse and separate java arguments in a user friendly fashion
|
* Parse and separate java arguments in a user friendly fashion
|
||||||
* It supports multi line and absence of spaces between arguments
|
* It supports multi line and absence of spaces between arguments
|
||||||
|
|
@ -397,12 +439,23 @@ public class JREUtils {
|
||||||
ArrayList<String> parsedArguments = new ArrayList<>(0);
|
ArrayList<String> parsedArguments = new ArrayList<>(0);
|
||||||
args = args.trim().replace(" ", "");
|
args = args.trim().replace(" ", "");
|
||||||
//For each prefixes, we separate args.
|
//For each prefixes, we separate args.
|
||||||
for(String prefix : new String[]{"-XX:-","-XX:+", "-XX:","--","-"}){
|
String[] separators = new String[]{"-XX:-","-XX:+", "-XX:","--", "-D", "-X", "-javaagent:", "-verbose"};
|
||||||
|
for(String prefix : separators){
|
||||||
while (true){
|
while (true){
|
||||||
int start = args.indexOf(prefix);
|
int start = args.indexOf(prefix);
|
||||||
if(start == -1) break;
|
if(start == -1) break;
|
||||||
//Get the end of the current argument
|
//Get the end of the current argument by checking the nearest separator
|
||||||
int end = args.indexOf("-", start + prefix.length());
|
int end = -1;
|
||||||
|
for(String separator: separators){
|
||||||
|
int tempEnd = args.indexOf(separator, start + prefix.length());
|
||||||
|
if(tempEnd == -1) continue;
|
||||||
|
if(end == -1){
|
||||||
|
end = tempEnd;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
end = Math.min(end, tempEnd);
|
||||||
|
}
|
||||||
|
//Fallback
|
||||||
if(end == -1) end = args.length();
|
if(end == -1) end = args.length();
|
||||||
|
|
||||||
//Extract it
|
//Extract it
|
||||||
|
|
|
||||||
|
|
@ -6,31 +6,47 @@ import static net.kdt.pojavlaunch.prefs.LauncherPreferences.DEFAULT_PREF;
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.content.res.*;
|
import android.content.res.*;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.LocaleList;
|
||||||
|
|
||||||
|
import androidx.core.os.ConfigurationCompat;
|
||||||
import androidx.preference.*;
|
import androidx.preference.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import net.kdt.pojavlaunch.prefs.*;
|
import net.kdt.pojavlaunch.prefs.*;
|
||||||
|
|
||||||
public class LocaleUtils {
|
public class LocaleUtils extends ContextWrapper {
|
||||||
|
|
||||||
|
public LocaleUtils(Context base) {
|
||||||
|
super(base);
|
||||||
|
}
|
||||||
|
|
||||||
public static Locale getLocale(){
|
public static Locale getLocale(){
|
||||||
return Locale.getDefault();
|
return Locale.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Context setLocale(Context context) {
|
public static ContextWrapper setLocale(Context context) {
|
||||||
if (DEFAULT_PREF == null) {
|
if (DEFAULT_PREF == null) {
|
||||||
DEFAULT_PREF = PreferenceManager.getDefaultSharedPreferences(context);
|
DEFAULT_PREF = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
LauncherPreferences.loadPreferences(context);
|
LauncherPreferences.loadPreferences(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DEFAULT_PREF.getBoolean("force_english", false)){
|
if(DEFAULT_PREF.getBoolean("force_english", false)){
|
||||||
Locale locale = Locale.ENGLISH;
|
Resources resources = context.getResources();
|
||||||
Locale.setDefault(locale);
|
Configuration configuration = resources.getConfiguration();
|
||||||
Configuration config = context.getResources().getConfiguration();
|
|
||||||
config.locale = locale;
|
configuration.setLocale(Locale.ENGLISH);
|
||||||
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
|
Locale.setDefault(Locale.ENGLISH);
|
||||||
|
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
|
||||||
|
LocaleList localeList = new LocaleList(Locale.ENGLISH);
|
||||||
|
LocaleList.setDefault(localeList);
|
||||||
|
configuration.setLocales(localeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
|
||||||
|
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1){
|
||||||
|
context = context.createConfigurationContext(configuration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return new LocaleUtils(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ import net.kdt.pojavlaunch.extra.ExtraConstants;
|
||||||
import net.kdt.pojavlaunch.extra.ExtraCore;
|
import net.kdt.pojavlaunch.extra.ExtraCore;
|
||||||
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
||||||
|
|
||||||
import java.sql.Date;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
/** Class here to help with various stuff to help run lower versions smoothly */
|
/** Class here to help with various stuff to help run lower versions smoothly */
|
||||||
|
|
@ -26,10 +26,18 @@ public class OldVersionsUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String openGlVersion = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse(creationDate.substring(0, creationDate.indexOf("T"))).before(new Date(2011-1900, 6, 8)) ? "1" : "2";
|
int tIndexOf = creationDate.indexOf('T');
|
||||||
|
if(tIndexOf != -1) creationDate = creationDate.substring(0, tIndexOf);
|
||||||
|
Date creationDateObj = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse(creationDate);
|
||||||
|
if(creationDateObj == null) {
|
||||||
|
Log.e("GL_SELECT", "Failed to parse version date");
|
||||||
|
ExtraCore.setValue(ExtraConstants.OPEN_GL_VERSION, "2");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String openGlVersion = creationDateObj.before(new Date(2011-1900, 6, 8)) ? "1" : "2";
|
||||||
ExtraCore.setValue(ExtraConstants.OPEN_GL_VERSION, openGlVersion);
|
ExtraCore.setValue(ExtraConstants.OPEN_GL_VERSION, openGlVersion);
|
||||||
}catch (ParseException exception){
|
}catch (ParseException exception){
|
||||||
Log.e("OPENGL SELECTION", exception.toString());
|
Log.e("GL_SELECT", exception.toString());
|
||||||
ExtraCore.setValue(ExtraConstants.OPEN_GL_VERSION, "2");
|
ExtraCore.setValue(ExtraConstants.OPEN_GL_VERSION, "2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ public class MinecraftAccount {
|
||||||
|
|
||||||
public Bitmap getSkinFace(){
|
public Bitmap getSkinFace(){
|
||||||
if(skinFaceBase64 == null){
|
if(skinFaceBase64 == null){
|
||||||
return Bitmap.createBitmap(1,1, Bitmap.Config.ARGB_8888);
|
return null;
|
||||||
}
|
}
|
||||||
byte[] faceIconBytes = Base64.decode(skinFaceBase64, Base64.DEFAULT);
|
byte[] faceIconBytes = Base64.decode(skinFaceBase64, Base64.DEFAULT);
|
||||||
return BitmapFactory.decodeByteArray(faceIconBytes, 0, faceIconBytes.length);
|
return BitmapFactory.decodeByteArray(faceIconBytes, 0, faceIconBytes.length);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package net.kdt.pojavlaunch.value.launcherprofiles;
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import net.kdt.pojavlaunch.*;
|
import net.kdt.pojavlaunch.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class LauncherProfiles {
|
public class LauncherProfiles {
|
||||||
public static MinecraftLauncherProfiles mainProfileJson;
|
public static MinecraftLauncherProfiles mainProfileJson;
|
||||||
|
|
@ -11,8 +12,10 @@ public class LauncherProfiles {
|
||||||
if (mainProfileJson == null) {
|
if (mainProfileJson == null) {
|
||||||
if (launcherProfilesFile.exists()) {
|
if (launcherProfilesFile.exists()) {
|
||||||
mainProfileJson = Tools.GLOBAL_GSON.fromJson(Tools.read(launcherProfilesFile.getAbsolutePath()), MinecraftLauncherProfiles.class);
|
mainProfileJson = Tools.GLOBAL_GSON.fromJson(Tools.read(launcherProfilesFile.getAbsolutePath()), MinecraftLauncherProfiles.class);
|
||||||
|
if(mainProfileJson.profiles == null) mainProfileJson.profiles = new HashMap<>();
|
||||||
} else {
|
} else {
|
||||||
mainProfileJson = new MinecraftLauncherProfiles();
|
mainProfileJson = new MinecraftLauncherProfiles();
|
||||||
|
mainProfileJson.profiles = new HashMap<>();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Tools.write(launcherProfilesFile.getAbsolutePath(), mainProfileJson.toJson());
|
Tools.write(launcherProfilesFile.getAbsolutePath(), mainProfileJson.toJson());
|
||||||
|
|
|
||||||
|
|
@ -206,11 +206,19 @@ public class CallbackBridge {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void onGrabStateChanged(boolean grabbing) {
|
private static void onGrabStateChanged(final boolean grabbing) {
|
||||||
isGrabbing = grabbing;
|
isGrabbing = grabbing;
|
||||||
synchronized (grabListeners) {
|
sChoreographer.postFrameCallbackDelayed((time) -> {
|
||||||
for (GrabListener g : grabListeners) g.onGrabState(grabbing);
|
// If the grab re-changed, skip notify process
|
||||||
}
|
if(isGrabbing != grabbing) return;
|
||||||
|
|
||||||
|
System.out.println("Grab changed : " + grabbing);
|
||||||
|
synchronized (grabListeners) {
|
||||||
|
for (GrabListener g : grabListeners) g.onGrabState(grabbing);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 16);
|
||||||
|
|
||||||
}
|
}
|
||||||
public static void addGrabListener(GrabListener listener) {
|
public static void addGrabListener(GrabListener listener) {
|
||||||
synchronized (grabListeners) {
|
synchronized (grabListeners) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
static JavaVM* dalvikJavaVMPtr;
|
static JavaVM* dalvikJavaVMPtr;
|
||||||
|
|
||||||
|
|
@ -13,6 +15,10 @@ jmethodID method_GetRGB;
|
||||||
jclass class_CTCAndroidInput;
|
jclass class_CTCAndroidInput;
|
||||||
jmethodID method_ReceiveInput;
|
jmethodID method_ReceiveInput;
|
||||||
|
|
||||||
|
jclass class_MainActivity;
|
||||||
|
jmethodID method_OpenLink;
|
||||||
|
jmethodID method_OpenPath;
|
||||||
|
|
||||||
jclass class_Frame;
|
jclass class_Frame;
|
||||||
jclass class_Rectangle;
|
jclass class_Rectangle;
|
||||||
jmethodID constructor_Rectangle;
|
jmethodID constructor_Rectangle;
|
||||||
|
|
@ -26,6 +32,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||||
if (dalvikJavaVMPtr == NULL) {
|
if (dalvikJavaVMPtr == NULL) {
|
||||||
//Save dalvik global JavaVM pointer
|
//Save dalvik global JavaVM pointer
|
||||||
dalvikJavaVMPtr = vm;
|
dalvikJavaVMPtr = vm;
|
||||||
|
JNIEnv *env = NULL;
|
||||||
|
(*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4);
|
||||||
|
class_MainActivity = (*env)->NewGlobalRef(env,(*env)->FindClass(env, "net/kdt/pojavlaunch/MainActivity"));
|
||||||
|
method_OpenLink= (*env)->GetStaticMethodID(env, class_MainActivity, "openLink", "(Ljava/lang/String;)V");
|
||||||
|
method_OpenPath= (*env)->GetStaticMethodID(env, class_MainActivity, "openLink", "(Ljava/lang/String;)V");
|
||||||
} else if (dalvikJavaVMPtr != vm) {
|
} else if (dalvikJavaVMPtr != vm) {
|
||||||
runtimeJavaVMPtr = vm;
|
runtimeJavaVMPtr = vm;
|
||||||
}
|
}
|
||||||
|
|
@ -136,6 +147,30 @@ Java_net_kdt_pojavlaunch_AWTInputBridge_nativePutClipboard(JNIEnv *env, jclass c
|
||||||
(*runtimeJNIEnvPtr_CLIPBOARD)->DeleteLocalRef(runtimeJNIEnvPtr_CLIPBOARD,o_stringSelection);
|
(*runtimeJNIEnvPtr_CLIPBOARD)->DeleteLocalRef(runtimeJNIEnvPtr_CLIPBOARD,o_stringSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_net_java_openjdk_cacio_ctc_CTCDesktopPeer_openFile(JNIEnv *env, jclass clazz, jstring filePath) {
|
||||||
|
JNIEnv *dalvikEnv;char detachable = 0;
|
||||||
|
if((*dalvikJavaVMPtr)->GetEnv(dalvikJavaVMPtr, (void **) &dalvikEnv, JNI_VERSION_1_6) == JNI_EDETACHED) {
|
||||||
|
(*dalvikJavaVMPtr)->AttachCurrentThread(dalvikJavaVMPtr, &dalvikEnv, NULL);
|
||||||
|
detachable = 1;
|
||||||
|
}
|
||||||
|
const char* stringChars = (*env)->GetStringUTFChars(env, filePath, NULL);
|
||||||
|
(*dalvikEnv)->CallStaticVoidMethod(dalvikEnv, class_MainActivity, method_OpenPath, (*dalvikEnv)->NewStringUTF(dalvikEnv, stringChars));
|
||||||
|
(*env)->ReleaseStringUTFChars(env, filePath, stringChars);
|
||||||
|
if(detachable) (*dalvikJavaVMPtr)->DetachCurrentThread(dalvikJavaVMPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_net_java_openjdk_cacio_ctc_CTCDesktopPeer_openUri(JNIEnv *env, jclass clazz, jstring uri) {
|
||||||
|
JNIEnv *dalvikEnv;char detachable = 0;
|
||||||
|
if((*dalvikJavaVMPtr)->GetEnv(dalvikJavaVMPtr, (void **) &dalvikEnv, JNI_VERSION_1_6) == JNI_EDETACHED) {
|
||||||
|
(*dalvikJavaVMPtr)->AttachCurrentThread(dalvikJavaVMPtr, &dalvikEnv, NULL);
|
||||||
|
detachable = 1;
|
||||||
|
}
|
||||||
|
const char* stringChars = (*env)->GetStringUTFChars(env, uri, NULL);
|
||||||
|
(*dalvikEnv)->CallStaticVoidMethod(dalvikEnv, class_MainActivity, method_OpenLink, (*dalvikEnv)->NewStringUTF(dalvikEnv, stringChars));
|
||||||
|
(*env)->ReleaseStringUTFChars(env, uri, stringChars);
|
||||||
|
if(detachable) (*dalvikJavaVMPtr)->DetachCurrentThread(dalvikJavaVMPtr);
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_net_kdt_pojavlaunch_AWTInputBridge_nativeMoveWindow(JNIEnv *env, jclass clazz, jint xoff, jint yoff) {
|
Java_net_kdt_pojavlaunch_AWTInputBridge_nativeMoveWindow(JNIEnv *env, jclass clazz, jint xoff, jint yoff) {
|
||||||
if (runtimeJNIEnvPtr_INPUT == NULL) {
|
if (runtimeJNIEnvPtr_INPUT == NULL) {
|
||||||
|
|
|
||||||
|
|
@ -165,5 +165,7 @@ void gl_setup_window() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gl_swap_interval(int swapInterval) {
|
void gl_swap_interval(int swapInterval) {
|
||||||
|
if(pojav_environ->force_vsync) swapInterval = 1;
|
||||||
|
|
||||||
eglSwapInterval_p(g_EglDisplay, swapInterval);
|
eglSwapInterval_p(g_EglDisplay, swapInterval);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -732,6 +732,11 @@ int pojavInit() {
|
||||||
savedHeight = ANativeWindow_getHeight(pojav_environ->pojavWindow);
|
savedHeight = ANativeWindow_getHeight(pojav_environ->pojavWindow);
|
||||||
ANativeWindow_setBuffersGeometry(pojav_environ->pojavWindow,savedWidth,savedHeight,AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM);
|
ANativeWindow_setBuffersGeometry(pojav_environ->pojavWindow,savedWidth,savedHeight,AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM);
|
||||||
|
|
||||||
|
// Only affects GL4ES as of now
|
||||||
|
const char *forceVsync = getenv("FORCE_VSYNC");
|
||||||
|
if (strcmp(forceVsync, "true") == 0)
|
||||||
|
pojav_environ->force_vsync = true;
|
||||||
|
|
||||||
// NOTE: Override for now.
|
// NOTE: Override for now.
|
||||||
const char *renderer = getenv("POJAV_RENDERER");
|
const char *renderer = getenv("POJAV_RENDERER");
|
||||||
if (strncmp("opengles3_virgl", renderer, 15) == 0) {
|
if (strncmp("opengles3_virgl", renderer, 15) == 0) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ struct pojav_environ_s {
|
||||||
struct ANativeWindow* pojavWindow;
|
struct ANativeWindow* pojavWindow;
|
||||||
render_window_t* mainWindowBundle;
|
render_window_t* mainWindowBundle;
|
||||||
int config_renderer;
|
int config_renderer;
|
||||||
|
bool force_vsync;
|
||||||
};
|
};
|
||||||
extern struct pojav_environ_s *pojav_environ;
|
extern struct pojav_environ_s *pojav_environ;
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app_pojavlauncher/src/main/jniLibs/arm64-v8a/libunpack200.so
Normal file → Executable file
BIN
app_pojavlauncher/src/main/jniLibs/arm64-v8a/libunpack200.so
Normal file → Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app_pojavlauncher/src/main/jniLibs/armeabi-v7a/libunpack200.so
Normal file → Executable file
BIN
app_pojavlauncher/src/main/jniLibs/armeabi-v7a/libunpack200.so
Normal file → Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app_pojavlauncher/src/main/jniLibs/x86/libunpack200.so
Normal file → Executable file
BIN
app_pojavlauncher/src/main/jniLibs/x86/libunpack200.so
Normal file → Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app_pojavlauncher/src/main/jniLibs/x86_64/libunpack200.so
Normal file → Executable file
BIN
app_pojavlauncher/src/main/jniLibs/x86_64/libunpack200.so
Normal file → Executable file
Binary file not shown.
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="@dimen/_128sdp" android:tint="@color/primary_text"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="@dimen/_128sdp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M18,2h-8L4.02,8L4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4C20,2.9 19.1,2 18,2zM13,17h-2v-2h2V17zM13,13h-2V8h2V13z"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -44,6 +44,17 @@
|
||||||
app:layout_constraintTop_toBottomOf="@id/custom_control_button"
|
app:layout_constraintTop_toBottomOf="@id/custom_control_button"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
|
android:id="@+id/share_logs_button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/_66sdp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:drawableStart="@android:drawable/ic_menu_share"
|
||||||
|
android:text="@string/main_share_logs"
|
||||||
|
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/install_jar_button"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
<com.kdt.mcgui.mcVersionSpinner
|
<com.kdt.mcgui.mcVersionSpinner
|
||||||
android:id="@+id/mc_version_spinner"
|
android:id="@+id/mc_version_spinner"
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
|
|
||||||
android:layout_marginHorizontal="15dp"
|
android:layout_marginHorizontal="@dimen/_15sdp"
|
||||||
android:background="@drawable/menu_background"
|
android:background="@drawable/menu_background"
|
||||||
android:paddingVertical="20dp"
|
android:paddingVertical="20dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
android:layout_height="@dimen/_52sdp"
|
android:layout_height="@dimen/_52sdp"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:src="@drawable/ic_menu_settings"
|
android:src="@drawable/ic_menu_settings"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:paddingVertical="@dimen/_8sdp"
|
||||||
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="@dimen/_230sdp"
|
android:layout_width="@dimen/_280sdp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/background_app"
|
android:background="@color/background_app"
|
||||||
android:paddingHorizontal="@dimen/_5sdp"
|
android:paddingHorizontal="@dimen/_5sdp"
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<net.kdt.pojavlaunch.colorselector.SVRectangleView
|
<net.kdt.pojavlaunch.colorselector.SVRectangleView
|
||||||
android:id="@+id/color_selector_rectangle_view"
|
android:id="@+id/color_selector_rectangle_view"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="150dp"
|
android:layout_height="@dimen/_150sdp"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
<net.kdt.pojavlaunch.colorselector.ColorSideBySideView
|
<net.kdt.pojavlaunch.colorselector.ColorSideBySideView
|
||||||
android:id="@+id/color_selector_color_view"
|
android:id="@+id/color_selector_color_view"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="94dp"
|
android:layout_height="@dimen/_94sdp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/color_selector_rectangle_view"
|
app:layout_constraintEnd_toEndOf="@+id/color_selector_rectangle_view"
|
||||||
app:layout_constraintStart_toStartOf="@+id/color_selector_rectangle_view"
|
app:layout_constraintStart_toStartOf="@+id/color_selector_rectangle_view"
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:importantForAutofill="no"
|
android:importantForAutofill="no"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:minHeight="48dp"
|
android:minHeight="@dimen/_48sdp"
|
||||||
android:typeface="monospace"
|
android:typeface="monospace"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/color_selector_color_view"
|
app:layout_constraintEnd_toEndOf="@+id/color_selector_color_view"
|
||||||
app:layout_constraintStart_toStartOf="@+id/color_selector_color_view"
|
app:layout_constraintStart_toStartOf="@+id/color_selector_color_view"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<com.kdt.DefocusableScrollView
|
<com.kdt.DefocusableScrollView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="@dimen/_230sdp"
|
android:layout_width="@dimen/_280sdp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:background="@color/background_app"
|
android:background="@color/background_app"
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/editSize_editTextX"
|
android:id="@+id/editSize_editTextX"
|
||||||
android:layout_width="140dp"
|
android:layout_width="@dimen/_138sdp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:imeOptions="flagNoExtractUi"
|
android:imeOptions="flagNoExtractUi"
|
||||||
|
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_marginHorizontal="15dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/control_offset_top_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/control_top_offset"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SeekBar
|
|
||||||
android:id="@+id/control_offset_top_seekbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/control_offset_right_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/control_right_offset"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SeekBar
|
|
||||||
android:id="@+id/control_offset_right_seekbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/control_offset_bottom_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/control_bottom_offset"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SeekBar
|
|
||||||
android:id="@+id/control_offset_bottom_seekbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/control_offset_left_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/control_left_offset"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SeekBar
|
|
||||||
android:id="@+id/control_offset_left_seekbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="40dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
|
|
@ -44,6 +44,17 @@
|
||||||
app:layout_constraintTop_toBottomOf="@id/custom_control_button"
|
app:layout_constraintTop_toBottomOf="@id/custom_control_button"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<com.kdt.mcgui.LauncherMenuButton
|
||||||
|
android:id="@+id/share_logs_button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/_66sdp"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:drawableStart="@android:drawable/ic_menu_share"
|
||||||
|
android:text="@string/main_share_logs"
|
||||||
|
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/install_jar_button"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
<com.kdt.mcgui.mcVersionSpinner
|
<com.kdt.mcgui.mcVersionSpinner
|
||||||
android:id="@+id/mc_version_spinner"
|
android:id="@+id/mc_version_spinner"
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/_24sdp"
|
android:layout_marginTop="@dimen/_24sdp"
|
||||||
android:background="@drawable/background_line"
|
android:background="@drawable/background_line"
|
||||||
|
android:textSize="@dimen/_13ssp"
|
||||||
|
|
||||||
android:ems="10"
|
android:ems="10"
|
||||||
android:hint="@string/unnamed"
|
android:hint="@string/unnamed"
|
||||||
|
|
@ -54,7 +55,7 @@
|
||||||
android:background="@drawable/background_line"
|
android:background="@drawable/background_line"
|
||||||
android:hint="Select a version"
|
android:hint="Select a version"
|
||||||
android:paddingHorizontal="@dimen/_12sdp"
|
android:paddingHorizontal="@dimen/_12sdp"
|
||||||
android:textSize="@dimen/_14sdp"
|
android:textSize="@dimen/_13ssp"
|
||||||
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/vprof_editor_version_button"
|
app:layout_constraintEnd_toStartOf="@+id/vprof_editor_version_button"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
@ -65,7 +66,8 @@
|
||||||
android:layout_width="@dimen/_72sdp"
|
android:layout_width="@dimen/_72sdp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
|
||||||
android:text="Select"
|
android:text="@string/global_select"
|
||||||
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/vprof_editor_version_spinner"
|
app:layout_constraintBottom_toBottomOf="@+id/vprof_editor_version_spinner"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@+id/vprof_editor_version_spinner" />
|
app:layout_constraintTop_toTopOf="@+id/vprof_editor_version_spinner" />
|
||||||
|
|
@ -89,7 +91,7 @@
|
||||||
android:background="@drawable/background_line"
|
android:background="@drawable/background_line"
|
||||||
android:hint="@string/use_global_default"
|
android:hint="@string/use_global_default"
|
||||||
android:paddingHorizontal="@dimen/_12sdp"
|
android:paddingHorizontal="@dimen/_12sdp"
|
||||||
android:textSize="@dimen/_14sdp"
|
android:textSize="@dimen/_13ssp"
|
||||||
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/vprof_editor_ctrl_button"
|
app:layout_constraintEnd_toStartOf="@id/vprof_editor_ctrl_button"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
@ -100,7 +102,8 @@
|
||||||
android:layout_width="@dimen/_72sdp"
|
android:layout_width="@dimen/_72sdp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
|
|
||||||
android:text="SELECT"
|
android:text="@string/global_select"
|
||||||
|
|
||||||
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/vprof_editor_ctrl_spinner"
|
app:layout_constraintBottom_toBottomOf="@id/vprof_editor_ctrl_spinner"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
@ -125,6 +128,7 @@
|
||||||
android:hint="@string/use_global_default"
|
android:hint="@string/use_global_default"
|
||||||
android:inputType="text"
|
android:inputType="text"
|
||||||
android:paddingHorizontal="@dimen/_12sdp"
|
android:paddingHorizontal="@dimen/_12sdp"
|
||||||
|
android:textSize="@dimen/_13ssp"
|
||||||
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/vprof_editor_ctrl_spinner" />
|
app:layout_constraintTop_toBottomOf="@+id/vprof_editor_ctrl_spinner" />
|
||||||
|
|
||||||
|
|
@ -149,7 +153,7 @@
|
||||||
|
|
||||||
android:hint=".minecraft"
|
android:hint=".minecraft"
|
||||||
android:paddingHorizontal="@dimen/_12sdp"
|
android:paddingHorizontal="@dimen/_12sdp"
|
||||||
android:textSize="@dimen/_14ssp"
|
android:textSize="@dimen/_13ssp"
|
||||||
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/vprof_editor_path_button"
|
app:layout_constraintEnd_toStartOf="@id/vprof_editor_path_button"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
@ -159,7 +163,7 @@
|
||||||
android:id="@+id/vprof_editor_path_button"
|
android:id="@+id/vprof_editor_path_button"
|
||||||
android:layout_width="@dimen/_72sdp"
|
android:layout_width="@dimen/_72sdp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:text="SELECT"
|
android:text="@string/global_select"
|
||||||
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/vprof_editor_path"
|
app:layout_constraintBottom_toBottomOf="@id/vprof_editor_path"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
@ -180,6 +184,7 @@
|
||||||
android:layout_marginTop="32dp"
|
android:layout_marginTop="32dp"
|
||||||
android:background="@drawable/background_line"
|
android:background="@drawable/background_line"
|
||||||
android:paddingVertical="0px"
|
android:paddingVertical="0px"
|
||||||
|
android:textSize="@dimen/_13ssp"
|
||||||
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/vprof_editor_path"
|
app:layout_constraintTop_toBottomOf="@+id/vprof_editor_path"
|
||||||
|
|
||||||
|
|
@ -234,7 +239,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginVertical="26dp"
|
android:layout_marginVertical="26dp"
|
||||||
android:text="Save profile"
|
android:text="@string/global_save"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/vprof_editor_delete_button"
|
app:layout_constraintEnd_toStartOf="@+id/vprof_editor_delete_button"
|
||||||
|
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
|
@ -247,7 +252,7 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
android:text="Delete profile"
|
android:text="@string/global_delete"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/app_short_name"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
|
||||||
android:fontFamily="@font/noto_sans_bold"
|
|
||||||
android:textSize="40sp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:text="@string/app_motd"
|
|
||||||
android:fontFamily="@font/noto_sans_bold"
|
|
||||||
android:id="@+id/startscreen_text"/>
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:id="@+id/startscreenProgress"
|
|
||||||
android:visibility="invisible"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="@dimen/_128sdp"
|
||||||
|
android:layout_height="@dimen/_128sdp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:src="@drawable/storage_alert" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="@dimen/_8sdp"
|
||||||
|
android:paddingTop="@dimen/_10sdp"
|
||||||
|
android:paddingEnd="@dimen/_8sdp"
|
||||||
|
android:text="@string/storage_required" />
|
||||||
|
</LinearLayout>
|
||||||
15
app_pojavlauncher/src/main/res/values-land/styles.xml
Normal file
15
app_pojavlauncher/src/main/res/values-land/styles.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<!-- Light or not? -->
|
||||||
|
<style name="AppTheme" parent="@style/Theme.AppCompat.NoActionBar">
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="windowActionBar">false</item>
|
||||||
|
<item name="android:windowContentOverlay">@null</item>
|
||||||
|
<item name="android:statusBarColor">@color/background_status_bar</item>
|
||||||
|
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||||
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
|
||||||
|
<item name="android:textSize">@dimen/_14ssp</item>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</resources>
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
<item>@string/control_adebug</item>
|
<item>@string/control_adebug</item>
|
||||||
<item>@string/control_customkey</item>
|
<item>@string/control_customkey</item>
|
||||||
<item>@string/mcl_setting_title_mousespeed</item>
|
<item>@string/mcl_setting_title_mousespeed</item>
|
||||||
|
<item>@string/preference_gyro_sensitivity_title</item>
|
||||||
<item>@string/mcl_option_customcontrol</item>
|
<item>@string/mcl_option_customcontrol</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
<string name="login_dialog_no_saved_account">You don\'t have any saved account.\nUse the option <b>\"Keep me logged in\"</b> to save an account upon first login.</string>
|
<string name="login_dialog_no_saved_account">You don\'t have any saved account.\nUse the option <b>\"Keep me logged in\"</b> to save an account upon first login.</string>
|
||||||
|
|
||||||
<!-- Hint -->
|
<!-- Hint -->
|
||||||
<string name="hint_control_mapping">"Swipe from right to left to open menu ◀\nHold a button to customize: edit, resize or delete."</string>
|
<string name="hint_control_mapping">"Tap the top center cog icon to open the context menu ⚙\nTap a button to customize: edit, resize, delete, or customize it's keybind."</string>
|
||||||
|
|
||||||
<!-- Warnings -->
|
<!-- Warnings -->
|
||||||
<string name="warning_remove_account">This account will be removed!</string>
|
<string name="warning_remove_account">This account will be removed!</string>
|
||||||
|
|
@ -110,6 +110,8 @@
|
||||||
<string name="mcl_setting_veroption_snapshot">Snapshot</string>
|
<string name="mcl_setting_veroption_snapshot">Snapshot</string>
|
||||||
<string name="mcl_setting_veroption_oldalpha">Old-alpha</string>
|
<string name="mcl_setting_veroption_oldalpha">Old-alpha</string>
|
||||||
<string name="mcl_setting_veroption_oldbeta">Old-beta</string>
|
<string name="mcl_setting_veroption_oldbeta">Old-beta</string>
|
||||||
|
<string name="mcl_setting_java_sandbox">Sandbox .jar installer</string>
|
||||||
|
<string name="mcl_setting_java_sandbox_subtitle">Control the availability of sandbox security manager when launching .jar installer.</string>
|
||||||
<string name="mcl_version_clone">Clone</string>
|
<string name="mcl_version_clone">Clone</string>
|
||||||
|
|
||||||
<!-- Global strings -->
|
<!-- Global strings -->
|
||||||
|
|
@ -125,6 +127,7 @@
|
||||||
<string name="global_unpacking">Unpacking %s</string>
|
<string name="global_unpacking">Unpacking %s</string>
|
||||||
<string name="global_error_field_empty">This field can\'t be empty</string>
|
<string name="global_error_field_empty">This field can\'t be empty</string>
|
||||||
<string name="global_waiting">Wait</string>
|
<string name="global_waiting">Wait</string>
|
||||||
|
<string name="global_select">Select</string>
|
||||||
|
|
||||||
<!-- MainActivity: strings -->
|
<!-- MainActivity: strings -->
|
||||||
<string name="mcn_exit_title">Application/Game exited with code %d, check latestlog.txt for more details.</string>
|
<string name="mcn_exit_title">Application/Game exited with code %d, check latestlog.txt for more details.</string>
|
||||||
|
|
@ -168,7 +171,7 @@
|
||||||
<string name="import_control_verifying_file">File is being verified, please wait and try again…</string>
|
<string name="import_control_verifying_file">File is being verified, please wait and try again…</string>
|
||||||
<string name="import_control_invalid_name">Invalid name or file already exists</string>
|
<string name="import_control_invalid_name">Invalid name or file already exists</string>
|
||||||
<string name="import_control_done">Importation done</string>
|
<string name="import_control_done">Importation done</string>
|
||||||
<!--
|
<!--
|
||||||
<string name="control_more3"></string>
|
<string name="control_more3"></string>
|
||||||
<string name="control_more4"></string>
|
<string name="control_more4"></string>
|
||||||
-->
|
-->
|
||||||
|
|
@ -207,7 +210,7 @@
|
||||||
<string name="customctrl_selectdefault">Select default Control json</string>
|
<string name="customctrl_selectdefault">Select default Control json</string>
|
||||||
<string name="customctrl_export">Export control</string>
|
<string name="customctrl_export">Export control</string>
|
||||||
|
|
||||||
|
<string name="main_share_logs">Share log file</string>
|
||||||
<string name="main_install_jar_file">Install .jar</string>
|
<string name="main_install_jar_file">Install .jar</string>
|
||||||
<string name="main_options">Options</string>
|
<string name="main_options">Options</string>
|
||||||
<string name="main_play">Play</string>
|
<string name="main_play">Play</string>
|
||||||
|
|
@ -268,21 +271,33 @@
|
||||||
<string name="preference_control_offset_title">Control side offsets</string>
|
<string name="preference_control_offset_title">Control side offsets</string>
|
||||||
<string name="preference_control_offset_description">Set a custom offset to each side of the screen</string>
|
<string name="preference_control_offset_description">Set a custom offset to each side of the screen</string>
|
||||||
<string name="preference_mouse_start_title">Start with virtual mouse on</string>
|
<string name="preference_mouse_start_title">Start with virtual mouse on</string>
|
||||||
<string name="preference_mouse_start_description">Using this option will get you judged by Mathias-Boulay</string>
|
<string name="preference_mouse_start_description">Virtual Mouse appears at startup when this option is on</string>
|
||||||
<string name="preference_video_title">Video and renderer</string>
|
<string name="preference_video_title">Video and renderer</string>
|
||||||
<string name="preference_video_description">Resolution, scaling type, and renderer</string>
|
<string name="preference_video_description">Resolution, scaling type, and renderer</string>
|
||||||
<string name="preference_control_title">Control customization</string>
|
<string name="preference_control_title">Control customization</string>
|
||||||
<string name="preference_control_description">Gestures types, triggers, and scaling</string>
|
<string name="preference_control_description">Gestures types, triggers, and scaling</string>
|
||||||
<string name="preference_java_title">Java Tweaks</string>
|
<string name="preference_java_title">Java Tweaks</string>
|
||||||
<string name="preference_java_description">Java versions, JVM Arguments, and RAM amount</string>
|
<string name="preference_java_description">Java versions, JVM Arguments, RAM amount and sandbox</string>
|
||||||
<string name="preference_misc_title">Miscellaneous settings</string>
|
<string name="preference_misc_title">Miscellaneous settings</string>
|
||||||
<string name="preference_misc_description">Version list, and libs checks</string>
|
<string name="preference_misc_description">Version list, and libs checks</string>
|
||||||
<string name="preference_experimental_title">Experimental Stuff</string>
|
<string name="preference_experimental_title">Experimental Stuff</string>
|
||||||
<string name="preference_experimental_description">Use things there with consideration, no support.</string>
|
<string name="preference_experimental_description">Use things there with consideration, no support.</string>
|
||||||
<string name="preference_sustained_performance_title">Enable sustained performance mode</string>
|
<string name="preference_sustained_performance_title">Enable sustained performance mode</string>
|
||||||
<string name="preference_sustained_performance_description">Limit thermal throttling by limiting peak performance</string>
|
<string name="preference_sustained_performance_description">Limit thermal throttling by limiting peak performance</string>
|
||||||
|
<string name="preference_force_vsync_title">Force enable vsync</string>
|
||||||
|
<string name="preference_force_vsync_description">Limit thermal throttling by limiting peak performance</string>
|
||||||
<string name="preference_force_english_title">Force language to english</string>
|
<string name="preference_force_english_title">Force language to english</string>
|
||||||
<string name="preference_force_english_description">Allows you to see original strings, as intended by developers. Requires a restart</string>
|
<string name="preference_force_english_description">Allows you to see original strings, as intended by developers. Requires a restart</string>
|
||||||
|
<string name="preference_edit_controls_title">Edit custom controls</string>
|
||||||
|
<string name="preference_edit_controls_summary">Tweak the control scheme to fit your needs</string>
|
||||||
|
|
||||||
|
<string name="preference_category_gyro_controls">Gyro controls</string>
|
||||||
|
<string name="preference_category_virtual_mouse">Virtual mouse</string>
|
||||||
|
|
||||||
|
<string name="preference_gyro_invert_x_axis">Invert X axis</string>
|
||||||
|
<string name="preference_gyro_invert_y_axis">Invert Y axis</string>
|
||||||
|
<string name="preference_gyro_invert_x_axis_description">Invert the horizontal axis</string>
|
||||||
|
<string name="preference_gyro_invert_y_axis_description">Invert the vertical axis</string>
|
||||||
|
|
||||||
<string name="preference_back_title">Back to the last screen</string>
|
<string name="preference_back_title">Back to the last screen</string>
|
||||||
<string name="gles_hack_title">GL4ES Shrink hack</string>
|
<string name="gles_hack_title">GL4ES Shrink hack</string>
|
||||||
|
|
@ -319,4 +334,23 @@
|
||||||
<string name="tasks_ongoing">Tasks are in progress, please wait</string>
|
<string name="tasks_ongoing">Tasks are in progress, please wait</string>
|
||||||
<string name="no_saved_accounts">No saved accounts</string>
|
<string name="no_saved_accounts">No saved accounts</string>
|
||||||
<string name="downloading_versions">Downloading version list…</string>
|
<string name="downloading_versions">Downloading version list…</string>
|
||||||
|
<string name="mc_download_failed">Failed to download Minecraft! This could be due to bad network connection, incorrectly placed files, etc..</string>
|
||||||
|
<string name="xerr_unknown">Unknown Xbox Live API error %d</string>
|
||||||
|
<string name="xerr_no_account">You don\'t seem to have an Xbox Live account. Please log in once on https://minecraft.net/ and try again.</string>
|
||||||
|
<string name="xerr_adult_verification">An adult needs to verify your account.</string>
|
||||||
|
<string name="xerr_child">Your account is a child account, and needs to be added into a Family in order to log in.</string>
|
||||||
|
<string name="minecraft_not_owned">It seems like this account does not have a Minecraft profile. If you have Xbox Game Pass, please log in on https://minecraft.net/ and set it up.</string>
|
||||||
|
<string name="xerr_not_available">Xbox Live is not available in your country</string>
|
||||||
|
<string name="preference_enable_gyro_title">Enable gyroscope controls</string>
|
||||||
|
<string name="preference_enable_gyro_description">Enabling this will allow you to turn in game by turning your phone</string>
|
||||||
|
<string name="preference_gyro_sensitivity_title">Gyroscope controls sensitivity</string>
|
||||||
|
<string name="preference_gyro_sensitivity_description">Adjust the sensitivity of gyroscope controls</string>
|
||||||
|
<string name="toast_turn_on_gyro">Enable gyro controls first to use this!</string>
|
||||||
|
<string name="preference_gyro_sample_rate_title">Gyroscope sampling rate</string>
|
||||||
|
<string name="preference_gyro_sample_rate_description">If you have performance issues with the gyroscope controls, increase this</string>
|
||||||
|
<string name="microsoft_login_retry_later">Too many requests, please try again later.</string>
|
||||||
|
<string name="storage_required">PojavLauncher requires an attached external storage. Please reconnect your storage and restart the app.</string>
|
||||||
|
<string name="mcl_setting_title_buttonallcaps">Use only capital letters in button labels</string>
|
||||||
|
<string name="mcl_setting_subtitle_buttonallcaps">Disable this if you want to use lowercase letters in your controls</string>
|
||||||
|
<string name="create_profile">Create new profile</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,7 @@
|
||||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
|
|
||||||
|
<item name="android:textSize">@dimen/_12ssp</item>
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,15 @@
|
||||||
|
|
||||||
<net.kdt.pojavlaunch.prefs.BackButtonPreference/>
|
<net.kdt.pojavlaunch.prefs.BackButtonPreference/>
|
||||||
|
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:title="@string/preference_edit_controls_title"
|
||||||
|
android:summary="@string/preference_edit_controls_summary"
|
||||||
|
app2:icon="@drawable/ic_menu_custom_controls"
|
||||||
|
>
|
||||||
|
<intent android:targetPackage="@string/application_package" android:targetClass="net.kdt.pojavlaunch.CustomControlsActivity" android:action=".CustomControlsActivity"/>
|
||||||
|
</Preference>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="Gestures ">
|
android:title="Gestures ">
|
||||||
|
|
||||||
|
|
@ -38,11 +47,17 @@
|
||||||
app2:seekBarIncrement="5"
|
app2:seekBarIncrement="5"
|
||||||
android:icon="@drawable/ic_setting_control_scale"
|
android:icon="@drawable/ic_setting_control_scale"
|
||||||
/>
|
/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="buttonAllCaps"
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:title="@string/mcl_setting_title_buttonallcaps"
|
||||||
|
android:summary="@string/mcl_setting_subtitle_buttonallcaps"
|
||||||
|
/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="Virtual mouse">
|
android:title="@string/preference_category_virtual_mouse">
|
||||||
|
|
||||||
<net.kdt.pojavlaunch.prefs.CustomSeekBarPreference
|
<net.kdt.pojavlaunch.prefs.CustomSeekBarPreference
|
||||||
android:key="mousescale"
|
android:key="mousescale"
|
||||||
|
|
@ -68,6 +83,37 @@
|
||||||
android:title="@string/preference_mouse_start_title"
|
android:title="@string/preference_mouse_start_title"
|
||||||
android:summary="@string/preference_mouse_start_description"
|
android:summary="@string/preference_mouse_start_description"
|
||||||
/>
|
/>
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="gyroCategory"
|
||||||
|
android:title="@string/preference_category_gyro_controls"
|
||||||
|
>
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="enableGyro"
|
||||||
|
android:title="@string/preference_enable_gyro_title"
|
||||||
|
android:summary="@string/preference_enable_gyro_description"/>
|
||||||
|
<net.kdt.pojavlaunch.prefs.CustomSeekBarPreference
|
||||||
|
android:key="gyroSensitivity"
|
||||||
|
android:title="@string/preference_gyro_sensitivity_title"
|
||||||
|
android:summary="@string/preference_gyro_sensitivity_description"
|
||||||
|
app2:selectable="false"
|
||||||
|
app2:seekBarIncrement="5"
|
||||||
|
app2:showSeekBarValue="true"/>
|
||||||
|
<net.kdt.pojavlaunch.prefs.CustomSeekBarPreference
|
||||||
|
android:key="gyroSampleRate"
|
||||||
|
android:title="@string/preference_gyro_sample_rate_title"
|
||||||
|
android:summary="@string/preference_gyro_sample_rate_description"
|
||||||
|
app2:selectable="false"
|
||||||
|
app2:showSeekBarValue="true"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="gyroInvertX"
|
||||||
|
android:title="@string/preference_gyro_invert_x_axis"
|
||||||
|
android:summary="@string/preference_gyro_invert_x_axis_description"/>
|
||||||
|
<SwitchPreference
|
||||||
|
android:key="gyroInvertY"
|
||||||
|
android:title="@string/preference_gyro_invert_y_axis"
|
||||||
|
android:summary="@string/preference_gyro_invert_y_axis_description"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,12 @@
|
||||||
app2:seekBarIncrement="10"
|
app2:seekBarIncrement="10"
|
||||||
app2:selectable="false"/>
|
app2:selectable="false"/>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="java_sandbox"
|
||||||
|
android:summary="@string/mcl_setting_java_sandbox_subtitle"
|
||||||
|
android:title="@string/mcl_setting_java_sandbox" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue