download pages

This commit is contained in:
Tungstend 2023-07-06 04:32:07 +08:00
parent ddc17f1c91
commit df63064360
13 changed files with 1184 additions and 23 deletions

View File

@ -1,19 +1,245 @@
package com.tungsten.fcl.ui.download;
import android.content.Context;
import android.content.res.ColorStateList;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ScrollView;
import com.tungsten.fcl.R;
import com.tungsten.fcl.util.AndroidUtils;
import com.tungsten.fcl.util.FXUtils;
import com.tungsten.fclcore.fakefx.beans.property.BooleanProperty;
import com.tungsten.fclcore.fakefx.beans.property.ListProperty;
import com.tungsten.fclcore.fakefx.beans.property.ObjectProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleBooleanProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleListProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleObjectProperty;
import com.tungsten.fclcore.fakefx.beans.property.SimpleStringProperty;
import com.tungsten.fclcore.fakefx.beans.property.StringProperty;
import com.tungsten.fclcore.fakefx.collections.FXCollections;
import com.tungsten.fclcore.mod.RemoteMod;
import com.tungsten.fclcore.mod.RemoteModRepository;
import com.tungsten.fclcore.task.Schedulers;
import com.tungsten.fclcore.task.Task;
import com.tungsten.fclcore.task.TaskExecutor;
import com.tungsten.fclcore.util.Lang;
import com.tungsten.fclcore.util.StringUtils;
import com.tungsten.fcllibrary.component.theme.ThemeEngine;
import com.tungsten.fcllibrary.component.ui.FCLCommonPage;
import com.tungsten.fcllibrary.component.view.FCLButton;
import com.tungsten.fcllibrary.component.view.FCLEditText;
import com.tungsten.fcllibrary.component.view.FCLProgressBar;
import com.tungsten.fcllibrary.component.view.FCLSpinner;
import com.tungsten.fcllibrary.component.view.FCLUILayout;
public class DownloadPage extends FCLCommonPage {
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public DownloadPage(Context context, int id, FCLUILayout parent, int resId) {
public class DownloadPage extends FCLCommonPage implements View.OnClickListener {
protected RemoteModRepository repository;
protected final BooleanProperty supportChinese = new SimpleBooleanProperty();
protected final ListProperty<String> downloadSources = new SimpleListProperty<>(this, "downloadSources", FXCollections.observableArrayList());
protected final StringProperty downloadSource = new SimpleStringProperty();
private final StringProperty gameVersion = new SimpleStringProperty(this, "gameVersion", "");
private final ObjectProperty<CategoryIndented> category = new SimpleObjectProperty<>(this, "category", new CategoryIndented(0, null));
private final ObjectProperty<RemoteModRepository.SortType> sortType = new SimpleObjectProperty<>(this, "sortType", RemoteModRepository.SortType.POPULARITY);
private TaskExecutor executor;
private RemoteModListAdapter adapter;
private ScrollView searchLayout;
private FCLEditText nameEditText;
private FCLSpinner<String> sourceSpinner;
private FCLSpinner<String> gameVersionSpinner;
private FCLSpinner<CategoryIndented> categorySpinner;
private FCLSpinner<RemoteModRepository.SortType> sortSpinner;
private FCLButton search;
private ListView listView;
private FCLProgressBar progressBar;
public void setLoading(boolean loading) {
Schedulers.androidUIThread().execute(() -> {
search.setEnabled(!loading);
nameEditText.setEnabled(!loading);
sourceSpinner.setEnabled(!loading);
gameVersionSpinner.setEnabled(!loading);
categorySpinner.setEnabled(!loading);
sortSpinner.setEnabled(!loading);
progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
listView.setVisibility(loading ? View.GONE : View.VISIBLE);
});
}
public void search() {
search(gameVersion.get(),
category.get().getCategory(),
0,
Objects.requireNonNull(nameEditText.getText()).toString(),
sortType.get());
}
public void search(String userGameVersion, RemoteModRepository.Category category, int pageOffset, String searchFilter, RemoteModRepository.SortType sort) {
setLoading(true);
if (executor != null && !executor.isCancelled()) {
executor.cancel();
}
executor = Task.supplyAsync(() -> repository.search(userGameVersion, category, pageOffset, 50, searchFilter, sort, RemoteModRepository.SortOrder.DESC))
.whenComplete(Schedulers.androidUIThread(), (result, exception) -> {
setLoading(false);
if (exception == null) {
ArrayList<RemoteMod> list = result.collect(Collectors.toCollection(ArrayList::new));
adapter = new RemoteModListAdapter(getContext(), this, list, mod -> {
});
listView.setAdapter(adapter);
}
}).executor(true);
}
protected String getLocalizedCategory(String category) {
return AndroidUtils.getLocalizedText(getContext(), "curse_category_" + category);
}
protected String getLocalizedCategoryIndent(CategoryIndented category) {
return StringUtils.repeats(' ', category.getIndent() * 4) +
(category.getCategory() == null
? getContext().getString(R.string.curse_category_0)
: getLocalizedCategory(category.getCategory().getId()));
}
public DownloadPage(Context context, int id, FCLUILayout parent, int resId, RemoteModRepository repository) {
super(context, id, parent, resId);
this.repository = repository;
if (repository != null) {
create();
}
}
public void create() {
searchLayout = findViewById(R.id.search_layout);
ThemeEngine.getInstance().registerEvent(searchLayout, () -> searchLayout.setBackgroundTintList(new ColorStateList(new int[][] { { } }, new int[] { ThemeEngine.getInstance().getTheme().getLtColor() })));
search = findViewById(R.id.search);
search.setOnClickListener(this);
nameEditText = findViewById(R.id.name);
sourceSpinner = findViewById(R.id.download_source);
gameVersionSpinner = findViewById(R.id.game_version);
categorySpinner = findViewById(R.id.category);
sortSpinner = findViewById(R.id.sort);
listView = findViewById(R.id.list);
progressBar = findViewById(R.id.progress);
nameEditText.setHint(supportChinese.get() ? getContext().getString(R.string.search_hint_chinese) : getContext().getString(R.string.search_hint_english));
sourceSpinner.setVisibility(downloadSources.getSize() > 1 ? View.VISIBLE : View.GONE);
if (downloadSources.getSize() > 1) {
sourceSpinner.setDataList(new ArrayList<>(downloadSources));
ArrayAdapter<String> sourceAdapter = new ArrayAdapter<>(getContext(), R.layout.item_spinner, new ArrayList<>(downloadSources));
sourceAdapter.setDropDownViewResource(R.layout.item_spinner_dropdown);
sourceSpinner.setAdapter(sourceAdapter);
sourceSpinner.setSelection(downloadSource.get().equals(getContext().getString(R.string.mods_modrinth)) ? 1 : 0);
FXUtils.bindSelection(sourceSpinner, downloadSource);
}
gameVersionSpinner.setDataList(new ArrayList<>(Arrays.stream(RemoteModRepository.DEFAULT_GAME_VERSIONS).collect(Collectors.toList())));
ArrayAdapter<String> gameVersionAdapter = new ArrayAdapter<>(getContext(), R.layout.item_spinner, new ArrayList<>(Arrays.stream(RemoteModRepository.DEFAULT_GAME_VERSIONS).collect(Collectors.toList())));
gameVersionAdapter.setDropDownViewResource(R.layout.item_spinner_dropdown);
gameVersionSpinner.setAdapter(gameVersionAdapter);
gameVersionSpinner.setSelection(0);
FXUtils.bindSelection(gameVersionSpinner, gameVersion);
ArrayList<CategoryIndented> categoryDataList = new ArrayList<>();
categoryDataList.add(new CategoryIndented(0, null));
categorySpinner.setDataList(categoryDataList);
ArrayList<String> categoryStringList = categoryDataList.stream().map(this::getLocalizedCategoryIndent).collect(Collectors.toCollection(ArrayList::new));
ArrayAdapter<String> categoryAdapter = new ArrayAdapter<>(getContext(), R.layout.item_spinner, categoryStringList);
categoryAdapter.setDropDownViewResource(R.layout.item_spinner_dropdown);
categorySpinner.setAdapter(categoryAdapter);
categorySpinner.setSelection(0);
FXUtils.bindSelection(categorySpinner, category);
downloadSource.addListener(observable -> Task.supplyAsync(() -> {
setLoading(true);
return repository.getCategories();
}).thenAcceptAsync(Schedulers.androidUIThread(), categories -> {
ArrayList<CategoryIndented> result = new ArrayList<>();
result.add(new CategoryIndented(0, null));
for (RemoteModRepository.Category category : Lang.toIterable(categories)) {
resolveCategory(category, 0, result);
}
categorySpinner.setDataList(result);
ArrayList<String> resultStr = result.stream().map(this::getLocalizedCategoryIndent).collect(Collectors.toCollection(ArrayList::new));
ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), R.layout.item_spinner, resultStr);
adapter.setDropDownViewResource(R.layout.item_spinner_dropdown);
categorySpinner.setAdapter(adapter);
FXUtils.unbindSelection(categorySpinner, category);
categorySpinner.setSelection(0);
category.set(result.get(0));
FXUtils.bindSelection(categorySpinner, category);
search();
}).start());
sortSpinner.setDataList(new ArrayList<>(Arrays.stream(RemoteModRepository.SortType.values()).collect(Collectors.toList())));
ArrayList<String> sorts = new ArrayList<>();
sorts.add(getContext().getString(R.string.curse_sort_popularity));
sorts.add(getContext().getString(R.string.curse_sort_name));
sorts.add(getContext().getString(R.string.curse_sort_date_created));
sorts.add(getContext().getString(R.string.curse_sort_last_updated));
sorts.add(getContext().getString(R.string.curse_sort_author));
sorts.add(getContext().getString(R.string.curse_sort_total_downloads));
ArrayAdapter<String> sortAdapter = new ArrayAdapter<>(getContext(), R.layout.item_spinner, sorts);
sortAdapter.setDropDownViewResource(R.layout.item_spinner_dropdown);
sortSpinner.setAdapter(sortAdapter);
sortSpinner.setSelection(0);
FXUtils.bindSelection(sortSpinner, sortType);
search("", null, 0, "", RemoteModRepository.SortType.POPULARITY);
}
@Override
public Task<?> refresh(Object... param) {
return null;
}
@Override
public void onClick(View v) {
if (v == search) {
search();
}
}
private static class CategoryIndented {
private final int indent;
private final RemoteModRepository.Category category;
public CategoryIndented(int indent, RemoteModRepository.Category category) {
this.indent = indent;
this.category = category;
}
public int getIndent() {
return indent;
}
public RemoteModRepository.Category getCategory() {
return category;
}
}
private static void resolveCategory(RemoteModRepository.Category category, int indent, List<CategoryIndented> result) {
result.add(new CategoryIndented(indent, category));
for (RemoteModRepository.Category subcategory : category.getSubcategories()) {
resolveCategory(subcategory, indent + 1, result);
}
}
}

View File

@ -5,6 +5,7 @@ import android.content.Context;
import com.tungsten.fcl.R;
import com.tungsten.fcl.ui.PageManager;
import com.tungsten.fcl.ui.UIListener;
import com.tungsten.fclcore.mod.curse.CurseForgeRemoteModRepository;
import com.tungsten.fcllibrary.component.ui.FCLCommonPage;
import com.tungsten.fcllibrary.component.view.FCLUILayout;
@ -21,8 +22,8 @@ public class DownloadPageManager extends PageManager {
private static DownloadPageManager instance;
private InstallVersionPage installVersionPage;
private DownloadPage downloadModpackPage;
private DownloadPage downloadModPage;
private ModpackDownloadPage downloadModpackPage;
private ModDownloadPage downloadModPage;
private DownloadPage downloadResourcePackPage;
private DownloadPage downloadWorldPage;
@ -41,10 +42,10 @@ public class DownloadPageManager extends PageManager {
@Override
public void init(UIListener listener) {
installVersionPage = new InstallVersionPage(getContext(), PAGE_ID_DOWNLOAD_GAME, getParent(), R.layout.page_install_version);
downloadModpackPage = new DownloadPage(getContext(), PAGE_ID_DOWNLOAD_MODPACK, getParent(), R.layout.page_download);
downloadModPage = new DownloadPage(getContext(), PAGE_ID_DOWNLOAD_MOD, getParent(), R.layout.page_download);
downloadResourcePackPage = new DownloadPage(getContext(), PAGE_ID_DOWNLOAD_RESOURCE_PACK, getParent(), R.layout.page_download);
downloadWorldPage = new DownloadPage(getContext(), PAGE_ID_DOWNLOAD_WORLD, getParent(), R.layout.page_download);
downloadModpackPage = new ModpackDownloadPage(getContext(), PAGE_ID_DOWNLOAD_MODPACK, getParent(), R.layout.page_download);
downloadModPage = new ModDownloadPage(getContext(), PAGE_ID_DOWNLOAD_MOD, getParent(), R.layout.page_download);
downloadResourcePackPage = new DownloadPage(getContext(), PAGE_ID_DOWNLOAD_RESOURCE_PACK, getParent(), R.layout.page_download, CurseForgeRemoteModRepository.RESOURCE_PACKS);
downloadWorldPage = new DownloadPage(getContext(), PAGE_ID_DOWNLOAD_WORLD, getParent(), R.layout.page_download, CurseForgeRemoteModRepository.WORLDS);
if (listener != null) {
listener.onLoad();

View File

@ -0,0 +1,56 @@
package com.tungsten.fcl.ui.download;
import android.content.Context;
import com.tungsten.fcl.R;
import com.tungsten.fcl.game.LocalizedRemoteModRepository;
import com.tungsten.fcl.util.AndroidUtils;
import com.tungsten.fclcore.mod.RemoteModRepository;
import com.tungsten.fclcore.mod.curse.CurseForgeRemoteModRepository;
import com.tungsten.fclcore.mod.modrinth.ModrinthRemoteModRepository;
import com.tungsten.fcllibrary.component.view.FCLUILayout;
public class ModDownloadPage extends DownloadPage {
public ModDownloadPage(Context context, int id, FCLUILayout parent, int resId) {
super(context, id, parent, resId, null);
repository = new Repository();
supportChinese.set(true);
downloadSources.get().setAll(context.getString(R.string.mods_curseforge), context.getString(R.string.mods_modrinth));
if (CurseForgeRemoteModRepository.isAvailable())
downloadSource.set(context.getString(R.string.mods_curseforge));
else
downloadSource.set(context.getString(R.string.mods_modrinth));
create();
}
private class Repository extends LocalizedRemoteModRepository {
@Override
protected RemoteModRepository getBackedRemoteModRepository() {
if (getContext().getString(R.string.mods_modrinth).equals(downloadSource.get())) {
return ModrinthRemoteModRepository.MODS;
} else {
return CurseForgeRemoteModRepository.MODS;
}
}
@Override
public Type getType() {
return Type.MOD;
}
}
@Override
protected String getLocalizedCategory(String category) {
if (getContext().getString(R.string.mods_modrinth).equals(downloadSource.get())) {
return AndroidUtils.getLocalizedText(getContext(), "modrinth_category_" + category.replaceAll("-", "_"));
} else {
return AndroidUtils.getLocalizedText(getContext(), "curse_category_" + category);
}
}
}

View File

@ -0,0 +1,76 @@
package com.tungsten.fcl.ui.download;
import android.content.Context;
import android.view.View;
import com.tungsten.fcl.R;
import com.tungsten.fcl.game.LocalizedRemoteModRepository;
import com.tungsten.fcl.ui.version.Versions;
import com.tungsten.fcl.util.AndroidUtils;
import com.tungsten.fclcore.mod.RemoteModRepository;
import com.tungsten.fclcore.mod.curse.CurseForgeRemoteModRepository;
import com.tungsten.fclcore.mod.modrinth.ModrinthRemoteModRepository;
import com.tungsten.fcllibrary.component.view.FCLButton;
import com.tungsten.fcllibrary.component.view.FCLUILayout;
public class ModpackDownloadPage extends DownloadPage {
private FCLButton installModpack;
public ModpackDownloadPage(Context context, int id, FCLUILayout parent, int resId) {
super(context, id, parent, resId, null);
repository = new Repository();
supportChinese.set(true);
downloadSources.get().setAll(context.getString(R.string.mods_curseforge), context.getString(R.string.mods_modrinth));
if (CurseForgeRemoteModRepository.isAvailable())
downloadSource.set(context.getString(R.string.mods_curseforge));
else
downloadSource.set(context.getString(R.string.mods_modrinth));
create();
}
private class Repository extends LocalizedRemoteModRepository {
@Override
protected RemoteModRepository getBackedRemoteModRepository() {
if (getContext().getString(R.string.mods_modrinth).equals(downloadSource.get())) {
return ModrinthRemoteModRepository.MODPACKS;
} else {
return CurseForgeRemoteModRepository.MODPACKS;
}
}
@Override
public Type getType() {
return Type.MODPACK;
}
}
@Override
protected String getLocalizedCategory(String category) {
if (getContext().getString(R.string.mods_modrinth).equals(downloadSource.get())) {
return AndroidUtils.getLocalizedText(getContext(), "modrinth_category_" + category.replaceAll("-", "_"));
} else {
return AndroidUtils.getLocalizedText(getContext(), "curse_category_" + category);
}
}
@Override
public void onCreate() {
super.onCreate();
installModpack = findViewById(R.id.install_modpack);
installModpack.setVisibility(View.VISIBLE);
installModpack.setOnClickListener(this);
}
@Override
public void onClick(View v) {
super.onClick(v);
if (v == installModpack) {
Versions.importModpack();
}
}
}

View File

@ -0,0 +1,108 @@
package com.tungsten.fcl.ui.download;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.tungsten.fcl.R;
import com.tungsten.fcl.util.ModTranslations;
import com.tungsten.fclcore.mod.RemoteMod;
import com.tungsten.fclcore.task.Schedulers;
import com.tungsten.fclcore.util.StringUtils;
import com.tungsten.fcllibrary.component.FCLAdapter;
import com.tungsten.fcllibrary.component.LocaleUtils;
import com.tungsten.fcllibrary.component.view.FCLImageView;
import com.tungsten.fcllibrary.component.view.FCLLinearLayout;
import com.tungsten.fcllibrary.component.view.FCLTextView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class RemoteModListAdapter extends FCLAdapter {
private final DownloadPage downloadPage;
private final ArrayList<RemoteMod> list;
private final Callback callback;
public RemoteModListAdapter(Context context, DownloadPage downloadPage, ArrayList<RemoteMod> list, Callback callback) {
super(context);
this.downloadPage = downloadPage;
this.list = list;
this.callback = callback;
}
private static class ViewHolder {
FCLLinearLayout parent;
FCLImageView icon;
FCLTextView name;
FCLTextView tag;
FCLTextView description;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
final ViewHolder viewHolder;
if (view == null) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(getContext()).inflate(R.layout.item_remote_version, null);
viewHolder.parent = view.findViewById(R.id.parent);
viewHolder.icon = view.findViewById(R.id.icon);
viewHolder.name = view.findViewById(R.id.version);
viewHolder.tag = view.findViewById(R.id.tag);
viewHolder.description = view.findViewById(R.id.date);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
RemoteMod remoteMod = list.get(i);
viewHolder.parent.setOnClickListener(v -> callback.onItemSelect(remoteMod));
viewHolder.icon.setImageDrawable(null);
viewHolder.icon.setTag(i);
new Thread(() -> {
try {
URL url = new URL(remoteMod.getIconUrl());
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setDoInput(true);
httpURLConnection.connect();
InputStream inputStream = httpURLConnection.getInputStream();
Bitmap icon = BitmapFactory.decodeStream(inputStream);
if (viewHolder.icon.getTag().equals(i)) {
Schedulers.androidUIThread().execute(() -> viewHolder.icon.setImageBitmap(icon));
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
ModTranslations.Mod mod = ModTranslations.getTranslationsByRepositoryType(downloadPage.repository.getType()).getModByCurseForgeId(remoteMod.getSlug());
viewHolder.name.setText(mod != null && LocaleUtils.isChinese(getContext()) ? mod.getDisplayName() : remoteMod.getTitle());
List<String> categories = remoteMod.getCategories().stream().map(downloadPage::getLocalizedCategory).collect(Collectors.toList());
StringBuilder stringBuilder = new StringBuilder();
categories.forEach(it -> stringBuilder.append(it).append(" "));
String tag = StringUtils.removeSuffix(stringBuilder.toString(), " ");
viewHolder.tag.setText(tag);
viewHolder.description.setText(remoteMod.getDescription());
return view;
}
public interface Callback {
void onItemSelect(RemoteMod mod);
}
}

View File

@ -2,6 +2,7 @@ package com.tungsten.fcl.ui.download;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
@ -18,6 +19,7 @@ import com.tungsten.fclcore.download.optifine.OptiFineRemoteVersion;
import com.tungsten.fclcore.download.quilt.QuiltAPIRemoteVersion;
import com.tungsten.fclcore.download.quilt.QuiltRemoteVersion;
import com.tungsten.fcllibrary.component.FCLAdapter;
import com.tungsten.fcllibrary.component.theme.ThemeEngine;
import com.tungsten.fcllibrary.component.view.FCLImageView;
import com.tungsten.fcllibrary.component.view.FCLLinearLayout;
import com.tungsten.fcllibrary.component.view.FCLTextView;
@ -55,6 +57,7 @@ public class RemoteVersionListAdapter extends FCLAdapter {
return list.get(i);
}
@SuppressLint("UseCompatLoadingForDrawables")
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
final ViewHolder viewHolder;
@ -74,6 +77,9 @@ public class RemoteVersionListAdapter extends FCLAdapter {
viewHolder.parent.setOnClickListener(view1 -> listener.onSelect(remoteVersion));
viewHolder.icon.setBackground(getIcon(remoteVersion));
viewHolder.version.setText(remoteVersion.getSelfVersion());
viewHolder.tag.setBackground(getContext().getDrawable(R.drawable.bg_container_white));
viewHolder.tag.setAutoBackgroundTint(true);
viewHolder.tag.setBackgroundTintList(new ColorStateList(new int[][] { { } }, new int[]{ ThemeEngine.getInstance().getTheme().getColor() }));
viewHolder.tag.setText(getTag(remoteVersion));
viewHolder.date.setVisibility(remoteVersion.getReleaseDate() == null ? View.GONE : View.VISIBLE);
viewHolder.date.setText(remoteVersion.getReleaseDate() == null ? "" : DateTimeFormatter.ofPattern(getContext().getString(R.string.world_time)).withZone(ZoneId.systemDefault()).format(remoteVersion.getReleaseDate().toInstant()));

View File

@ -8,6 +8,7 @@ import com.tungsten.fcl.activity.MainActivity;
import com.tungsten.fcl.game.LauncherHelper;
import com.tungsten.fcl.setting.Accounts;
import com.tungsten.fcl.setting.Profile;
import com.tungsten.fcl.setting.Profiles;
import com.tungsten.fcl.ui.TaskDialog;
import com.tungsten.fcl.ui.account.CreateAccountDialog;
import com.tungsten.fcl.util.RequestCodes;
@ -15,7 +16,6 @@ import com.tungsten.fcl.util.TaskCancellationAction;
import com.tungsten.fclcore.auth.Account;
import com.tungsten.fclcore.auth.AccountFactory;
import com.tungsten.fclcore.download.game.GameAssetDownloadTask;
import com.tungsten.fclcore.game.GameDirectoryType;
import com.tungsten.fclcore.task.Schedulers;
import com.tungsten.fclcore.task.Task;
import com.tungsten.fclcore.task.TaskExecutor;
@ -33,14 +33,14 @@ import java.util.logging.Level;
public class Versions {
/*
public static void importModpack() {
Profile profile = Profiles.getSelectedProfile();
if (profile.getRepository().isLoaded()) {
Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(profile), i18n("install.modpack"));
//Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(profile), i18n("install.modpack"));
}
}
/*
public static void downloadModpackImpl(Profile profile, String version, RemoteMod.Version file) {
Path modpack;
URL downloadURL;

View File

@ -45,7 +45,6 @@
app:auto_text_tint="true"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:background="@drawable/bg_container_white"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:paddingTop="2dp"
@ -57,7 +56,6 @@
android:id="@+id/tag"
android:layout_gravity="center"
android:singleLine="true"
app:auto_text_background_tint="true"
app:auto_text_tint="true"/>
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@ -1,8 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/ui_bg_color"
android:padding="10dp"
android:paddingTop="10dp"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/left"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintWidth_percent="0.3">
<ScrollView
android:id="@+id/search_layout"
android:background="@drawable/bg_container_white"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.appcompat.widget.LinearLayoutCompat
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/mods_name"
app:auto_text_tint="true"/>
<com.tungsten.fcllibrary.component.view.FCLEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="13sp"
android:id="@+id/name"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/settings_launcher_download_source"
app:auto_text_tint="true"/>
<com.tungsten.fcllibrary.component.view.FCLSpinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:id="@+id/download_source"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/world_game_version"
app:auto_text_tint="true"/>
<com.tungsten.fcllibrary.component.view.FCLSpinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:id="@+id/game_version"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/mods_category"
app:auto_text_tint="true"/>
<com.tungsten.fcllibrary.component.view.FCLSpinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:id="@+id/category"/>
<com.tungsten.fcllibrary.component.view.FCLTextView
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="@string/search_sort"
app:auto_text_tint="true"/>
<com.tungsten.fcllibrary.component.view.FCLSpinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:id="@+id/sort"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</ScrollView>
<com.tungsten.fcllibrary.component.view.FCLButton
android:visibility="gone"
app:ripple="true"
android:id="@+id/install_modpack"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/install_modpack"/>
<com.tungsten.fcllibrary.component.view.FCLButton
app:ripple="true"
android:id="@+id/search"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/search"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="10dp"
app:layout_constraintStart_toEndOf="@+id/left"
app:layout_constraintEnd_toEndOf="parent">
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
<com.tungsten.fcllibrary.component.view.FCLProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:id="@+id/progress"/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -107,6 +107,118 @@
<string name="control_select">选择布局</string>
<string name="control_share">分享布局</string>
<string name="curse_category_0">全部</string>
<string name="curse_category_4474">科幻</string>
<string name="curse_category_4481">轻量整合包</string>
<string name="curse_category_4483">战斗 PVP</string>
<string name="curse_category_4477">小游戏</string>
<string name="curse_category_4478">任务</string>
<string name="curse_category_4484">多人</string>
<string name="curse_category_4476">探索</string>
<string name="curse_category_6145">空岛</string>
<string name="curse_category_4475">冒险 RPG</string>
<string name="curse_category_4487">FTB 整合包</string>
<string name="curse_category_4480">有特定地图</string>
<string name="curse_category_4479">高难度</string>
<string name="curse_category_4482">大型整合包</string>
<string name="curse_category_4472">科技</string>
<string name="curse_category_4473">魔法</string>
<string name="curse_category_5128">原版增强</string>
<string name="curse_category_5299">教育</string>
<string name="curse_category_5232">额外行星</string>
<string name="curse_category_5129">原版增强</string>
<string name="curse_category_5189">实用与QOL</string>
<string name="curse_category_5190">QoL</string>
<string name="curse_category_5191">实用与QoL</string>
<string name="curse_category_5192">梦幻菜单</string>
<string name="curse_category_423">信息展示</string>
<string name="curse_category_426">模组扩展</string>
<string name="curse_category_434">装备武器</string>
<string name="curse_category_409">自然生成</string>
<string name="curse_category_4485">血魔法</string>
<string name="curse_category_420">存储</string>
<string name="curse_category_429">工业 (Industrialcraft)</string>
<string name="curse_category_419">魔法</string>
<string name="curse_category_412">科技</string>
<string name="curse_category_4557">红石</string>
<string name="curse_category_428">匠魂</string>
<string name="curse_category_414">交通运输</string>
<string name="curse_category_4486">幸运方块 (Lucky Blocks)</string>
<string name="curse_category_432">建筑 (Buildcraft)</string>
<string name="curse_category_418">基因</string>
<string name="curse_category_4671">Twitch</string>
<string name="curse_category_5314">KubeJS</string>
<string name="curse_category_408">矿物资源</string>
<string name="curse_category_4773">CraftTweaker</string>
<string name="curse_category_430">神秘 (Thaumcraft)</string>
<string name="curse_category_422">冒险 RPG</string>
<string name="curse_category_413">机器处理</string>
<string name="curse_category_417">能源</string>
<string name="curse_category_415">物流运输</string>
<string name="curse_category_433">林业 (Forestry)</string>
<string name="curse_category_425">其他</string>
<string name="curse_category_4545">应用能源 2 (Applied Energistics 2)</string>
<string name="curse_category_416">农业</string>
<string name="curse_category_421">支持库</string>
<string name="curse_category_4780">Fabric</string>
<string name="curse_category_424">装饰</string>
<string name="curse_category_406">世界生成</string>
<string name="curse_category_435">服务器</string>
<string name="curse_category_411">生物</string>
<string name="curse_category_407">生物群系</string>
<string name="curse_category_427">热力膨胀 (Thermal Expansion)</string>
<string name="curse_category_410">维度</string>
<string name="curse_category_436">食物</string>
<string name="curse_category_4558">红石</string>
<string name="curse_category_4843">自动化</string>
<string name="curse_category_4906">MCreator</string>
<string name="curse_category_5244">字体包</string>
<string name="curse_category_5193">数据包</string>
<string name="curse_category_399">蒸汽朋克</string>
<string name="curse_category_396">128x</string>
<string name="curse_category_398">512x 及更高</string>
<string name="curse_category_397">256x</string>
<string name="curse_category_405">其他</string>
<string name="curse_category_395">64x</string>
<string name="curse_category_400">仿真</string>
<string name="curse_category_393">16x</string>
<string name="curse_category_403">传统</string>
<string name="curse_category_394">32x</string>
<string name="curse_category_404">动态效果</string>
<string name="curse_category_4465">模组支持</string>
<string name="curse_category_402">中世纪风格</string>
<string name="curse_category_401">现代风格</string>
<string name="curse_category_4464">模组</string>
<string name="curse_category_250">游戏挑战</string>
<string name="curse_category_249">创造模式</string>
<string name="curse_category_251">跑酷</string>
<string name="curse_category_253">生存模式</string>
<string name="curse_category_248">冒险模式</string>
<string name="curse_category_252">解谜类</string>
<string name="curse_category_4551">硬核任务模式</string>
<string name="curse_category_4548">幸运方块 (Lucky Blocks)</string>
<string name="curse_category_4556">任务进度</string>
<string name="curse_category_4752">小物件</string>
<string name="curse_category_4553">CraftTweaker</string>
<string name="curse_category_4554">合成表</string>
<string name="curse_category_4549">指引书</string>
<string name="curse_category_4547">配置</string>
<string name="curse_category_4550">任务</string>
<string name="curse_category_4555">世界生成</string>
<string name="curse_category_4552">脚本</string>
<string name="curse_sort_author">作者</string>
<string name="curse_sort_date_created">创建日期</string>
<string name="curse_sort_last_updated">最近更新</string>
<string name="curse_sort_name">名称</string>
<string name="curse_sort_popularity">热度</string>
<string name="curse_sort_total_downloads">下载量</string>
<string name="download_code_404">远程服务器不包含需要下载的文件: %s</string>
<string name="download_failed">下载失败: %1$s错误码%2$d</string>
<string name="download_failed_empty">没有可供选择的版本</string>
@ -190,6 +302,7 @@
<string name="install_installer_install_offline">从本地文件安装/升级</string>
<string name="install_installer_install_offline_extension">Forge/OptiFine 安装器</string>
<string name="install_installer_not_installed">不安装</string>
<string name="install_modpack">安装整合包</string>
<string name="install_new_game">安装新游戏版本</string>
<string name="install_new_game_already_exists">当前版本已存在,请换一个名称。</string>
<string name="install_new_game_malformed">无效的名称</string>
@ -275,6 +388,117 @@
<string name="message_unknown">未知</string>
<string name="message_copy">复制成功!</string>
<string name="modpack">整合包</string>
<string name="modpack_choose">选择要安装的游戏整合包文件</string>
<string name="modpack_choose_local">导入本地整合包文件</string>
<string name="modpack_choose_remote">从互联网下载整合包</string>
<string name="modpack_choose_remote_tooltip">要下载的整合包的链接</string>
<string name="modpack_completion">下载整合包相关文件</string>
<string name="modpack_desc">描述你要制作的整合包,比如整合包注意事项和更新记录,支持 HTML图片请用网络图</string>
<string name="modpack_description">整合包描述</string>
<string name="modpack_download">下载整合包</string>
<string name="modpack_enter_name">给游戏起个你喜欢的名字</string>
<string name="modpack_export">导出整合包</string>
<string name="modpack_export_as">请选择整合包类型 (若无法决定,请选择我的世界中文论坛整合包标准)</string>
<string name="modpack_file_api">整合包下载链接前缀</string>
<string name="modpack_files_blueprints">BuildCraft 蓝图</string>
<string name="modpack_files_config">Mod 配置文件</string>
<string name="modpack_files_dumps">NEI 调试输出</string>
<string name="modpack_files_fclversion_cfg">启动器配置文件</string>
<string name="modpack_files_liteconfig">Mod 配置文件</string>
<string name="modpack_files_mods">Mod</string>
<string name="modpack_files_mods_voxelmods">VoxelMods 配置,如小地图</string>
<string name="modpack_files_options_txt">游戏设定</string>
<string name="modpack_files_optionsshaders_txt">光影设定</string>
<string name="modpack_files_resourcepacks">资源包(材质包)</string>
<string name="modpack_files_saves">游戏存档</string>
<string name="modpack_files_scripts">MineTweaker 配置</string>
<string name="modpack_files_servers_dat">多人游戏服务器列表</string>
<string name="modpack_install">安装 %s 整合包</string>
<string name="modpack_installing">正在安装整合包</string>
<string name="modpack_introduction">支持 Curse、Modrinth、MultiMC、MCBBS 整合包。</string>
<string name="modpack_invalid">无效的整合包升级文件,可能是下载时出现问题。</string>
<string name="modpack_mismatched_type">整合包类型不匹配,当前游戏是 %s 整合包,但是提供的整合包更新文件是 %s 整合包。</string>
<string name="modpack_name">整合包名称</string>
<string name="modpack_not_a_valid_name">不是一个有效的整合包名称</string>
<string name="modpack_origin">来源</string>
<string name="modpack_origin_url">官方网站</string>
<string name="modpack_origin_mcbbs">MCBBS</string>
<string name="modpack_origin_mcbbs_prompt">贴子 id</string>
<string name="modpack_scan">解析整合包</string>
<string name="modpack_task_install">导入整合包</string>
<string name="modpack_task_install_error">无法识别该整合包,目前仅支持导入 Curse、Modrinth、MultiMC、MCBBS 整合包。</string>
<string name="modpack_task_install_will">将会安装整合包:</string>
<string name="modpack_type_curse">Curse</string>
<string name="modpack_type_curse_tolerable_error">但未能完成该整合包所需的依赖下载,您可以在启动该游戏版本时继续该整合包文件的下载。由于网络问题,您可能需要重试多次。</string>
<string name="modpack_type_curse_error">未能完成该整合包所需的依赖下载,请多次重试或设置代理。</string>
<string name="modpack_type_curse_not_found">部分必需文件已经在网络中被删除并且再也无法下载,请尝试该整合包的最新版本或者安装其他整合包。</string>
<string name="modpack_type_manual_warning">该整合包由发布者手动打包,其中可能已经包含启动器,建议尝试解压后使用其自带的启动器运行游戏。\nFCL 可以尝试导入该整合包,但不保证可用性,是否继续?</string>
<string name="modpack_type_mcbbs">我的世界中文论坛整合包标准</string>
<string name="modpack_type_mcbbs_export">可以被 FCLHMCL 和 MultiMC 导入</string>
<string name="modpack_type_modrinth">Modrinth</string>
<string name="modpack_type_multimc">MultiMC</string>
<string name="modpack_type_multimc_export">可以被 FCLHMCL 和 MultiMC 导入</string>
<string name="modpack_type_server">服务器自动更新整合包</string>
<string name="modpack_type_server_export">允许服务器管理员远程更新游戏客户端</string>
<string name="modpack_type_server_malformed">服务器整合包配置格式错误,请联系服务器管理员解决此问题</string>
<string name="modpack_unsupported">Fold Craft Launcher 不支持该整合包格式</string>
<string name="modpack_update">正在升级整合包</string>
<string name="modpack_wizard">导出整合包向导</string>
<string name="modpack_wizard_step_1">基本设置</string>
<string name="modpack_wizard_step_1_title">设置整合包的主要信息</string>
<string name="modpack_wizard_step_2">文件选择</string>
<string name="modpack_wizard_step_2_title">选中你想加到整合包中的文件或文件夹</string>
<string name="modpack_wizard_step_3">整合包类型</string>
<string name="modpack_wizard_step_3_title">选择整合包导出类型</string>
<string name="modpack_wizard_step_initialization_exported_version">要导出的游戏版本</string>
<string name="modpack_wizard_step_initialization_force_update">强制升级整合包至最新版本(需要自建服务器)</string>
<string name="modpack_wizard_step_initialization_include_launcher">包含启动器</string>
<string name="modpack_wizard_step_initialization_save">选择要导出到的游戏整合包位置</string>
<string name="modpack_wizard_step_initialization_warning">在制作整合包前,请您确认您选择的版本可以正常启动,\n并保证您的 Minecraft 是正式版而非快照版,\n而且不应当将不允许非官方途径传播的 Mod、材质包等纳入整合包。\n整合包会保存您目前的下载源设置</string>
<string name="modrinth_category_adventure">冒险</string>
<string name="modrinth_category_bukkit">Bukkit</string>
<string name="modrinth_category_bungeecord">BungeeCord</string>
<string name="modrinth_category_challenging">高难度</string>
<string name="modrinth_category_combat">战斗</string>
<string name="modrinth_category_cursed">Cursed</string>
<string name="modrinth_category_decoration">装饰</string>
<string name="modrinth_category_economy">经济</string>
<string name="modrinth_category_equipment">装备</string>
<string name="modrinth_category_fabric">Fabric</string>
<string name="modrinth_category_food">食物</string>
<string name="modrinth_category_forge">Forge</string>
<string name="modrinth_category_game_mechanics">游戏机制</string>
<string name="modrinth_category_kitchen_sink">大杂烩</string>
<string name="modrinth_category_library">支持库</string>
<string name="modrinth_category_lightweight">轻量</string>
<string name="modrinth_category_magic">魔法</string>
<string name="modrinth_category_management">管理</string>
<string name="modrinth_category_minigame">小游戏</string>
<string name="modrinth_category_misc">其他</string>
<string name="modrinth_category_mobs">生物</string>
<string name="modrinth_category_modloader">Modloader</string>
<string name="modrinth_category_multiplayer">多人</string>
<string name="modrinth_category_optimization">优化</string>
<string name="modrinth_category_paper">Paper</string>
<string name="modrinth_category_purpur">Purpur</string>
<string name="modrinth_category_quests">任务</string>
<string name="modrinth_category_quilt">Quilt</string>
<string name="modrinth_category_rift">Rift</string>
<string name="modrinth_category_social">社交</string>
<string name="modrinth_category_spigot">Spigot</string>
<string name="modrinth_category_sponge">Sponge</string>
<string name="modrinth_category_storage">存储</string>
<string name="modrinth_category_technology">科技</string>
<string name="modrinth_category_transportation">运输</string>
<string name="modrinth_category_utility">实用</string>
<string name="modrinth_category_velocity">Velocity</string>
<string name="modrinth_category_waterfall">Waterfall</string>
<string name="modrinth_category_worldgen">世界生成</string>
<string name="modrinth_category_datapack">数据包</string>
<string name="modrinth_category_folia">Folia</string>
<string name="mods">模组</string>
<string name="mods_add">添加模组</string>
<string name="mods_add_failed">无法安装模组 %s。</string>
@ -305,9 +529,6 @@
<string name="mods_restore">回滚</string>
<string name="mods_url">官方页面</string>
<string name="modpack">整合包</string>
<string name="modpack_export">导出整合包</string>
<string name="profile_shared">公有目录</string>
<string name="profile_private">私有目录</string>
<string name="profile_name">名称</string>
@ -323,6 +544,11 @@
<string name="resourcepack">资源包</string>
<string name="search">搜索</string>
<string name="search_hint_chinese">支持中英文搜索</string>
<string name="search_hint_english">仅支持英文搜索</string>
<string name="search_sort">排序</string>
<string name="settings_advanced_dont_check_game_completeness">不检查游戏完整性</string>
<string name="settings_advanced_dont_check_jvm_validity">不检查 JVM 兼容性</string>
<string name="settings_advanced_game_dir_default">默认 (.minecraft/)</string>
@ -354,6 +580,7 @@
<string name="settings_icon">版本图标</string>
<string name="settings_launcher">启动器设置</string>
<string name="settings_launcher_download_source">下载源</string>
<string name="settings_memory">游戏内存</string>
<string name="settings_memory_allocate_auto">最低分配 %1$.1f GB / 实际分配 %2$.1f GB</string>
@ -441,6 +668,53 @@
<string name="view_info_reference_height">屏幕高</string>
<string name="world">世界</string>
<string name="world_manage">世界 / 数据包</string>
<string name="world_add">添加世界</string>
<string name="world_datapack">管理数据包</string>
<string name="world_datapack_1_13">仅 Minecraft 1.13 及之后的版本支持数据包</string>
<string name="world_description">%s。 上一次游戏时间: %s。 游戏版本: %s。</string>
<string name="world_download">存档下载</string>
<string name="world_export">导出此世界</string>
<string name="world_export_title">选择该世界的存储位置</string>
<string name="world_export_location">保存到</string>
<string name="world_export_wizard">导出世界 %s</string>
<string name="world_extension">世界压缩包</string>
<string name="world_game_version">游戏版本</string>
<string name="world_import_already_exists">此世界已经存在</string>
<string name="world_import_choose">选择要导入的存档压缩包</string>
<string name="world_import_failed">无法导入此世界:%s</string>
<string name="world_import_invalid">无法识别该存档压缩包</string>
<string name="world_info_title">世界 %s - 世界信息</string>
<string name="world_info_basic">基本信息</string>
<string name="world_info_allow_cheats">允许作弊</string>
<string name="world_info_dimension_the_nether">下界</string>
<string name="world_info_dimension_the_end">末地</string>
<string name="world_info_difficulty">难度</string>
<string name="world_info_difficulty_peaceful">和平</string>
<string name="world_info_difficulty_easy">简单</string>
<string name="world_info_difficulty_normal">普通</string>
<string name="world_info_difficulty_hard">困难</string>
<string name="world_info_game_version">游戏版本</string>
<string name="world_info_last_played">上一次游戏时间</string>
<string name="world_info_generate_features">生成建筑</string>
<string name="world_info_player">玩家信息</string>
<string name="world_info_player_food_level">饥饿值</string>
<string name="world_info_player_game_type">游戏模式</string>
<string name="world_info_player_game_type_adventure">冒险</string>
<string name="world_info_player_game_type_creative">创造</string>
<string name="world_info_player_game_type_spectator">旁观</string>
<string name="world_info_player_game_type_survival">生存</string>
<string name="world_info_player_health">生命值</string>
<string name="world_info_player_last_death_location">上次死亡位置</string>
<string name="world_info_player_location">位置</string>
<string name="world_info_player_spawn">床/重生锚位置</string>
<string name="world_info_player_xp_level">经验等级</string>
<string name="world_info_random_seed">种子</string>
<string name="world_info_time">游戏内时间</string>
<string name="world_info_time_format">%s 天</string>
<string name="world_manage">世界/数据包</string>
<string name="world_name">世界名称</string>
<string name="world_name_enter">输入世界名称</string>
<string name="world_reveal">打开文件夹</string>
<string name="world_show_all">显示全部</string>
<string name="world_time">yyyy 年 MM 月 dd 日 HH:mm:ss</string>
</resources>

View File

@ -118,6 +118,118 @@
<string name="control_select">Select Controller</string>
<string name="control_share">Share Controller</string>
<string name="curse_category_0">All</string>
<string name="curse_category_4474">Sci-Fi</string>
<string name="curse_category_4481">Small / Light</string>
<string name="curse_category_4483">Combat</string>
<string name="curse_category_4477">Mini Game</string>
<string name="curse_category_4478">Quests</string>
<string name="curse_category_4484">Multiplayer</string>
<string name="curse_category_4476">Exploration</string>
<string name="curse_category_6145">Skyblock</string>
<string name="curse_category_4475">Adventure and RPG</string>
<string name="curse_category_4487">FTB</string>
<string name="curse_category_4480">Map Based</string>
<string name="curse_category_4479">Hardcore</string>
<string name="curse_category_4482">Extra Large</string>
<string name="curse_category_4472">Tech</string>
<string name="curse_category_4473">Magic</string>
<string name="curse_category_5128">Vanilla+</string>
<string name="curse_category_5299">Education</string>
<string name="curse_category_5232">Galacticraft</string>
<string name="curse_category_5129">Vanilla+</string>
<string name="curse_category_5189">Utility &#38; QOL</string>
<string name="curse_category_5190">QoL</string>
<string name="curse_category_5191">Utility &#38; QoL</string>
<string name="curse_category_5192">FancyMenu</string>
<string name="curse_category_423">Map and Information</string>
<string name="curse_category_426">Addons</string>
<string name="curse_category_434">Armor, Tools, and Weapons</string>
<string name="curse_category_409">Structures</string>
<string name="curse_category_4485">Blood Magic</string>
<string name="curse_category_420">Storage</string>
<string name="curse_category_429">Industrial Craft</string>
<string name="curse_category_419">Magic</string>
<string name="curse_category_412">Technology</string>
<string name="curse_category_4557">Redstone</string>
<string name="curse_category_428">Tinker\'s Construct</string>
<string name="curse_category_414">Player Transport</string>
<string name="curse_category_4486">Lucky Blocks</string>
<string name="curse_category_432">Buildcraft</string>
<string name="curse_category_418">Genetics</string>
<string name="curse_category_4671">Twitch Integration</string>
<string name="curse_category_5314">KubeJS</string>
<string name="curse_category_408">Ores and Resources</string>
<string name="curse_category_4773">CraftTweaker</string>
<string name="curse_category_430">Thaumcraft</string>
<string name="curse_category_422">Adventure and RPG</string>
<string name="curse_category_413">Processing</string>
<string name="curse_category_417">Energy</string>
<string name="curse_category_415">Energy, Fluid and Item Transport</string>
<string name="curse_category_433">Forestry</string>
<string name="curse_category_425">Miscellaneous</string>
<string name="curse_category_4545">Applied Energistics 2</string>
<string name="curse_category_416">Farming</string>
<string name="curse_category_421">API and Library</string>
<string name="curse_category_4780">Fabric</string>
<string name="curse_category_424">Cosmetic</string>
<string name="curse_category_406">World gen</string>
<string name="curse_category_435">Server Utility</string>
<string name="curse_category_411">Mobs</string>
<string name="curse_category_407">Biomes</string>
<string name="curse_category_427">Thermal Expansion</string>
<string name="curse_category_410">Dimensions</string>
<string name="curse_category_436">Food</string>
<string name="curse_category_4558">Redstone</string>
<string name="curse_category_4843">Automation</string>
<string name="curse_category_4906">MCreator</string>
<string name="curse_category_5244">Font Packs</string>
<string name="curse_category_5193">Data Packs</string>
<string name="curse_category_399">Steampunk</string>
<string name="curse_category_396">128x</string>
<string name="curse_category_398">512x and Higher</string>
<string name="curse_category_397">256x</string>
<string name="curse_category_405">Miscellaneous</string>
<string name="curse_category_395">64x</string>
<string name="curse_category_400">Photo Realistic</string>
<string name="curse_category_393">16x</string>
<string name="curse_category_403">Traditional</string>
<string name="curse_category_394">32x</string>
<string name="curse_category_404">Animated</string>
<string name="curse_category_4465">Mod Support</string>
<string name="curse_category_402">Medieval</string>
<string name="curse_category_401">Modern</string>
<string name="curse_category_4464">Modded World</string>
<string name="curse_category_250">Game Map</string>
<string name="curse_category_249">Creation</string>
<string name="curse_category_251">Parkour</string>
<string name="curse_category_253">Survival</string>
<string name="curse_category_248">Adventure</string>
<string name="curse_category_252">Puzzle</string>
<string name="curse_category_4551">Hardcore Questing Mode</string>
<string name="curse_category_4548">Lucky Blocks</string>
<string name="curse_category_4556">Progression</string>
<string name="curse_category_4752">Building Gadgets</string>
<string name="curse_category_4553">CraftTweaker</string>
<string name="curse_category_4554">Recipes</string>
<string name="curse_category_4549">Guidebook</string>
<string name="curse_category_4547">Configuration</string>
<string name="curse_category_4550">Quests</string>
<string name="curse_category_4555">World Gen</string>
<string name="curse_category_4552">Scripts</string>
<string name="curse_sort_author">Author</string>
<string name="curse_sort_date_created">Date Created</string>
<string name="curse_sort_last_updated">Last Updated</string>
<string name="curse_sort_name">Name</string>
<string name="curse_sort_popularity">Popularity</string>
<string name="curse_sort_total_downloads">Total Downloads</string>
<string name="download_code_404">File not found on the remote server: %s</string>
<string name="download_failed">Failed to download %1$s, response code: %2$d</string>
<string name="download_failed_empty">No versions are available</string>
@ -209,6 +321,7 @@
<string name="install_installer_optifine" translatable="false">OptiFine</string>
<string name="install_installer_quilt" translatable="false">Quilt</string>
<string name="install_installer_quilt_api" translatable="false">QSL/QFAPI</string>
<string name="install_modpack">Install a Modpack</string>
<string name="install_new_game">Add a New Instance</string>
<string name="install_new_game_already_exists">This instance already exists. Please use another name.</string>
<string name="install_new_game_malformed">Invalid Name</string>
@ -294,6 +407,117 @@
<string name="message_unknown">Unknown</string>
<string name="message_copy">Copy successfully!</string>
<string name="modpack">Modpack</string>
<string name="modpack_choose">Select a modpack</string>
<string name="modpack_choose_local">Import from local file</string>
<string name="modpack_choose_remote">Download from the Internet</string>
<string name="modpack_choose_remote_tooltip">Please enter your modpack URL</string>
<string name="modpack_completion">Downloading dependencies</string>
<string name="modpack_desc">Describe your modpack, including an introduction and probably some changelog. Markdown and images from URL are currently supported.</string>
<string name="modpack_description">Description</string>
<string name="modpack_download">Download Modpack</string>
<string name="modpack_enter_name">Enter a name for this modpack.</string>
<string name="modpack_export">Export Modpack</string>
<string name="modpack_export_as">Export Modpack As…</string>
<string name="modpack_file_api">Modpack URL Prefix</string>
<string name="modpack_files_blueprints">BuildCraft Blueprints</string>
<string name="modpack_files_config">Mod Configs</string>
<string name="modpack_files_dumps">NEI Debug Output File</string>
<string name="modpack_files_fclversion_cfg">Launcher Configuration File</string>
<string name="modpack_files_liteconfig">Mod Configuration File</string>
<string name="modpack_files_mods">Mods</string>
<string name="modpack_files_mods_voxelmods">VoxelMods options</string>
<string name="modpack_files_options_txt">Minecraft Settings File</string>
<string name="modpack_files_optionsshaders_txt">Shaders Settings File</string>
<string name="modpack_files_resourcepacks">Resource/Texture Packs</string>
<string name="modpack_files_saves">Game Saves</string>
<string name="modpack_files_scripts">MineTweaker Configuration File</string>
<string name="modpack_files_servers_dat">Server List File</string>
<string name="modpack_install">Install Modpack %s</string>
<string name="modpack_installing">Installing Modpack</string>
<string name="modpack_introduction">CurseForge, Modrinth, MultiMC, and MCBBS modpacks are currently supported.</string>
<string name="modpack_invalid">Invalid modpack, you can try to redownload it.</string>
<string name="modpack_mismatched_type">Modpack type mismatched, the current instance is a %s type, but the provided one is %s type.</string>
<string name="modpack_name">Modpack Name</string>
<string name="modpack_not_a_valid_name">Invalid Modpack Name</string>
<string name="modpack_origin">Source</string>
<string name="modpack_origin_url">Official Website</string>
<string name="modpack_origin_mcbbs">MCBBS</string>
<string name="modpack_origin_mcbbs_prompt">Post ID</string>
<string name="modpack_scan">Parsing Modpack Index</string>
<string name="modpack_task_install">Install Modpack</string>
<string name="modpack_task_install_error">Unable to identify this modpack. We currently only support Curse, Modrinth, MultiMC, and MCBBS modpacks.</string>
<string name="modpack_task_install_will">You are going to install modpack:</string>
<string name="modpack_type_curse">Curse</string>
<string name="modpack_type_curse_tolerable_error">Unable to download dependencies, you can try to continue downloading by launching this game instance.</string>
<string name="modpack_type_curse_error">Unable to download dependencies from CurseForge, please try again or use a proxy connection.</string>
<string name="modpack_type_curse_not_found">Some dependencies are no longer available, please try to install a newer version of the modpack.</string>
<string name="modpack_type_manual_warning">The modpack is manually packaged by the publisher, which may already contain a launcher. It is recommended to try to decompress and run the game with its own launcher. FCL can still import it, with no guarantee of its usability, still continue?</string>
<string name="modpack_type_mcbbs">MCBBS Type</string>
<string name="modpack_type_mcbbs_export">Can be imported by FCL, HMCL and MultiMC</string>
<string name="modpack_type_modrinth">Modrinth</string>
<string name="modpack_type_multimc">MultiMC</string>
<string name="modpack_type_multimc_export">Can be imported by FCL, HMCL and MultiMC</string>
<string name="modpack_type_server">Auto-Update Modpack from Server</string>
<string name="modpack_type_server_export">Allows server owner to update the game instance remotely</string>
<string name="modpack_type_server_malformed">Invalid modpack manifest, please refer to the server modpack maker to fix this issue.</string>
<string name="modpack_unsupported">Unsupported modpack format</string>
<string name="modpack_update">Updating modpack</string>
<string name="modpack_wizard">Modpack Export Wizard</string>
<string name="modpack_wizard_step_1">Basic Settings</string>
<string name="modpack_wizard_step_1_title">Some basic settings for the modpack.</string>
<string name="modpack_wizard_step_2">Select Files</string>
<string name="modpack_wizard_step_2_title">Select files you wanted to add to the modpack.</string>
<string name="modpack_wizard_step_3">Modpack Type</string>
<string name="modpack_wizard_step_3_title">Choose the modpack type you wanted to export as.</string>
<string name="modpack_wizard_step_initialization_exported_version">Game version to export</string>
<string name="modpack_wizard_step_initialization_force_update">Force updating the modpack to the latest version (you\'ll need a file-hosting service)</string>
<string name="modpack_wizard_step_initialization_include_launcher">Include the launcher</string>
<string name="modpack_wizard_step_initialization_save">Export to…</string>
<string name="modpack_wizard_step_initialization_warning">Before creating a modpack, please make sure the game launches, and it is a release version instead of a snapshot version. The launcher will save your download settings.\n\nKeep in mind that you are not allowed to add mods and resource packs that are explicitly said not to be distributed or put in a modpack.</string>
<string name="modrinth_category_adventure">Adventure</string>
<string name="modrinth_category_bukkit">Bukkit</string>
<string name="modrinth_category_bungeecord">BungeeCord</string>
<string name="modrinth_category_challenging">Challenging</string>
<string name="modrinth_category_combat">Combat</string>
<string name="modrinth_category_cursed">Cursed</string>
<string name="modrinth_category_decoration">Decoration</string>
<string name="modrinth_category_economy">Economy</string>
<string name="modrinth_category_equipment">Equipment</string>
<string name="modrinth_category_fabric">Fabric</string>
<string name="modrinth_category_food">Food</string>
<string name="modrinth_category_forge">Forge</string>
<string name="modrinth_category_game_mechanics">Game Mechanics</string>
<string name="modrinth_category_kitchen_sink">Kitchen-Sink</string>
<string name="modrinth_category_library">Library</string>
<string name="modrinth_category_lightweight">Lightweight</string>
<string name="modrinth_category_magic">Magic</string>
<string name="modrinth_category_management">Management</string>
<string name="modrinth_category_minigame">Minigame</string>
<string name="modrinth_category_misc">Misc</string>
<string name="modrinth_category_mobs">Mobs</string>
<string name="modrinth_category_modloader">Modloader</string>
<string name="modrinth_category_multiplayer">Multiplayer</string>
<string name="modrinth_category_optimization">Optimization</string>
<string name="modrinth_category_paper">Paper</string>
<string name="modrinth_category_purpur">Purpur</string>
<string name="modrinth_category_quests">Quests</string>
<string name="modrinth_category_quilt">Quilt</string>
<string name="modrinth_category_rift">Rift</string>
<string name="modrinth_category_social">Social</string>
<string name="modrinth_category_spigot">Spigot</string>
<string name="modrinth_category_sponge">Sponge</string>
<string name="modrinth_category_storage">Storage</string>
<string name="modrinth_category_technology">Technology</string>
<string name="modrinth_category_transportation">Transportation</string>
<string name="modrinth_category_utility">Utility</string>
<string name="modrinth_category_velocity">Velocity</string>
<string name="modrinth_category_waterfall">Waterfall</string>
<string name="modrinth_category_worldgen">Worldgen</string>
<string name="modrinth_category_datapack">Datapack</string>
<string name="modrinth_category_folia">Folia</string>
<string name="mods">Mods</string>
<string name="mods_add">Add Mods</string>
<string name="mods_add_failed">Failed to install mod %s.</string>
@ -323,9 +547,6 @@
<string name="mods_not_modded">You must install a mod loader (Fabric, Forge or LiteLoader) first to manage your mods!</string>
<string name="mods_restore">Rollback</string>
<string name="mods_url">Official Page</string>
<string name="modpack">Modpack</string>
<string name="modpack_export">Export Modpack</string>
<string name="profile_shared">Shared Directory</string>
<string name="profile_private">Private Directory</string>
@ -342,6 +563,11 @@
<string name="resourcepack">Resource Packs</string>
<string name="search">Search</string>
<string name="search_hint_chinese">Search queries support both Chinese and English</string>
<string name="search_hint_english">Only English is supported</string>
<string name="search_sort">Sort By</string>
<string name="settings_advanced_dont_check_game_completeness">Do not check game integrity</string>
<string name="settings_advanced_dont_check_jvm_validity">Do not check JVM compatibility</string>
<string name="settings_advanced_game_dir_default">Default (.minecraft/)</string>
@ -377,6 +603,7 @@
<string name="settings_icon">Icon</string>
<string name="settings_launcher">Launcher Settings</string>
<string name="settings_launcher_download_source">Download Source</string>
<string name="settings_memory">Memory</string>
<string name="settings_memory_allocate_auto">%1$.1f GB Minimum / %2$.1f GB Allocated</string>
@ -464,6 +691,53 @@
<string name="view_info_reference_height">Screen Height</string>
<string name="world">Worlds</string>
<string name="world_add">Add a World (.zip)</string>
<string name="world_datapack">Manage Datapacks</string>
<string name="world_datapack_1_13">Only Minecraft 1.13 or newer supports datapacks.</string>
<string name="world_description">%s. Last played on %s. Game Version: %s.</string>
<string name="world_download">Download a World</string>
<string name="world_export">Export World</string>
<string name="world_export_title">Select a directory for this exported world</string>
<string name="world_export_location">Export to</string>
<string name="world_export_wizard">Export World %s</string>
<string name="world_extension">World Archive</string>
<string name="world_game_version">Game Version</string>
<string name="world_import_already_exists">This world already exists.</string>
<string name="world_import_choose">Select the save archive you want to import</string>
<string name="world_import_failed">Unable to import this world: %s</string>
<string name="world_import_invalid">Unable to parse the save.</string>
<string name="world_info_title">World %s - Information</string>
<string name="world_info_basic">Basic Information</string>
<string name="world_info_allow_cheats">Allow Cheats</string>
<string name="world_info_dimension_the_nether">The Nether</string>
<string name="world_info_dimension_the_end">The End</string>
<string name="world_info_difficulty">Difficulty</string>
<string name="world_info_difficulty_peaceful">Peaceful</string>
<string name="world_info_difficulty_easy">Easy</string>
<string name="world_info_difficulty_normal">Normal</string>
<string name="world_info_difficulty_hard">Hard</string>
<string name="world_info_game_version">Game Version</string>
<string name="world_info_last_played">Last Played</string>
<string name="world_info_generate_features">Generate structures</string>
<string name="world_info_player">Player Information</string>
<string name="world_info_player_food_level">Hunger Level</string>
<string name="world_info_player_game_type">Game Mode</string>
<string name="world_info_player_game_type_adventure">Adventure</string>
<string name="world_info_player_game_type_creative">Creative</string>
<string name="world_info_player_game_type_spectator">Spectator</string>
<string name="world_info_player_game_type_survival">Survival</string>
<string name="world_info_player_health">Health</string>
<string name="world_info_player_last_death_location">Last Death Location</string>
<string name="world_info_player_location">Location</string>
<string name="world_info_player_spawn">Spawn Location</string>
<string name="world_info_player_xp_level">Experience Level</string>
<string name="world_info_random_seed">Seed</string>
<string name="world_info_time">Game Time</string>
<string name="world_info_time_format">%s days</string>
<string name="world_manage">Worlds / Datapacks</string>
<string name="world_name">World Name</string>
<string name="world_name_enter">Enter the world name</string>
<string name="world_reveal">Reveal in Explorer</string>
<string name="world_show_all">Show All</string>
<string name="world_time">EEE, MMM d, yyyy HH:mm:ss</string>
</resources>

View File

@ -72,6 +72,7 @@ public interface RemoteModRepository {
}
String[] DEFAULT_GAME_VERSIONS = new String[]{
"",
"1.20.1", "1.20",
"1.19.4", "1.19.3", "1.19.2", "1.19.1", "1.19",
"1.18.2", "1.18.1", "1.18",

View File

@ -21,10 +21,10 @@ public class LocaleUtils {
public static boolean isChinese(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences("launcher", Context.MODE_PRIVATE);
int lang = sharedPreferences.getInt("lang", 0);
return lang == 2 || (lang == 0 && getSystemLocale() == Locale.CHINA);
return lang == 2 || (lang == 0 && getSystemLocale().toString().equals(Locale.CHINA.toString()));
}
public static Context setLanguage(Context context){
public static Context setLanguage(Context context) {
SharedPreferences sharedPreferences = context.getSharedPreferences("launcher", Context.MODE_PRIVATE);
return updateResources(context, sharedPreferences.getInt("lang", 0));
}