Skip to content

Commit

Permalink
plugin discoverer api
Browse files Browse the repository at this point in the history
  • Loading branch information
deirn committed Mar 12, 2024
1 parent d8061f7 commit 9a1064f
Show file tree
Hide file tree
Showing 22 changed files with 246 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,37 @@

import com.google.common.collect.Streams;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import mcp.mobius.waila.Waila;
import mcp.mobius.waila.api.IPluginInfo;
import mcp.mobius.waila.plugin.PluginInfo;
import mcp.mobius.waila.plugin.PluginLoader;
import mcp.mobius.waila.plugin.DefaultPluginDiscoverer;
import mcp.mobius.waila.util.Log;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.metadata.CustomValue;
import net.minecraft.resources.ResourceLocation;

import static net.fabricmc.loader.api.metadata.CustomValue.CvType.ARRAY;
import static net.fabricmc.loader.api.metadata.CustomValue.CvType.OBJECT;
import static net.fabricmc.loader.api.metadata.CustomValue.CvType.STRING;

public class FabricPluginLoader extends PluginLoader {
public class FabricPluginDiscoverer extends DefaultPluginDiscoverer {

public static final ResourceLocation ID = Waila.id("fabric");

private static final Log LOG = Log.create();

@Override
protected void gatherPlugins() {
public ResourceLocation getDiscovererId() {
return ID;
}

@Override
public void discover(Candidates candidates) {
Map<ModContainer, CustomValue.CvObject[]> pluginMap = new Object2ObjectOpenHashMap<>();
for (var mod : FabricLoader.getInstance().getAllMods()) {
for (var file : PLUGIN_JSON_FILES) {
mod.findPath(file).ifPresent(path -> readPluginsJson(mod.getMetadata().getId(), path));
mod.findPath(file).ifPresent(path -> readPluginsJson(candidates, mod.getMetadata().getId(), path));
}

var data = mod.getMetadata();
Expand Down Expand Up @@ -100,7 +108,7 @@ protected void gatherPlugins() {
continue;
}

PluginInfo.register(mod.getMetadata().getId(), id, side, initializer, requiredDeps, true, true);
registerLegacy(mod.getMetadata().getId(), id, side, requiredDeps, initializer);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void onInitialize() {
.ifPresent(m -> DumpGenerator.VERSIONS.put(m.getName(), m.getVersion().getFriendlyString()));
}

PluginLoader.INSTANCE.loadPlugins();
PluginLoader.load();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mcp.mobius.waila.fabric.FabricPluginDiscoverer

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,34 @@
import java.nio.file.Files;
import java.util.Arrays;

import mcp.mobius.waila.Waila;
import mcp.mobius.waila.api.IPluginInfo;
import mcp.mobius.waila.api.WailaPlugin;
import mcp.mobius.waila.plugin.PluginInfo;
import mcp.mobius.waila.plugin.PluginLoader;
import mcp.mobius.waila.plugin.DefaultPluginDiscoverer;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.loading.FMLLoader;

public class ForgePluginLoader extends PluginLoader {
public class ForgePluginDiscoverer extends DefaultPluginDiscoverer {

public static final ResourceLocation ID = Waila.id("forge");

@SuppressWarnings("deprecation")
private static final String WAILA_PLUGIN = WailaPlugin.class.getName();

@Override
protected void gatherPlugins() {
public ResourceLocation getDiscovererId() {
return ID;
}

@Override
public void discover(Candidates candidates) {
for (var modFile : ModList.get().getModFiles()) {
for (var file : PLUGIN_JSON_FILES) {
var path = modFile.getFile().findResource(file);
if (Files.exists(path)) {
readPluginsJson(modFile.getMods().get(0).getModId(), path);
readPluginsJson(candidates, modFile.getMods().get(0).getModId(), path);
}
}

Expand All @@ -46,7 +54,7 @@ protected void gatherPlugins() {
}

if (satisfied) {
PluginInfo.register(modFile.getMods().get(0).getModId(), id, side, annotation.memberName(), Arrays.asList(required), true, true);
registerLegacy(modFile.getMods().get(0).getModId(), id, side, Arrays.asList(required), annotation.memberName());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static void setup(FMLCommonSetupEvent event) {

@SubscribeEvent
static void loadComplete(FMLLoadCompleteEvent event) {
PluginLoader.INSTANCE.loadPlugins();
PluginLoader.load();
}

@EventBusSubscriber(modid = WailaConstants.WAILA)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mcp.mobius.waila.forge.ForgePluginDiscoverer

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package mcp.mobius.waila.neo;

import java.nio.file.Files;

import mcp.mobius.waila.Waila;
import mcp.mobius.waila.plugin.DefaultPluginDiscoverer;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.fml.ModList;

public class NeoPluginDiscoverer extends DefaultPluginDiscoverer {

public static final ResourceLocation ID = Waila.id("neo");

@Override
public ResourceLocation getDiscovererId() {
return ID;
}

@Override
public void discover(Candidates candidates) {
for (var modFile : ModList.get().getModFiles()) {
for (var file : PLUGIN_JSON_FILES) {
var path = modFile.getFile().findResource(file);
if (Files.exists(path)) {
readPluginsJson(candidates, modFile.getMods().get(0).getModId(), path);
}
}
}
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static void setup(FMLCommonSetupEvent event) {

@SubscribeEvent
static void loadComplete(FMLLoadCompleteEvent event) {
PluginLoader.INSTANCE.loadPlugins();
PluginLoader.load();
}

@EventBusSubscriber(modid = WailaConstants.WAILA)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mcp.mobius.waila.neo.NeoPluginDiscoverer

This file was deleted.

53 changes: 53 additions & 0 deletions src/api/java/mcp/mobius/waila/api/IPluginDiscoverer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package mcp.mobius.waila.api;

import java.util.List;

import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;

/**
* Dynamic plugin discoverer.
* <p>
* Implement this class as a service provider.
*/
@ApiStatus.Experimental
public interface IPluginDiscoverer {

/**
* Returns the discoverer ID.
*/
ResourceLocation getDiscovererId();

/**
* Discover plugin candidates.
* <p>
* Will only called once per game session.
*
* @param candidates the plugin candidates
*/
void discover(Candidates candidates);

@ApiStatus.NonExtendable
interface Candidates {

/**
* Adds a plugin candidate.
*
* @param modId the mod origin
* @param pluginId the plugin id
* @param side the plugin environment side
* @param requiredModIds the plugin dependencies
* @param defaultEnabled whether the plugin is enabled by default or require end user to manually enable it
* @param factory the instance factory, will only be called when the environment and dependencies match
*/
void add(String modId, ResourceLocation pluginId, IPluginInfo.Side side, List<String> requiredModIds, boolean defaultEnabled, Factory factory);

}

interface Factory {

IWailaPlugin get() throws Exception;

}

}
2 changes: 1 addition & 1 deletion src/main/java/mcp/mobius/waila/command/ClientCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ protected Minecraft getExecutor(S source) {

@Override
protected void reloadPlugins(Minecraft executor) {
PluginLoader.reloadClientPlugins();
PluginLoader.reloadClient();
}

}
2 changes: 1 addition & 1 deletion src/main/java/mcp/mobius/waila/command/ServerCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ protected MinecraftServer getExecutor(CommandSourceStack source) {

@Override
protected void reloadPlugins(MinecraftServer executor) {
PluginLoader.reloadServerPlugins(executor);
PluginLoader.reloadServer(executor);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public ConfigListWidget getOptions() {
var integratedServer = minecraft.getSingleplayerServer();

if (integratedServer != null) {
PluginLoader.reloadServerPlugins(integratedServer);
PluginLoader.reloadServer(integratedServer);
} else {
PluginLoader.reloadClientPlugins();
PluginLoader.reloadClient();
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private static void receive(Payload payload) {
((PluginInfo) IPluginInfo.get(plugin)).setDisabledOnServer(true);
}

PluginLoader.INSTANCE.loadPlugins();
PluginLoader.load();
}

@Override
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/mcp/mobius/waila/plugin/DefaultPluginDiscoverer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package mcp.mobius.waila.plugin;

import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.google.gson.JsonParser;
import mcp.mobius.waila.Waila;
import mcp.mobius.waila.api.IPluginDiscoverer;
import mcp.mobius.waila.api.IPluginInfo;
import mcp.mobius.waila.api.IWailaPlugin;
import net.minecraft.resources.ResourceLocation;

public abstract class DefaultPluginDiscoverer implements IPluginDiscoverer {

public static final ResourceLocation LEGACY = Waila.id("legacy");

protected static final String[] PLUGIN_JSON_FILES = {
"waila_plugins.json",
"wthit_plugins.json"
};

protected static final String KEY_INITIALIZER = "initializer";
protected static final String KEY_SIDE = "side";
protected static final String KEY_REQUIRED = "required";
protected static final String KEY_DEFAULT_ENABLED = "defaultEnabled";
protected static final Map<String, IPluginInfo.Side> SIDES = Map.of(
"client", IPluginInfo.Side.CLIENT,
"server", IPluginInfo.Side.SERVER,
"both", IPluginInfo.Side.BOTH,
"*", IPluginInfo.Side.BOTH
);

protected Factory factory(String initializer) {
return () -> (IWailaPlugin) Class.forName(initializer).getConstructor().newInstance();
}

protected void registerLegacy(String modId, String pluginId, IPluginInfo.Side side, List<String> requiredModIds, String initializer) {
PluginInfo.register(LEGACY, modId, new ResourceLocation(pluginId), side, requiredModIds, true, factory(initializer));
}

protected void readPluginsJson(Candidates candidates, String modId, Path path) {
try (Reader reader = Files.newBufferedReader(path)) {
var object = JsonParser.parseReader(reader).getAsJsonObject();

for (var pluginId : object.keySet()) {
var plugin = object.getAsJsonObject(pluginId);

var initializer = plugin.getAsJsonPrimitive(KEY_INITIALIZER).getAsString();
var side = plugin.has(KEY_SIDE)
? Objects.requireNonNull(SIDES.get(plugin.get(KEY_SIDE).getAsString()), () -> readError(path) + ", invalid side, available: " + SIDES.keySet().stream().collect(Collectors.joining(", ", "[", "]")))
: IPluginInfo.Side.BOTH;

List<String> required = new ArrayList<>();
if (plugin.has(KEY_REQUIRED)) {
var array = plugin.getAsJsonArray(KEY_REQUIRED);
for (var element : array) {
var requiredModId = element.getAsString();
required.add(requiredModId);
}
}

var defaultEnabled = !plugin.has(KEY_DEFAULT_ENABLED) || plugin.get(KEY_DEFAULT_ENABLED).getAsBoolean();
candidates.add(modId, new ResourceLocation(pluginId), side, required, defaultEnabled, factory(initializer));
}
} catch (IOException e) {
throw new RuntimeException(readError(path), e);
}
}

private static String readError(Path path) {
return "Failed to read [" + path + "]";
}

}
Loading

0 comments on commit 9a1064f

Please sign in to comment.