Skip to content

Commit

Permalink
Add KubeJS plugin bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
Su5eD committed Dec 10, 2023
1 parent 9f71ab4 commit f55da37
Show file tree
Hide file tree
Showing 14 changed files with 374 additions and 2 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ However, this is too soon as it happens before blocks of Forge mods are register
be created for Forge mod blocks. To fix this issue, we patch Continuity to move the block state map initialization from
Fabric's client entrypoint to FML's client setup event, which is fired after registration has completed.

### KubeJS Bridge

Provides KubeJS plugin support for Fabric mods on Forge by initializing them earlier.

### Amecs API - Forge port

A Forge port of the Fabric [Amecs API](https://github.com/Siphalor/amecs-api)
Expand Down
3 changes: 3 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ dependencies {
includeProject("amecs-api")
includeProject("forgeconfigapiport")
includeProject("extras-utils")
includeProject("kubejs-bridge")

// Misc
modImplementation("curse.maven:mcpitanlibarch-682213:4723157")
Expand Down Expand Up @@ -197,6 +198,7 @@ publishMods {
optional { slug.set("architectury-api") }
optional { slug.set("geckolib") }
optional { slug.set("continuity") }
optional { slug.set("kubejs") }
}
modrinth {
accessToken.set(providers.environmentVariable("MODRINTH_TOKEN"))
Expand All @@ -211,5 +213,6 @@ publishMods {
optional { id.set("lhGA9TYQ") } // Architectury API
optional { id.set("8BmcQJ2H") } // Geckolib
optional { id.set("1IjD5062") } // Continuity
optional { id.set("umyGl7zF") } // KubeJS
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fabric.loom.multiProjectOptimisation=true
# Versions
versionMc=1.20.1
versionForge=47.1.3
versionConnectorExtras=1.7.0
versionConnectorExtras=1.8.0

# Publishing
curseForgeId=913445
Expand Down
40 changes: 40 additions & 0 deletions kubejs-bridge/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
plugins {
id("dev.architectury.loom")
}

val versionMc: String by rootProject
val versionForge: String by rootProject

loom {
forge {
mixinConfig("mixins.connectorextras_kubejs_bridge.json")
}
mixin {
defaultRefmapName.set("refmap.connectorextras_kubejs_bridge.json")
}
}

repositories {
maven {
url = uri("https://maven.architectury.dev")
content {
includeGroup("dev.architectury")
}
}
maven {
url = uri("https://maven.saps.dev/minecraft")
content {
includeGroup("dev.latvian.mods")
}
}
}

dependencies {
mappings(loom.officialMojangMappings())
forge(group = "net.minecraftforge", name = "forge", version = "$versionMc-$versionForge")

modImplementation("dev.su5ed.sinytra:Connector:1.0.0-beta.29+1.20.1")
modImplementation("dev.latvian.mods:kubejs-forge:2001.6.4-build.111")
modImplementation("dev.latvian.mods:rhino-forge:2001.2.2-build.13")
modImplementation("dev.architectury:architectury-forge:9.1.12")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.su5ed.sinytra.connectorextras.kubejs;

import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.loading.LoadingModList;

@Mod(KubeJSCompat.MODID)
public class KubeJSCompat {
public static final String MODID = "connectorextras_kubejs_bridge";
private static final String KUBEJS_MODID = "kubejs";
private static final String CONNECTOR_MODID = "connectormod";

public static boolean isEnabled() {
return LoadingModList.get().getModFileById(KUBEJS_MODID) != null && LoadingModList.get().getModFileById(CONNECTOR_MODID) != null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package dev.su5ed.sinytra.connectorextras.kubejs;

import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;

import java.util.List;
import java.util.Set;

public class KubeJSCompatMixinPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String s) {}

@Override
public String getRefMapperConfig() {
return null;
}

@Override
public boolean shouldApplyMixin(String s, String s1) {
return KubeJSCompat.isEnabled();
}

@Override
public void acceptTargets(Set<String> set, Set<String> set1) {

}

@Override
public List<String> getMixins() {
return null;
}

@Override
public void preApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) {

}

@Override
public void postApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package dev.su5ed.sinytra.connectorextras.kubejs;

import dev.architectury.platform.Mod;
import dev.latvian.mods.kubejs.KubeJSPlugin;
import dev.latvian.mods.kubejs.util.KubeJSPlugins;
import dev.su5ed.sinytra.connector.loader.ConnectorEarlyLoader;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.forgespi.language.IModFileInfo;
import net.minecraftforge.forgespi.language.IModInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

public class KubeJSCompatSetup {
public static List<String> loadedMods;
public static List<KubeJSPlugin> fabricPlugins;

public static void initFabricPlugins() {
List<Mod> mods = ConnectorEarlyLoader.getConnectorMods().stream()
.<Mod>map(LoadingModImpl::new)
.toList();
loadedMods = mods.stream().map(Mod::getModId).toList();

KubeJSPlugins.load(mods, FMLEnvironment.dist.isClient());
fabricPlugins = List.copyOf(KubeJSPlugins.getAll());

KubeJSPlugins.forEachPlugin(KubeJSPlugin::init);
KubeJSPlugins.forEachPlugin(KubeJSPlugin::registerEvents);
KubeJSPlugins.forEachPlugin(KubeJSPlugin::initStartup);
}

public static void forForgePluginsOnly(Consumer<KubeJSPlugin> callback) {
KubeJSPlugins.forEachPlugin(plugin -> {
if (!fabricPlugins.contains(plugin)) {
callback.accept(plugin);
}
});
}

private static class LoadingModImpl implements Mod {
private final IModInfo info;

public LoadingModImpl(IModInfo modInfo) {
this.info = modInfo;
}

@Override
@NotNull
public String getModId() {
return info.getModId();
}

@Override
@NotNull
public String getVersion() {
return info.getVersion().toString();
}

@Override
@NotNull
public String getName() {
return info.getDisplayName();
}

@Override
@NotNull
public String getDescription() {
return info.getDescription();
}

@Override
public Optional<String> getLogoFile(int i) {
return this.info.getLogoFile();
}

@Override
public List<Path> getFilePaths() {
return List.of(getFilePath());
}

@Override
public Path getFilePath() {
return this.info.getOwningFile().getFile().getSecureJar().getRootPath();
}

@Override
public Optional<Path> findResource(String... path) {
return Optional.of(this.info.getOwningFile().getFile().findResource(path)).filter(Files::exists);
}

@Override
public Collection<String> getAuthors() {
Optional<String> optional = this.info.getConfig().getConfigElement("authors")
.map(String::valueOf);
return optional.isPresent() ? Collections.singleton(optional.get()) : Collections.emptyList();
}

@Override
public @Nullable Collection<String> getLicense() {
return Collections.singleton(this.info.getOwningFile().getLicense());
}

@Override
public Optional<String> getHomepage() {
return this.info.getConfig().getConfigElement("displayURL")
.map(String::valueOf);
}

@Override
public Optional<String> getSources() {
return Optional.empty();
}

@Override
public Optional<String> getIssueTracker() {
IModFileInfo owningFile = this.info.getOwningFile();
if (owningFile instanceof ModFileInfo info) {
return Optional.ofNullable(info.getIssueURL())
.map(URL::toString);
}
return Optional.empty();
}

@Override
public void registerConfigurationScreen(ConfigurationScreenProvider configurationScreenProvider) {
throw new UnsupportedOperationException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.su5ed.sinytra.connectorextras.kubejs.mixin;

import dev.architectury.platform.Mod;
import dev.latvian.mods.kubejs.KubeJS;
import dev.latvian.mods.kubejs.KubeJSPlugin;
import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompatSetup;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.List;
import java.util.function.Consumer;

@Mixin(KubeJS.class)
public class KubeJSMixin {

@ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Ldev/latvian/mods/kubejs/util/KubeJSPlugins;load(Ljava/util/List;Z)V"))
private List<Mod> removeInitializedMods(List<Mod> mods) {
return mods.stream().filter(m -> !KubeJSCompatSetup.loadedMods.contains(m.getModId())).toList();
}

@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ldev/latvian/mods/kubejs/util/KubeJSPlugins;forEachPlugin(Ljava/util/function/Consumer;)V"))
private void initForgePlugins(Consumer<KubeJSPlugin> callback) {
KubeJSCompatSetup.forForgePluginsOnly(callback);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.su5ed.sinytra.connectorextras.kubejs.mixin;

import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompat;
import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompatSetup;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.GameConfig;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(value = Minecraft.class, priority = 100)
public abstract class MinecraftMixin {
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/lang/Thread;currentThread()Ljava/lang/Thread;"), remap = false)
private void kubejsBridgeEarlyInit(GameConfig gameConfig, CallbackInfo ci) {
if (KubeJSCompat.isEnabled()) {
KubeJSCompatSetup.initFabricPlugins();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.su5ed.sinytra.connectorextras.kubejs.mixin;

import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompat;
import dev.su5ed.sinytra.connectorextras.kubejs.KubeJSCompatSetup;
import net.minecraft.server.Main;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(value = Main.class, priority = 100)
public abstract class ServerMainMixin {
@Inject(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraftforge/server/loading/ServerModLoader;load()V"), remap = false)
private static void kubejsBridgeEarlyInit(CallbackInfo ci) {
if (KubeJSCompat.isEnabled()) {
KubeJSCompatSetup.initFabricPlugins();
}
}
}
40 changes: 40 additions & 0 deletions kubejs-bridge/src/main/resources/META-INF/mods.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
modLoader="javafml"
loaderVersion="[47,)"
license="MIT"
issueTrackerURL="https://github.com/Sinytra/ConnectorExtras/issues"

[[mods]]
modId="connectorextras_kubejs_bridge"
version="${file.jarVersion}"
displayName="Connector Extras KubeJS Bridge"
authors="Su5eD"
displayURL="https://github.com/Sinytra/ConnectorExtras"
description='''
Provides KubeJS plugin support for Fabric mods on Forge
'''
displayTest = 'IGNORE_ALL_VERSION'

[[dependencies.connectorextras_kubejs_bridge]]
modId="forge"
mandatory=true
versionRange="[47,)"
ordering="NONE"
side="BOTH"
[[dependencies.connectorextras_kubejs_bridge]]
modId="minecraft"
mandatory=true
versionRange="[1.20.1,1.21)"
ordering="NONE"
side="BOTH"
[[dependencies.connectorextras_kubejs_bridge]]
modId="kubejs"
mandatory=false
versionRange="[0,)"
ordering="NONE"
side="BOTH"
[[dependencies.connectorextras_kubejs_bridge]]
modId="connectormod"
mandatory=false
versionRange="[0,)"
ordering="NONE"
side="BOTH"
Loading

0 comments on commit f55da37

Please sign in to comment.