Skip to content

Commit 2b5178a

Browse files
authored
Merge pull request #37 from CopperLauncher/add-shit
Add shit
2 parents 6c2d408 + 5aba580 commit 2b5178a

20 files changed

Lines changed: 1352 additions & 261 deletions

File tree

.github/workflows/android.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ jobs:
106106
rm -rf app_pojavlauncher/src/main/assets/components/jre
107107
rm -rf app_pojavlauncher/src/main/assets/components/jre-new
108108
rm -rf app_pojavlauncher/src/main/assets/components/jre-21
109+
rm -rf app_pojavlauncher/src/main/assets/components/jre-25
109110
./gradlew assembleDebug
110111
mv app_pojavlauncher/build/outputs/apk/debug/app_pojavlauncher-debug.apk out/app-debug-noruntime.apk
111112

app_pojavlauncher/build.gradle

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ static def getDate() { return new Date().format('yyyyMMdd') }
77
def getVersionName = {
88
// Get the last version tag, as well as the short head of the last commit
99
ByteArrayOutputStream TAG = new ByteArrayOutputStream()
10-
ByteArrayOutputStream BRANCH = new ByteArrayOutputStream()
10+
String semVer = "1.0.0"
1111
// Used by the fallback for github actions
1212
ByteArrayOutputStream TAG_PART_COMMIT = new ByteArrayOutputStream()
1313
String TAG_STRING
@@ -48,17 +48,7 @@ def getVersionName = {
4848

4949
}
5050

51-
exec {
52-
try {
53-
commandLine 'git', 'branch', '--show-current'
54-
ignoreExitValue true
55-
standardOutput = BRANCH
56-
} catch (Exception e) {
57-
e.printStackTrace();
58-
}
59-
}
60-
61-
return TAG_STRING.trim().replace("-g", "-") + "-" + BRANCH.toString().trim()
51+
return TAG_STRING.trim().replace("-g", "-") + "-" + semVer
6252
}
6353

6454
def getCFApiKey = {
-10.3 MB
Binary file not shown.
Binary file not shown.

app_pojavlauncher/src/main/assets/components/lwjgl3/version

Lines changed: 0 additions & 1 deletion
This file was deleted.

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ private static File getGameDir() {
268268

269269
/**
270270
* Searches for mod in mods directory of current selected profile
271+
* Not case-sensitive
271272
* @param filenames Filename(s) of the .jar mod(s)
272273
* @return Whether or not the .jar is found
273274
*/
@@ -278,7 +279,7 @@ public static boolean hasMods(String... filenames) {
278279
if (modFiles == null) return false;
279280
for (File file : modFiles) {
280281
for (String filename : filenames)
281-
if (file.getName().contains(filename)) return true;
282+
if (file.getName().toLowerCase().contains(filename.toLowerCase())) return true;
282283
}
283284
return false;
284285
}
@@ -320,10 +321,12 @@ private static boolean affectedByRenderDistanceIssue() {
320321
return info.isAdreno() && info.glesMajorVersion >= 3;
321322
}
322323

324+
private static String[] sodiumMods = {"sodium", "embeddium", "rubidium", "xenon"};
325+
323326
private static boolean affectedByLTWRenderDistanceIssue() {
324327
if(!"opengles3_ltw".equals(Tools.LOCAL_RENDERER)) return false;
325328
if(!affectedByRenderDistanceIssue()) return false;
326-
if(hasMods("sodium", "embeddium", "rubidium")) return false;
329+
if(hasMods(sodiumMods)) return false;
327330

328331
int renderDistance;
329332
try {
@@ -432,7 +435,37 @@ public static void launchMinecraft(final AppCompatActivity activity, MinecraftAc
432435
javaArgList.add("-Dimgui.library.name=imgui-java");
433436
// We use an abomination to support all DH versions with a single library.
434437
javaArgList.add("-DZstdNativePath="+Tools.NATIVE_LIB_DIR+"/libzstd-jni-1.5.7-6-dhcompat.so");
438+
// We only ever reach this point when user has already used the force run switch
439+
boolean hasSodiumMod = false;
440+
for (String modName : sodiumMods) {
441+
if (hasMods(sodiumMods)) {
442+
hasSodiumMod = true;
443+
File mixinPropertiesConfigFile = new File(getGameDir(), "config/" + modName + "-mixins.properties");
444+
// Write mixin configs to somewhat help stability. We don't want more people complaining.
445+
String[] propertiesToAdd = {
446+
"mixin.features.buffer_builder.intrinsics=false",
447+
"mixin.features.chunk_rendering=false"
448+
};
449+
List<String> mixinPropertiesConfigStrings = null;
450+
try {
451+
mixinPropertiesConfigStrings = org.apache.commons.io.FileUtils.readLines(mixinPropertiesConfigFile, "UTF-8");
452+
} catch (IOException ignored) {}
453+
if (mixinPropertiesConfigStrings == null) {
454+
mixinPropertiesConfigStrings = new ArrayList<>();
455+
}
456+
for (String newLine : propertiesToAdd) {
457+
if (!mixinPropertiesConfigStrings.contains(newLine)) {
458+
mixinPropertiesConfigStrings.add(newLine);
459+
}
460+
}
461+
try {
462+
org.apache.commons.io.FileUtils.writeLines(mixinPropertiesConfigFile, mixinPropertiesConfigStrings);
463+
} catch (IOException ignored) {} // If we can't write it, we tried our best.
435464

465+
}
466+
}
467+
// We use a janky lwjgl setup. We don't want more people complaining it crashes.
468+
if (hasSodiumMod) javaArgList.add("-Dsodium.checks.issue2561=false");
436469
javaArgList.add(versionInfo.mainClass);
437470
javaArgList.addAll(Arrays.asList(launchArgs));
438471
// ctx.appendlnToLog("full args: "+javaArgList.toString());

app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/fragments/MainMenuFragment.java

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
package net.kdt.pojavlaunch.fragments;
22

3-
import static net.kdt.pojavlaunch.Tools.dialogOnUiThread;
43
import static net.kdt.pojavlaunch.Tools.hasNoOnlineProfileDialog;
54
import static net.kdt.pojavlaunch.Tools.hasOnlineProfile;
65
import static net.kdt.pojavlaunch.Tools.openPath;
7-
import static net.kdt.pojavlaunch.Tools.runOnUiThread;
86
import static net.kdt.pojavlaunch.Tools.shareLog;
97

10-
import android.app.Dialog;
118
import android.content.Intent;
129
import android.os.Bundle;
1310
import android.view.View;
@@ -17,7 +14,6 @@
1714

1815
import androidx.annotation.NonNull;
1916
import androidx.annotation.Nullable;
20-
import androidx.appcompat.app.AlertDialog;
2117
import androidx.fragment.app.Fragment;
2218

2319
import com.kdt.mcgui.mcVersionSpinner;
@@ -39,63 +35,93 @@ public class MainMenuFragment extends Fragment {
3935

4036
private mcVersionSpinner mVersionSpinner;
4137

42-
public MainMenuFragment(){
38+
public MainMenuFragment() {
4339
super(R.layout.fragment_launcher);
4440
}
4541

4642
@Override
4743
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
48-
Button mNewsButton = view.findViewById(R.id.news_button);
49-
Button mDiscordButton = view.findViewById(R.id.discord_button);
50-
Button mCustomControlButton = view.findViewById(R.id.custom_control_button);
51-
Button mInstallJarButton = view.findViewById(R.id.install_jar_button);
52-
Button mShareLogsButton = view.findViewById(R.id.share_logs_button);
53-
Button mOpenDirectoryButton = view.findViewById(R.id.open_files_button);
44+
Button mNewsButton = view.findViewById(R.id.news_button);
45+
Button mDiscordButton = view.findViewById(R.id.discord_button);
46+
Button mCustomControlButton = view.findViewById(R.id.custom_control_button);
47+
Button mInstallJarButton = view.findViewById(R.id.install_jar_button);
48+
Button mShareLogsButton = view.findViewById(R.id.share_logs_button);
49+
Button mManageModsButton = view.findViewById(R.id.open_files_button);
50+
Button mOpenDirectoryButton = view.findViewById(R.id.open_directory_button);
51+
Button mModStoreButton = view.findViewById(R.id.mod_store_button);
5452

5553
ImageButton mEditProfileButton = view.findViewById(R.id.edit_profile_button);
5654
Button mPlayButton = view.findViewById(R.id.play_button);
5755
mVersionSpinner = view.findViewById(R.id.mc_version_spinner);
5856

57+
// Wiki
5958
mNewsButton.setOnClickListener(v -> Tools.openURL(requireActivity(), Tools.URL_HOME));
59+
60+
// Discord
6061
mDiscordButton.setOnClickListener(v -> Tools.openURL(requireActivity(), getString(R.string.discord_invite)));
61-
mCustomControlButton.setOnClickListener(v -> startActivity(new Intent(requireContext(), CustomControlsActivity.class)));
62+
63+
// Custom controls
64+
mCustomControlButton.setOnClickListener(v ->
65+
startActivity(new Intent(requireContext(), CustomControlsActivity.class)));
66+
67+
// Mod Store → individual mod search
68+
if (mModStoreButton != null)
69+
mModStoreButton.setOnClickListener(v ->
70+
Tools.swapFragment(requireActivity(), ModsSearchFragment.class, ModsSearchFragment.TAG, null));
71+
72+
// Execute .jar
6273
if (hasOnlineProfile()) {
6374
mInstallJarButton.setOnClickListener(v -> runInstallerWithConfirmation(false));
6475
mInstallJarButton.setOnLongClickListener(v -> {
6576
runInstallerWithConfirmation(true);
6677
return true;
6778
});
68-
} else mInstallJarButton.setOnClickListener(v -> hasNoOnlineProfileDialog(requireActivity()));
69-
mEditProfileButton.setOnClickListener(v -> mVersionSpinner.openProfileEditor(requireActivity()));
70-
71-
mPlayButton.setOnClickListener(v -> {
72-
ExtraCore.setValue(ExtraConstants.LAUNCH_GAME, true);
73-
});
74-
75-
mShareLogsButton.setOnClickListener((v) -> shareLog(requireContext()));
76-
77-
mOpenDirectoryButton.setOnClickListener((v)-> {
78-
if (Tools.isDemoProfile(v.getContext())){ // Say a different message when on demo profile since they might see the hidden demo folder
79-
hasNoOnlineProfileDialog(getActivity(), getString(R.string.demo_unsupported), getString(R.string.change_account));
80-
} else if (!hasOnlineProfile()) { // Otherwise display the generic pop-up to log in
81-
hasNoOnlineProfileDialog(requireActivity());
82-
} else openPath(v.getContext(), getCurrentProfileDirectory(), false);
79+
} else {
80+
mInstallJarButton.setOnClickListener(v -> hasNoOnlineProfileDialog(requireActivity()));
81+
}
82+
83+
// Share logs
84+
if (mShareLogsButton != null)
85+
mShareLogsButton.setOnClickListener(v -> shareLog(requireContext()));
86+
87+
// Manage Mods & Tools → new UI
88+
mManageModsButton.setOnClickListener(v ->
89+
Tools.swapFragment(requireActivity(), ManageModsFragment.class, ManageModsFragment.TAG, null));
90+
91+
// Open game directory (original behaviour)
92+
if (mOpenDirectoryButton != null) {
93+
mOpenDirectoryButton.setOnClickListener(v -> {
94+
if (Tools.isDemoProfile(v.getContext())) {
95+
hasNoOnlineProfileDialog(getActivity(),
96+
getString(R.string.demo_unsupported), getString(R.string.change_account));
97+
} else if (!hasOnlineProfile()) {
98+
hasNoOnlineProfileDialog(requireActivity());
99+
} else {
100+
openPath(v.getContext(), getCurrentProfileDirectory(), false);
101+
}
102+
});
103+
}
83104

84-
});
105+
// Edit profile
106+
mEditProfileButton.setOnClickListener(v -> mVersionSpinner.openProfileEditor(requireActivity()));
85107

108+
// Play
109+
mPlayButton.setOnClickListener(v -> ExtraCore.setValue(ExtraConstants.LAUNCH_GAME, true));
86110

87-
mNewsButton.setOnLongClickListener((v)->{
111+
// Long-press wiki → gamepad mapper (hidden)
112+
mNewsButton.setOnLongClickListener(v -> {
88113
Tools.swapFragment(requireActivity(), GamepadMapperFragment.class, GamepadMapperFragment.TAG, null);
89114
return true;
90115
});
91116
}
92117

93118
private File getCurrentProfileDirectory() {
94-
String currentProfile = LauncherPreferences.DEFAULT_PREF.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE, null);
95-
if(!Tools.isValidString(currentProfile)) return new File(Tools.DIR_GAME_NEW);
119+
String currentProfile = LauncherPreferences.DEFAULT_PREF
120+
.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE, null);
121+
if (!Tools.isValidString(currentProfile)) return new File(Tools.DIR_GAME_NEW);
96122
LauncherProfiles.load();
97123
MinecraftProfile profileObject = LauncherProfiles.mainProfileJson.profiles.get(currentProfile);
98-
if(profileObject == null) return new File(Tools.DIR_GAME_NEW);
124+
if (profileObject == null) return new File(Tools.DIR_GAME_NEW);
99125
return Tools.getGameDirPath(profileObject);
100126
}
101127

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package net.kdt.pojavlaunch.fragments;
2+
3+
import android.os.Bundle;
4+
import android.view.View;
5+
import android.widget.ImageButton;
6+
import android.widget.TextView;
7+
8+
import androidx.annotation.NonNull;
9+
import androidx.annotation.Nullable;
10+
import androidx.fragment.app.Fragment;
11+
import androidx.recyclerview.widget.LinearLayoutManager;
12+
import androidx.recyclerview.widget.RecyclerView;
13+
14+
import net.kdt.pojavlaunch.R;
15+
import net.kdt.pojavlaunch.fragments.ModsSearchFragment;
16+
import net.kdt.pojavlaunch.Tools;
17+
import net.kdt.pojavlaunch.modloaders.InstalledModAdapter;
18+
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
19+
import net.kdt.pojavlaunch.value.launcherprofiles.LauncherProfiles;
20+
import net.kdt.pojavlaunch.value.launcherprofiles.MinecraftProfile;
21+
22+
import java.io.File;
23+
24+
public class ManageModsFragment extends Fragment {
25+
26+
public static final String TAG = "ManageModsFragment";
27+
28+
public ManageModsFragment() {
29+
super(R.layout.fragment_manage_mods);
30+
}
31+
32+
@Override
33+
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
34+
ImageButton backButton = view.findViewById(R.id.manage_mods_back);
35+
ImageButton addButton = view.findViewById(R.id.manage_mods_add);
36+
TextView title = view.findViewById(R.id.manage_mods_title);
37+
RecyclerView recycler = view.findViewById(R.id.manage_mods_recycler);
38+
View emptyState = view.findViewById(R.id.manage_mods_empty);
39+
40+
// Back
41+
backButton.setOnClickListener(v -> Tools.removeCurrentFragment(requireActivity()));
42+
43+
// Add → open mod store
44+
addButton.setOnClickListener(v ->
45+
Tools.swapFragment(requireActivity(), ModsSearchFragment.class, ModsSearchFragment.TAG, null));
46+
47+
// Title: "ProfileName - Mods"
48+
String profileName = getCurrentProfileName();
49+
title.setText(profileName.isEmpty()
50+
? getString(R.string.mcl_button_manage_mods)
51+
: profileName + " - Mods");
52+
53+
// Build mod list
54+
File modsDir = getModsDir();
55+
InstalledModAdapter adapter = new InstalledModAdapter(modsDir, isEmpty -> {
56+
recycler.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
57+
emptyState.setVisibility(isEmpty ? View.VISIBLE : View.GONE);
58+
});
59+
60+
recycler.setLayoutManager(new LinearLayoutManager(requireContext()));
61+
recycler.setAdapter(adapter);
62+
}
63+
64+
// ── Helpers ─────────────────────────────────────────────────────────────
65+
66+
private String getCurrentProfileName() {
67+
try {
68+
String key = LauncherPreferences.DEFAULT_PREF
69+
.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE, null);
70+
if (key == null || key.isEmpty()) return "";
71+
LauncherProfiles.load();
72+
MinecraftProfile profile = LauncherProfiles.mainProfileJson.profiles.get(key);
73+
if (profile == null) return "";
74+
return profile.name != null ? profile.name : key;
75+
} catch (Exception e) {
76+
return "";
77+
}
78+
}
79+
80+
private File getModsDir() {
81+
try {
82+
String key = LauncherPreferences.DEFAULT_PREF
83+
.getString(LauncherPreferences.PREF_KEY_CURRENT_PROFILE, null);
84+
if (key != null && !key.isEmpty()) {
85+
LauncherProfiles.load();
86+
MinecraftProfile profile = LauncherProfiles.mainProfileJson.profiles.get(key);
87+
if (profile != null) {
88+
File gameDir = Tools.getGameDirPath(profile);
89+
return new File(gameDir, "mods");
90+
}
91+
}
92+
} catch (Exception ignored) {}
93+
return new File(Tools.DIR_GAME_NEW, "mods");
94+
}
95+
}

0 commit comments

Comments
 (0)