deploader v2

This commit is contained in:
FalsePattern committed 2025-08-01 00:07:07 +02:00
1 parent cbef9706db
commit c03f221ef9
8 files changed
+128 -27

No files matched your search

@@ -22,6 +22,7 @@
package com.falsepattern.lib.internal;
import com.falsepattern.lib.internal.asm.PreShare;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.val;
@@ -32,16 +33,7 @@ import java.io.IOException;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class Share {
public static final boolean DEV_ENV;
static {
try {
val bs = Launch.classLoader.getClassBytes("net.minecraft.world.World");
DEV_ENV = bs != null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static final boolean DEV_ENV = PreShare.devEnv();
public static boolean EARLY_INIT_DONE = false;
}
@@ -56,6 +56,7 @@ public class CoreLoadingPlugin implements IFMLLoadingPlugin {
private static boolean obfuscated;
static {
PreShare.initDevState(Launch.classLoader.findResource("net/minecraft/world/World.class") != null);
LetsEncryptHelper.replaceSSLContext();
FPLog.LOG.info("Removing skill issues...");
try {
@@ -67,7 +68,7 @@ public class CoreLoadingPlugin implements IFMLLoadingPlugin {
//Scan for dependencies now
FPLog.LOG.info("Scanning for deps...");
long start = System.nanoTime();
DependencyLoaderImpl.executeDependencyLoading(true);
DependencyLoaderImpl.executeDependencyLoading();
long end = System.nanoTime();
FPLog.LOG.info("Scanned in " + (end - start) / 1000000 + "ms");
//Initializing the rest
@@ -0,0 +1,41 @@
/*
* This file is part of FalsePatternLib.
*
* Copyright (C) 2022-2025 FalsePattern
* All Rights Reserved
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* FalsePatternLib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, only version 3 of the License.
*
* FalsePatternLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FalsePatternLib. If not, see <https://www.gnu.org/licenses/>.
*/
package com.falsepattern.lib.internal.asm;
import lombok.Getter;
public class PreShare {
private static volatile boolean devEnv = false;
private static volatile boolean inited = false;
public static synchronized void initDevState(boolean state) {
if (inited) {
return;
}
inited = true;
devEnv = state;
}
public static synchronized boolean devEnv() {
return devEnv;
}
}
@@ -25,12 +25,31 @@ package com.falsepattern.lib.internal.asm;
import com.falsepattern.lib.internal.core.LowLevelCallMultiplexer;
import com.falsepattern.lib.internal.impl.dependencies.DependencyLoaderImpl;
import com.falsepattern.lib.internal.impl.dependencies.LetsEncryptHelper;
import com.gtnewhorizons.retrofuturabootstrap.RfbApiImpl;
import com.gtnewhorizons.retrofuturabootstrap.api.RfbPlugin;
import lombok.val;
import java.net.URLClassLoader;
public class RFBLoadingPlugin implements RfbPlugin {
static {
val loader = RfbApiImpl.INSTANCE.launchClassLoader();
try {
val exc = loader.getClass()
.getDeclaredMethod("addClassLoaderExclusion", String.class);
exc.invoke(loader, "com.falsepattern.lib.dependencies.");
exc.invoke(loader, "com.falsepattern.lib.internal.impl.dependencies.");
exc.invoke(loader, "com.falsepattern.lib.internal.Internet");
exc.invoke(loader, "com.falsepattern.lib.internal.Share");
exc.invoke(loader, "com.falsepattern.lib.internal.asm.PreShare");
exc.invoke(loader, "com.falsepattern.lib.internal.FPLog");
exc.invoke(loader, "com.falsepattern.lib.internal.Tags");
exc.invoke(loader, "com.falsepattern.lib.internal.config.EarlyConfig");
exc.invoke(loader, "com.falsepattern.lib.internal.core.LowLevelCallMultiplexer");
} catch (Exception ignored) {}
PreShare.initDevState(((URLClassLoader)loader).findResource("net/minecraft/world/World.class") != null);
LetsEncryptHelper.replaceSSLContext();
LowLevelCallMultiplexer.rfbDetected();
DependencyLoaderImpl.executeDependencyLoading(false);
DependencyLoaderImpl.executeDependencyLoading();
}
}
@@ -29,8 +29,10 @@ import org.jetbrains.annotations.NotNull;
import net.minecraft.launchwrapper.Launch;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
@UtilityClass
@@ -64,21 +66,32 @@ public class LowLevelCallMultiplexer {
}
}
public static int javaMajorVersion() {
if (rfbDetected) {
return RFBLowLevel.javaMajorVersion();
} else {
return LaunchWrapperLowLevel.javaMajorVersion();
}
}
//Separate classes to avoid accidental classloading
@SuppressWarnings("resource")
private static class RFBLowLevel {
static void addURLToClassPath(URL url) {
RfbApiImpl.INSTANCE.compatClassLoader().addURL(url);
RfbApiImpl.INSTANCE.launchClassLoader().addURL(url);
}
static List<URL> getClassPathSources() {
return RfbApiImpl.INSTANCE.compatClassLoader().getSources();
return Arrays.asList(((URLClassLoader)RfbApiImpl.INSTANCE.launchClassLoader()).getURLs());
}
static @NotNull Path gameDir() {
return RfbApiImpl.INSTANCE.gameDirectory();
}
static int javaMajorVersion() {
return RfbApiImpl.INSTANCE.javaMajorVersion();
}
}
private static class LaunchWrapperLowLevel {
@@ -93,5 +106,16 @@ public class LowLevelCallMultiplexer {
static @NotNull Path gameDir() {
return Launch.minecraftHome == null ? Paths.get(".") : Launch.minecraftHome.toPath();
}
static int javaMajorVersion() {
String version = System.getProperty("java.version");
if(version.startsWith("1.")) {
version = version.substring(2, 3);
} else {
int dot = version.indexOf(".");
if(dot != -1) { version = version.substring(0, dot); }
}
return Integer.parseInt(version);
}
}
}
@@ -33,6 +33,10 @@ import java.util.List;
public class DepRoot {
private String source;
@Expose
private Integer minJava;
@Expose
private Integer maxJava;
@Expose
private List<String> repositories;
@Expose
private Dependencies dependencies;
@@ -225,12 +225,12 @@ public class DependencyLoaderImpl {
}
}
private static synchronized void addToClasspath(Path file) {
private static synchronized void addToClasspath(URL file) {
try {
LowLevelCallMultiplexer.addURLToClassPath(file.toUri().toURL());
LowLevelCallMultiplexer.addURLToClassPath(file);
LOG.debug("Injected file {} into classpath!", file);
} catch (Exception e) {
throw new RuntimeException("Failed to add library to classpath: " + file.toAbsolutePath(), e);
throw new RuntimeException("Failed to add library to classpath: " + file, e);
}
}
@@ -407,13 +407,13 @@ public class DependencyLoaderImpl {
private static boolean initialScan = false;
private static List<Pair<ScopeSide, DependencyLoadTask>> tasks;
public static void executeDependencyLoading(boolean sideAware) {
public static void executeDependencyLoading() {
if (!initialScan) {
initialScan = true;
scanDeps();
}
executeArtifactLoading(sideAware);
executeArtifactLoading();
}
private static void scanDeps() {
@@ -450,6 +450,7 @@ public class DependencyLoaderImpl {
} catch (IOException e) {
LOG.error("Could not write dependency scanner cache", e);
}
val javaVersion = LowLevelCallMultiplexer.javaMajorVersion();
val dependencySpecs = urls.stream().map((source) -> {
//Convert source to GSON json
try (val is = new BufferedInputStream(source.openStream())) {
@@ -468,6 +469,11 @@ public class DependencyLoaderImpl {
val gson = builder.create();
json.remove("identifier");
val root = gson.fromJson(json, DepRoot.class);
val minJ = root.minJava();
val maxJ = root.maxJava();
if (minJ != null && minJ > javaVersion || maxJ != null && maxJ < javaVersion) {
return null;
}
root.source(source.toString());
return root;
} catch (Exception e) {
@@ -562,8 +568,8 @@ public class DependencyLoaderImpl {
}
}
private static void executeArtifactLoading(boolean sideAware) {
val scopeSide = sideAware ? SideAwareAssistant.current() : new ScopeSide(DependencyScope.ALWAYS, DependencySide.COMMON);
private static void executeArtifactLoading() {
val scopeSide = SideAwareAssistant.current();
val iter = tasks.iterator();
val artifactMap = new HashMap<String, DependencyLoadTask>();
while (iter.hasNext()) {
@@ -621,7 +627,6 @@ public class DependencyLoaderImpl {
}
jFrame.pack();
jFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
jFrame.setVisible(true);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
jFrame.setLocation(dim.width/2-jFrame.getSize().width/2, dim.height/2-jFrame.getSize().height/2);
} catch (Exception ignored) {
@@ -667,7 +672,14 @@ public class DependencyLoaderImpl {
@NotNull
private static Thread getVizThread(AtomicBoolean doViz, HashMap<DependencyLoadTask, JProgressBar> progresses, JFrame theFrame) {
val vizThread = new Thread(() -> {
int waitBeforeShowing = 100;
while (doViz.get()) {
if (waitBeforeShowing > 0) {
waitBeforeShowing--;
} else if (waitBeforeShowing == 0) {
theFrame.setVisible(true);
waitBeforeShowing = -1;
}
for (val progress : progresses.entrySet()) {
val task = progress.getKey();
val bar = progress.getValue();
@@ -825,11 +837,11 @@ public class DependencyLoaderImpl {
return false;
}
try {
addToClasspath(file);
addToClasspath(file.toUri().toURL());
loadedLibraries.put(artifact, preferredVersion);
LOG.debug("Library {} successfully loaded from disk!", artifactLogName);
return true;
} catch (RuntimeException e) {
} catch (Exception e) {
LOG.warn("Failed to load library {} from file! Re-downloading...", artifactLogName);
checkedDelete(file);
return false;
@@ -912,7 +924,7 @@ public class DependencyLoaderImpl {
}
loadedLibraries.put(artifact, preferredVersion);
loadedLibraryMods.put(artifact, loadingModId);
addToClasspath(file);
addToClasspath(file.toUri().toURL());
return true;
}
}