Skip to content

Commit

Permalink
Fix fabric mod entrypoint class unexpectedly loaded
Browse files Browse the repository at this point in the history
Signed-off-by: Hendrix-Shen <HendrixShen@hendrixshen.top>
  • Loading branch information
Hendrix-Shen committed May 9, 2024
1 parent 112cea8 commit 0a3343c
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
package top.hendrixshen.magiclib.util;

import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import top.hendrixshen.magiclib.MagicLib;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Set;

public class FileUtil {
public static @NotNull File getConfigFile(String identifier) {
return MagicLib.getInstance().getPlatformManage().getCurrentPlatform()
.getConfigFolder().resolve(identifier + ".json").toFile();
}

public static @NotNull Set<URL> getResources(String name) throws IOException {
ClassLoader urlLoader = Thread.currentThread().getContextClassLoader();
Set<URL> set = Sets.newHashSet();
Enumeration<URL> urlEnumeration = urlLoader.getResources(name);

while (urlEnumeration.hasMoreElements()) {
set.add(urlEnumeration.nextElement());
}

return set;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,28 @@
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.DedicatedServerModInitializer;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.entrypoint.EntrypointContainer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import top.hendrixshen.magiclib.api.platform.adapter.ModEntryPointAdapter;
import top.hendrixshen.magiclib.impl.platform.adapter.internal.ModMetaDataLite;
import top.hendrixshen.magiclib.util.collect.ValueContainer;
import top.hendrixshen.magiclib.util.mixin.MixinUtil;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;

public class FabricModEntryPoint implements ModEntryPointAdapter {
private final List<ClassNode> entryPoints;

public FabricModEntryPoint(@NotNull FabricModContainer container) {
List<EntrypointContainer<?>> containers = Lists.newArrayList();
containers.addAll(FabricModEntryPoint.getEntryPoint("main", ModInitializer.class,
container.getModMetaData().getModId()));
containers.addAll(FabricModEntryPoint.getEntryPoint("client", ClientModInitializer.class,
container.getModMetaData().getModId()));
containers.addAll(FabricModEntryPoint.getEntryPoint("server", DedicatedServerModInitializer.class,
container.getModMetaData().getModId()));

Set<String> containers = Sets.newHashSet();
containers.addAll(FabricModEntryPoint.getEntryPoint("main", container.getModMetaData().getModId()));
containers.addAll(FabricModEntryPoint.getEntryPoint("client", container.getModMetaData().getModId()));
containers.addAll(FabricModEntryPoint.getEntryPoint("server", container.getModMetaData().getModId()));
this.entryPoints = containers.stream()
.map(entrypointContainer -> entrypointContainer.getEntrypoint().getClass())
.filter(clazz -> !clazz.getName().startsWith("com.sun.proxy.jdk.proxy3"))
.filter(clazz -> !clazz.getName().contains("$$Lambda"))
.map(clazz -> MixinUtil.getClassNode(clazz.getName()))
.map(FabricModEntryPoint::validateAndCreate)
.filter(Objects::nonNull)
.collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
Sets.newTreeSet(Comparator.comparing(classNode -> classNode.name))), Lists::newArrayList));
Expand All @@ -52,13 +43,24 @@ public Collection<ClassNode> getMagicEntryPoints() {
.filter(classNode ->
classNode.interfaces.contains(Type.getType(ModInitializer.class).getInternalName()) ||
classNode.interfaces.contains(Type.getType(ClientModInitializer.class).getInternalName()) ||
classNode.interfaces.contains(Type.getType(ModInitializer.class).getInternalName()))
classNode.interfaces.contains(Type.getType(DedicatedServerModInitializer.class).getInternalName()))
.collect(Collectors.toList());
}

public static Collection<EntrypointContainer<?>> getEntryPoint(String key, Class<?> type, String modId) {
return FabricLoader.getInstance().getEntrypointContainers(key, type).stream()
.filter(entrypoint -> entrypoint.getProvider().getMetadata().getId().equals(modId))
.collect(Collectors.toList());
public static @NotNull Collection<String> getEntryPoint(String key, String modIdentifier) {
return Lists.newArrayList(ValueContainer.ofNullable(ModMetaDataLite.getMetaData(modIdentifier))
.flatMap(metaData -> ValueContainer.ofNullable(metaData.getEntrypoints().get(key)))
.orElse(Sets.newHashSet()));
}

private static @Nullable ClassNode validateAndCreate(@NotNull String value) {
String[] methodSplit = value.split("::");

// Only provide standard entrypoint.
if (methodSplit.length != 1) {
return null;
}

return MixinUtil.getClassNode(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package top.hendrixshen.magiclib.impl.platform.adapter.internal;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import lombok.Getter;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import top.hendrixshen.magiclib.MagicLib;
import top.hendrixshen.magiclib.util.FileUtil;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Map;

@ApiStatus.Internal
public class ModMetaDataLite {
private static final Map<String, MetaData> data = Maps.newHashMap();

public static MetaData getMetaData(String modIdentifier) {
return ModMetaDataLite.data.get(modIdentifier);
}

static {
try {
for (URL url : FileUtil.getResources("fabric.mod.json")) {
InputStream inputStream = url.openStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
JsonReader jsonReader = new JsonReader(inputStreamReader);

try {
MetaData modMetaData = new MetaData(jsonReader);
ModMetaDataLite.data.put(modMetaData.getModIdentifier(), modMetaData);
} catch (Throwable e) {
MagicLib.getLogger().debug("Failed to parse {}.", url, e);
}
}
} catch (IOException e) {
MagicLib.getLogger().error("Failed to load fabric.mod.json", e);
}
}

@Getter
public static class MetaData {
private String modIdentifier;
private final Map<String, HashSet<String>> entrypoints;

MetaData(@NotNull JsonReader reader) throws IOException {
this.entrypoints = Maps.newHashMap();
reader.beginObject();

while (reader.hasNext()) {
String key = reader.nextName();

switch (key) {
case "id":
this.modIdentifier = reader.nextString();
break;

case "entrypoints":
reader.beginObject();

while (reader.hasNext()) {
final String entryKey = reader.nextName();
reader.beginArray();

while (reader.hasNext()) {
if (reader.peek() == JsonToken.STRING) {
this.entrypoints.computeIfAbsent(entryKey, k -> Sets.newHashSet()).add(reader.nextString());
} else {
reader.skipValue();
}
}

reader.endArray();
}

reader.endObject();
break;
default:
reader.skipValue();
}
}

reader.endObject();
}
}
}

0 comments on commit 0a3343c

Please sign in to comment.