Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat[launcher]: add built-in support for the "Better than Adventure!" mod #6602

Merged
merged 7 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ public static void launchMinecraft(final AppCompatActivity activity, MinecraftAc
}
javaArgList.addAll(Arrays.asList(getMinecraftJVMArgs(versionId, gamedir)));
javaArgList.add("-cp");
javaArgList.add(getLWJGL3ClassPath() + ":" + launchClassPath);
javaArgList.add(launchClassPath + ":" + getLWJGL3ClassPath());

javaArgList.add(versionInfo.mainClass);
javaArgList.addAll(Arrays.asList(launchArgs));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
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> {
public static final String TAG = "BTAInstallFragment";

public BTAInstallFragment() {
super(TAG);
}

@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 BTAUtils.BTAVersionList loadVersionList() throws IOException {
return BTAUtils.downloadVersionList();
}

@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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,8 @@
public class FabricInstallFragment extends FabriclikeInstallFragment {

public static final String TAG = "FabricInstallFragment";
private static ModloaderListenerProxy sTaskProxy;

public FabricInstallFragment() {
super(FabriclikeUtils.FABRIC_UTILS);
}

@Override
protected ModloaderListenerProxy getListenerProxy() {
return sTaskProxy;
}

@Override
protected void setListenerProxy(ModloaderListenerProxy listenerProxy) {
sTaskProxy = listenerProxy;
super(FabriclikeUtils.FABRIC_UTILS, TAG);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import net.kdt.pojavlaunch.PojavApplication;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.extra.ExtraCore;
import net.kdt.pojavlaunch.modloaders.FabriclikeDownloadTask;
import net.kdt.pojavlaunch.modloaders.FabriclikeUtils;
import net.kdt.pojavlaunch.modloaders.FabricVersion;
Expand All @@ -36,6 +37,7 @@

public abstract class FabriclikeInstallFragment extends Fragment implements ModloaderDownloadListener, CompoundButton.OnCheckedChangeListener {
private final FabriclikeUtils mFabriclikeUtils;
private final String mExtraTag;
private Spinner mGameVersionSpinner;
private FabricVersion[] mGameVersionArray;
private Future<?> mGameVersionFuture;
Expand All @@ -48,9 +50,10 @@ public abstract class FabriclikeInstallFragment extends Fragment implements Modl
private Button mStartButton;
private View mRetryView;
private CheckBox mOnlyStableCheckbox;
protected FabriclikeInstallFragment(FabriclikeUtils mFabriclikeUtils) {
protected FabriclikeInstallFragment(FabriclikeUtils mFabriclikeUtils, String mFragmentTag) {
super(R.layout.fragment_fabric_install);
this.mFabriclikeUtils = mFabriclikeUtils;
this.mExtraTag = mFragmentTag + "_proxy";
}

@Override
Expand Down Expand Up @@ -290,6 +293,10 @@ private void updateGameSpinner() {
mGameVersionSpinner.setAdapter(createAdapter(mGameVersionArray, mOnlyStableCheckbox.isChecked()));
}

protected abstract ModloaderListenerProxy getListenerProxy();
protected abstract void setListenerProxy(ModloaderListenerProxy listenerProxy);
private ModloaderListenerProxy getListenerProxy() {
return (ModloaderListenerProxy) ExtraCore.getValue(mExtraTag);
}
private void setListenerProxy(ModloaderListenerProxy listenerProxy) {
ExtraCore.setValue(mExtraTag, listenerProxy);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

public class ForgeInstallFragment extends ModVersionListFragment<List<String>> {
public static final String TAG = "ForgeInstallFragment";
private static ModloaderListenerProxy sTaskProxy;
public ForgeInstallFragment() {
super(TAG);
}

@Override
public void onAttach(@NonNull Context context) {
Expand All @@ -38,15 +40,6 @@ public int getNoDataMsg() {
return R.string.forge_dl_no_installer;
}

@Override
public ModloaderListenerProxy getTaskProxy() {
return sTaskProxy;
}
@Override
public void setTaskProxy(ModloaderListenerProxy proxy) {
sTaskProxy = proxy;
}

@Override
public List<String> loadVersionList() throws IOException {
return ForgeUtils.downloadForgeVersions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.extra.ExtraCore;
import net.kdt.pojavlaunch.mirrors.DownloadMirror;
import net.kdt.pojavlaunch.modloaders.ModloaderDownloadListener;
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
Expand All @@ -25,14 +26,15 @@
import java.io.IOException;

public abstract class ModVersionListFragment<T> extends Fragment implements Runnable, View.OnClickListener, ExpandableListView.OnChildClickListener, ModloaderDownloadListener {
public static final String TAG = "ForgeInstallFragment";
private final String mExtraTag;
private ExpandableListView mExpandableListView;
private ProgressBar mProgressBar;
private LayoutInflater mInflater;
private View mRetryView;

public ModVersionListFragment() {
public ModVersionListFragment(String mFragmentTag) {
super(R.layout.fragment_mod_version_list);
this.mExtraTag = mFragmentTag + "_proxy";
}

@Override
Expand Down Expand Up @@ -148,11 +150,19 @@ public void onDownloadError(Exception e) {
});
}

private void setTaskProxy(ModloaderListenerProxy proxy) {
ExtraCore.setValue(mExtraTag, proxy);
}

private ModloaderListenerProxy getTaskProxy() {
return (ModloaderListenerProxy) ExtraCore.getValue(mExtraTag);
}

public abstract int getTitleText();
public abstract int getNoDataMsg();
public abstract ModloaderListenerProxy getTaskProxy();

public abstract T loadVersionList() throws IOException;
public abstract void setTaskProxy(ModloaderListenerProxy proxy);

public abstract ExpandableListAdapter createAdapter(T versionList, LayoutInflater layoutInflater);
public abstract Runnable createDownloadTask(Object selectedVersion, ModloaderListenerProxy listenerProxy);
public abstract void onDownloadFinished(Context context, File downloadedFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import net.kdt.pojavlaunch.JavaGUILauncherActivity;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.Tools;
import net.kdt.pojavlaunch.modloaders.ModloaderListenerProxy;
import net.kdt.pojavlaunch.modloaders.OptiFineDownloadTask;
import net.kdt.pojavlaunch.modloaders.OptiFineUtils;
Expand All @@ -18,7 +17,9 @@

public class OptiFineInstallFragment extends ModVersionListFragment<OptiFineUtils.OptiFineVersions> {
public static final String TAG = "OptiFineInstallFragment";
private static ModloaderListenerProxy sTaskProxy;
public OptiFineInstallFragment() {
super(TAG);
}
@Override
public int getTitleText() {
return R.string.of_dl_select_version;
Expand All @@ -28,22 +29,11 @@ public int getTitleText() {
public int getNoDataMsg() {
return R.string.of_dl_failed_to_scrape;
}

@Override
public ModloaderListenerProxy getTaskProxy() {
return sTaskProxy;
}

@Override
public OptiFineUtils.OptiFineVersions loadVersionList() throws IOException {
return OptiFineUtils.downloadOptiFineVersions();
}

@Override
public void setTaskProxy(ModloaderListenerProxy proxy) {
sTaskProxy = proxy;
}

@Override
public ExpandableListAdapter createAdapter(OptiFineUtils.OptiFineVersions versionList, LayoutInflater layoutInflater) {
return new OptiFineVersionListAdapter(versionList, layoutInflater);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
Tools.swapFragment(requireActivity(), SearchModFragment.class, SearchModFragment.TAG, null));
view.findViewById(R.id.modded_profile_quilt).setOnClickListener((v)->
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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@ public class QuiltInstallFragment extends FabriclikeInstallFragment {
private static ModloaderListenerProxy sTaskProxy;

public QuiltInstallFragment() {
super(FabriclikeUtils.QUILT_UTILS);
}

@Override
protected ModloaderListenerProxy getListenerProxy() {
return sTaskProxy;
}

@Override
protected void setListenerProxy(ModloaderListenerProxy listenerProxy) {
sTaskProxy = listenerProxy;
super(FabriclikeUtils.QUILT_UTILS, TAG);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
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!";
// Allows for smooth upgrades
btaProfile.gameDir = "./custom_instances/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);
}
}
Loading
Loading