mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-13 06:39:54 -04:00
Feat[launcher]: add support for the "Better than Adventure!" mod
This commit is contained in:
parent
3d256a29e4
commit
ee3435d52a
@ -327,7 +327,7 @@ public final class Tools {
|
|||||||
}
|
}
|
||||||
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionId, gamedir)));
|
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionId, gamedir)));
|
||||||
javaArgList.add("-cp");
|
javaArgList.add("-cp");
|
||||||
javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath);
|
javaArgList.add(launchClassPath + ":" + getLWJGL3ClassPath());
|
||||||
|
|
||||||
javaArgList.add(versionInfo.mainClass);
|
javaArgList.add(versionInfo.mainClass);
|
||||||
javaArgList.addAll(Arrays.asList(launchArgs));
|
javaArgList.addAll(Arrays.asList(launchArgs));
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
package net.kdt.pojavlaunch.fragments;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.widget.ExpandableListAdapter;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.R;
|
||||||
|
import net.kdt.pojavlaunch.modloaders.BTADownloadTask;
|
||||||
|
import net.kdt.pojavlaunch.modloaders.BTAUtils;
|
||||||
|
import net.kdt.pojavlaunch.modloaders.BTAVersionListAdapter;
|
||||||
|
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BTAInstallFragment extends ModVersionListFragment<BTAUtils.BTAVersionList> {
|
||||||
|
private static ModloaderListenerProxy sTaskProxy;
|
||||||
|
@Override
|
||||||
|
public int getTitleText() {
|
||||||
|
return R.string.select_bta_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNoDataMsg() {
|
||||||
|
return R.string.modloader_dl_failed_to_load_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModloaderListenerProxy getTaskProxy() {
|
||||||
|
return sTaskProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BTAUtils.BTAVersionList loadVersionList() throws IOException {
|
||||||
|
return BTAUtils.downloadVersionList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTaskProxy(ModloaderListenerProxy proxy) {
|
||||||
|
sTaskProxy = proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExpandableListAdapter createAdapter(BTAUtils.BTAVersionList versionList, LayoutInflater layoutInflater) {
|
||||||
|
return new BTAVersionListAdapter(versionList, layoutInflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Runnable createDownloadTask(Object selectedVersion, ModloaderListenerProxy listenerProxy) {
|
||||||
|
return new BTADownloadTask(listenerProxy, (BTAUtils.BTAVersion) selectedVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDownloadFinished(Context context, File downloadedFile) {
|
||||||
|
// We don't have to do anything after the BTADownloadTask ends, so this is a stub
|
||||||
|
}
|
||||||
|
}
|
@ -35,5 +35,7 @@ public class ProfileTypeSelectFragment extends Fragment {
|
|||||||
Tools.swapFragment(requireActivity(), SearchModFragment.class, SearchModFragment.TAG, null));
|
Tools.swapFragment(requireActivity(), SearchModFragment.class, SearchModFragment.TAG, null));
|
||||||
view.findViewById(R.id.modded_profile_quilt).setOnClickListener((v)->
|
view.findViewById(R.id.modded_profile_quilt).setOnClickListener((v)->
|
||||||
Tools.swapFragment(requireActivity(), QuiltInstallFragment.class, QuiltInstallFragment.TAG, null));
|
Tools.swapFragment(requireActivity(), QuiltInstallFragment.class, QuiltInstallFragment.TAG, null));
|
||||||
|
view.findViewById(R.id.modded_profile_bta).setOnClickListener((v)->
|
||||||
|
Tools.swapFragment(requireActivity(), BTAInstallFragment.class, BTAInstallFragment.TAG, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
package net.kdt.pojavlaunch.modloaders;
|
||||||
|
|
||||||
|
import android.util.Base64;
|
||||||
|
import android.util.Base64OutputStream;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.kdt.mcgui.ProgressLayout;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.R;
|
||||||
|
import net.kdt.pojavlaunch.Tools;
|
||||||
|
import net.kdt.pojavlaunch.progresskeeper.ProgressKeeper;
|
||||||
|
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
||||||
|
import net.kdt.pojavlaunch.utils.FileUtils;
|
||||||
|
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
|
||||||
|
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class BTADownloadTask implements Runnable {
|
||||||
|
private static final String BASE_JSON = "{\"inheritsFrom\":\"b1.7.3\",\"mainClass\":\"net.minecraft.client.Minecraft\",\"libraries\":[{\"name\":\"bta-client:bta-client:%1$s\",\"downloads\":{\"artifact\":{\"path\":\"bta-client/bta-client-%1$s.jar\",\"url\":\"%2$s\"}}}],\"id\":\"%3$s\"}";
|
||||||
|
private final ModloaderDownloadListener mListener;
|
||||||
|
private final BTAUtils.BTAVersion mBtaVersion;
|
||||||
|
|
||||||
|
public BTADownloadTask(ModloaderDownloadListener mListener, BTAUtils.BTAVersion mBtaVersion) {
|
||||||
|
this.mListener = mListener;
|
||||||
|
this.mBtaVersion = mBtaVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ProgressKeeper.submitProgress(ProgressLayout.INSTALL_MODPACK, 0, R.string.fabric_dl_progress, "BTA");
|
||||||
|
try {
|
||||||
|
runCatching() ;
|
||||||
|
mListener.onDownloadFinished(null);
|
||||||
|
}catch (IOException e) {
|
||||||
|
mListener.onDownloadError(e);
|
||||||
|
}
|
||||||
|
ProgressLayout.clearProgress(ProgressLayout.INSTALL_MODPACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String tryDownloadIcon() {
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
try (Base64OutputStream base64OutputStream = new Base64OutputStream(byteArrayOutputStream, Base64.DEFAULT)){
|
||||||
|
// Instead of appending and wasting memory with a StringBuilder, just write the prefix
|
||||||
|
// to the stream before the base64 icon data.
|
||||||
|
byteArrayOutputStream.write("data:image/png;base64,".getBytes(StandardCharsets.US_ASCII));
|
||||||
|
DownloadUtils.download(mBtaVersion.iconUrl, base64OutputStream);
|
||||||
|
return new String(byteArrayOutputStream.toByteArray(), StandardCharsets.US_ASCII);
|
||||||
|
}catch (IOException e) {
|
||||||
|
Log.w("BTADownloadTask", "Failed to download base64 icon", e);
|
||||||
|
}finally {
|
||||||
|
try {
|
||||||
|
byteArrayOutputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.wtf("BTADownloadTask", "Failed to close a byte array stream??", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createJson(String btaVersionId) throws IOException {
|
||||||
|
String btaJson = String.format(BASE_JSON, mBtaVersion.versionName, mBtaVersion.downloadUrl, btaVersionId);
|
||||||
|
File jsonDir = new File(Tools.DIR_HOME_VERSION, btaVersionId);
|
||||||
|
File jsonFile = new File(jsonDir, btaVersionId+".json");
|
||||||
|
FileUtils.ensureDirectory(jsonDir);
|
||||||
|
Tools.write(jsonFile.getAbsolutePath(), btaJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BTA doesn't have SHA1 checksums in its repositories, so the user may try to reinstall it
|
||||||
|
// if it didn't work due to a broken download. So, for reinstalls like that to work,
|
||||||
|
// we need to delete the old client jar to force the download of a new one.
|
||||||
|
private void removeOldClient() throws IOException{
|
||||||
|
File btaClientPath = new File(Tools.DIR_HOME_LIBRARY, String.format("bta-client/bta-client-%1$s.jar", mBtaVersion.versionName));
|
||||||
|
if(btaClientPath.exists() && !btaClientPath.delete())
|
||||||
|
throw new IOException("Failed to delete old client jar");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProfile(String btaVersionId) throws IOException {
|
||||||
|
LauncherProfiles.load();
|
||||||
|
MinecraftProfile btaProfile = new MinecraftProfile();
|
||||||
|
btaProfile.lastVersionId = btaVersionId;
|
||||||
|
btaProfile.name = "Better than Adventure!";
|
||||||
|
btaProfile.icon = tryDownloadIcon();
|
||||||
|
LauncherProfiles.insertMinecraftProfile(btaProfile);
|
||||||
|
LauncherProfiles.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runCatching() throws IOException {
|
||||||
|
removeOldClient();
|
||||||
|
String btaVersionId = "bta-"+mBtaVersion.versionName;
|
||||||
|
createJson(btaVersionId);
|
||||||
|
createProfile(btaVersionId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
package net.kdt.pojavlaunch.modloaders;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.Tools;
|
||||||
|
import net.kdt.pojavlaunch.utils.DownloadUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
public class BTAUtils {
|
||||||
|
private static final String BTA_CLIENT_URL = "https://downloads.betterthanadventure.net/bta-client/release/%s/client.jar";
|
||||||
|
private static final String BTA_ICON_URL = "https://downloads.betterthanadventure.net/bta-client/release/%s/auto/%s.png";
|
||||||
|
private static final List<String> BTA_TESTED_VERSIONS = new ArrayList<>();
|
||||||
|
static {
|
||||||
|
BTA_TESTED_VERSIONS.add("v7.3");
|
||||||
|
BTA_TESTED_VERSIONS.add("v7.2_01");
|
||||||
|
BTA_TESTED_VERSIONS.add("v7.2");
|
||||||
|
BTA_TESTED_VERSIONS.add("v7.1_01");
|
||||||
|
BTA_TESTED_VERSIONS.add("v7.1");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getIconUrl(String version) {
|
||||||
|
String versionUnderscore = version.replace('.','_');
|
||||||
|
return String.format(BTA_ICON_URL, version, versionUnderscore);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<BTAVersion> createVersionList(List<String> versionStrings) {
|
||||||
|
ListIterator<String> iterator = versionStrings.listIterator(versionStrings.size());
|
||||||
|
ArrayList<BTAVersion> btaVersions = new ArrayList<>(versionStrings.size());
|
||||||
|
while(iterator.hasPrevious()) {
|
||||||
|
String version = iterator.previous();
|
||||||
|
btaVersions.add(new BTAVersion(
|
||||||
|
version,
|
||||||
|
String.format(BTA_CLIENT_URL, version),
|
||||||
|
getIconUrl(version)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
btaVersions.trimToSize();
|
||||||
|
return btaVersions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BTAVersionList processReleasesJson(String releasesInfo) throws JsonParseException {
|
||||||
|
BTAVersionsManifest manifest = Tools.GLOBAL_GSON.fromJson(releasesInfo, BTAVersionsManifest.class);
|
||||||
|
List<String> stringVersions = manifest.versions;
|
||||||
|
List<String> testedVersions = new ArrayList<>();
|
||||||
|
List<String> untestedVersions = new ArrayList<>();
|
||||||
|
for(String version : stringVersions) {
|
||||||
|
if(version == null) break;
|
||||||
|
if(BTA_TESTED_VERSIONS.contains(version)) {
|
||||||
|
testedVersions.add(version);
|
||||||
|
}else {
|
||||||
|
untestedVersions.add(version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BTAVersionList(
|
||||||
|
createVersionList(testedVersions),
|
||||||
|
createVersionList(untestedVersions)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BTAVersionList downloadVersionList() throws IOException {
|
||||||
|
try {
|
||||||
|
return DownloadUtils.downloadStringCached(
|
||||||
|
"https://downloads.betterthanadventure.net/bta-client/release/versions.json",
|
||||||
|
"bta_releases", BTAUtils::processReleasesJson);
|
||||||
|
}catch (DownloadUtils.ParseException e) {
|
||||||
|
Log.e("BTAUtils", "Failed to process json", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BTAVersionsManifest {
|
||||||
|
@Keep
|
||||||
|
public List<String> versions;
|
||||||
|
@Keep
|
||||||
|
@SerializedName("default")
|
||||||
|
public String defaultVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BTAVersion {
|
||||||
|
public final String versionName;
|
||||||
|
public final String downloadUrl;
|
||||||
|
public final String iconUrl;
|
||||||
|
|
||||||
|
public BTAVersion(String versionName, String downloadUrl, String iconUrl) {
|
||||||
|
this.versionName = versionName;
|
||||||
|
this.downloadUrl = downloadUrl;
|
||||||
|
this.iconUrl = iconUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static class BTAVersionList {
|
||||||
|
public final List<BTAVersion> testedVersions;
|
||||||
|
public final List<BTAVersion> untestedVersions;
|
||||||
|
|
||||||
|
public BTAVersionList(List<BTAVersion> mTestedVersions, List<BTAVersion> mUntestedVersions) {
|
||||||
|
this.testedVersions = mTestedVersions;
|
||||||
|
this.untestedVersions = mUntestedVersions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package net.kdt.pojavlaunch.modloaders;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseExpandableListAdapter;
|
||||||
|
import android.widget.ExpandableListAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import net.kdt.pojavlaunch.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BTAVersionListAdapter extends BaseExpandableListAdapter implements ExpandableListAdapter{
|
||||||
|
private final LayoutInflater mLayoutInflater;
|
||||||
|
private final ArrayList<String> mGroupNames;
|
||||||
|
private final ArrayList<List<BTAUtils.BTAVersion>> mGroups;
|
||||||
|
|
||||||
|
public BTAVersionListAdapter(BTAUtils.BTAVersionList versionList, LayoutInflater mLayoutInflater) {
|
||||||
|
this.mLayoutInflater = mLayoutInflater;
|
||||||
|
Context context = mLayoutInflater.getContext();
|
||||||
|
mGroupNames = new ArrayList<>(2);
|
||||||
|
mGroups = new ArrayList<>(2);
|
||||||
|
if(!versionList.testedVersions.isEmpty()) {
|
||||||
|
mGroupNames.add(context.getString(R.string.bta_installer_available_versions));
|
||||||
|
mGroups.add(versionList.testedVersions);
|
||||||
|
}
|
||||||
|
if(!versionList.untestedVersions.isEmpty()) {
|
||||||
|
mGroupNames.add(context.getString(R.string.bta_installer_untested_versions));
|
||||||
|
mGroups.add(versionList.untestedVersions);
|
||||||
|
}
|
||||||
|
mGroupNames.trimToSize();
|
||||||
|
mGroups.trimToSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGroupCount() {
|
||||||
|
return mGroups.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildrenCount(int i) {
|
||||||
|
return mGroups.get(i).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getGroup(int i) {
|
||||||
|
return mGroupNames.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getChild(int i, int i1) {
|
||||||
|
return mGroups.get(i).get(i1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getGroupId(int i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getChildId(int i, int i1) {
|
||||||
|
return i1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStableIds() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getGroupView(int i, boolean b, View convertView, ViewGroup viewGroup) {
|
||||||
|
if(convertView == null)
|
||||||
|
convertView = mLayoutInflater.inflate(android.R.layout.simple_expandable_list_item_1, viewGroup, false);
|
||||||
|
|
||||||
|
((TextView) convertView).setText((String)getGroup(i));
|
||||||
|
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getChildView(int i, int i1, boolean b, View convertView, ViewGroup viewGroup) {
|
||||||
|
if(convertView == null)
|
||||||
|
convertView = mLayoutInflater.inflate(android.R.layout.simple_expandable_list_item_1, viewGroup, false);
|
||||||
|
((TextView) convertView).setText(((BTAUtils.BTAVersion)getChild(i,i1)).versionName);
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChildSelectable(int i, int i1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -111,6 +111,14 @@
|
|||||||
android:layout_marginTop="@dimen/padding_large"
|
android:layout_marginTop="@dimen/padding_large"
|
||||||
android:text="@string/modpack_install_button" />
|
android:text="@string/modpack_install_button" />
|
||||||
|
|
||||||
|
<com.kdt.mcgui.MineButton
|
||||||
|
android:id="@+id/modded_profile_bta"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="@dimen/padding_large"
|
||||||
|
android:layout_marginTop="@dimen/padding_large"
|
||||||
|
android:text="@string/create_bta_profile" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
<androidx.constraintlayout.widget.Guideline
|
||||||
android:id="@+id/guideline"
|
android:id="@+id/guideline"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -424,4 +424,8 @@
|
|||||||
<string name="local_login_bad_username_title">Unsuitable username</string>
|
<string name="local_login_bad_username_title">Unsuitable username</string>
|
||||||
<string name="local_login_bad_username_text">The username must be between 3–16 characters long, and must only contain latin letters, numbers 0–9 and underscores.</string>
|
<string name="local_login_bad_username_text">The username must be between 3–16 characters long, and must only contain latin letters, numbers 0–9 and underscores.</string>
|
||||||
<string name="quick_setting_title">Quick settings</string>
|
<string name="quick_setting_title">Quick settings</string>
|
||||||
|
<string name="create_bta_profile">Create \"Better than Adventure!\" profile</string>
|
||||||
|
<string name="select_bta_version">Select \"Better than Adventure!\" version</string>
|
||||||
|
<string name="bta_installer_available_versions">Supported BTA versions</string>
|
||||||
|
<string name="bta_installer_untested_versions">Untested BTA versions</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1045,6 +1045,12 @@ public class GLFW
|
|||||||
nglfwSetShowingWindow(window);
|
nglfwSetShowingWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void glfwHideWindow(long window) {
|
||||||
|
GLFWWindowProperties win = internalGetWindow(window);
|
||||||
|
win.windowAttribs.put(GLFW_HOVERED, 0);
|
||||||
|
win.windowAttribs.put(GLFW_VISIBLE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public static void glfwWindowHint(int hint, int value) {
|
public static void glfwWindowHint(int hint, int value) {
|
||||||
if (hint == GLFW_VISIBLE) {
|
if (hint == GLFW_VISIBLE) {
|
||||||
mGLFWWindowVisibleOnCreation = value == GLFW_TRUE;
|
mGLFWWindowVisibleOnCreation = value == GLFW_TRUE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user