diff --git a/fml/src/main/java/net/minecraftforge/fml/common/DummyModContainer.java b/fml/src/main/java/net/minecraftforge/fml/common/DummyModContainer.java index d2c567ff0..88b171c36 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/DummyModContainer.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/DummyModContainer.java @@ -200,4 +200,10 @@ public class DummyModContainer implements ModContainer { return ImmutableList.of(); } + + @Override + public boolean shouldLoadInEnvironment() + { + return true; + } } diff --git a/fml/src/main/java/net/minecraftforge/fml/common/FMLModContainer.java b/fml/src/main/java/net/minecraftforge/fml/common/FMLModContainer.java index e4e6ae441..1b6bb1914 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/FMLModContainer.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/FMLModContainer.java @@ -39,6 +39,7 @@ import net.minecraftforge.fml.common.versioning.ArtifactVersion; import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion; import net.minecraftforge.fml.common.versioning.VersionParser; import net.minecraftforge.fml.common.versioning.VersionRange; +import net.minecraftforge.fml.relauncher.Side; import org.apache.logging.log4j.Level; @@ -611,4 +612,30 @@ public class FMLModContainer implements ModContainer { return candidate.getContainedPackages(); } + + @Override + public boolean shouldLoadInEnvironment() + { + boolean clientSideOnly = (Boolean)this.descriptor.get("clientSideOnly"); + boolean serverSideOnly = (Boolean)this.descriptor.get("serverSideOnly"); + + if (clientSideOnly && serverSideOnly) + throw new RuntimeException("Mod annotation claims to be both client and server side only!"); + + Side side = FMLCommonHandler.instance().getSide(); + + if (clientSideOnly && side != Side.CLIENT) + { + FMLLog.info("Disabling mod %d it is client side only.", getModId()); + return false; + } + + if (serverSideOnly && side != Side.SERVER) + { + FMLLog.info("Disabling mod %d it is server side only.", getModId()); + return false; + } + + return true; + } } diff --git a/fml/src/main/java/net/minecraftforge/fml/common/InjectedModContainer.java b/fml/src/main/java/net/minecraftforge/fml/common/InjectedModContainer.java index f5e6e8d56..af91db153 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/InjectedModContainer.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/InjectedModContainer.java @@ -201,4 +201,10 @@ public class InjectedModContainer implements ModContainer { return wrappedContainer.getOwnedPackages(); } + + @Override + public boolean shouldLoadInEnvironment() + { + return true; + } } diff --git a/fml/src/main/java/net/minecraftforge/fml/common/Mod.java b/fml/src/main/java/net/minecraftforge/fml/common/Mod.java index de2925556..ac51b406a 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/Mod.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/Mod.java @@ -89,9 +89,22 @@ public @interface Mod */ boolean useMetadata() default false; + /** + * If true, this mod will not be loaded on the Dedicated Server environment. + * Will crash if both serverSideOnly and clientSideOnly are set to true. + */ + boolean clientSideOnly() default false; + + /** + * If true, this mod will not be loaded on the Client environment. + * Will crash if both serverSideOnly and clientSideOnly are set to true. + */ + boolean serverSideOnly() default false; + /** * The acceptable range of minecraft versions that this mod will load and run in - * The default ("empty string") indicates that only the current minecraft version is acceptable. + * The default ("empty string") indicates that the currently RUNNING minecraft version is acceptable. + * This means ANY version that the end user adds the mod to. Modders PLEASS set this. * FML will refuse to run with an error if the minecraft version is not in this range across all mods. * @return A version range as specified by the maven version range specification or the empty string */ diff --git a/fml/src/main/java/net/minecraftforge/fml/common/ModContainer.java b/fml/src/main/java/net/minecraftforge/fml/common/ModContainer.java index 984b89993..dde8ddef5 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/ModContainer.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/ModContainer.java @@ -147,4 +147,6 @@ public interface ModContainer String getGuiClassName(); List getOwnedPackages(); + + boolean shouldLoadInEnvironment(); } diff --git a/fml/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java b/fml/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java index db2cd064e..6b1a1240a 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/ModContainerFactory.java @@ -32,7 +32,7 @@ public class ModContainerFactory public static Map> modTypes = Maps.newHashMap(); private static Pattern modClass = Pattern.compile(".*(\\.|)(mod\\_[^\\s$]+)$"); private static ModContainerFactory INSTANCE = new ModContainerFactory(); - + private ModContainerFactory() { // We always know about Mod type registerContainerType(Type.getType(Mod.class), FMLModContainer.class); @@ -40,7 +40,7 @@ public class ModContainerFactory public static ModContainerFactory instance() { return INSTANCE; } - + public void registerContainerType(Type type, Class container) { try { @@ -76,7 +76,13 @@ public class ModContainerFactory { FMLLog.fine("Identified a mod of type %s (%s) - loading", ann.getASMType(), className); try { - return modTypes.get(ann.getASMType()).newInstance(className, container, ann.getValues()); + ModContainer ret = modTypes.get(ann.getASMType()).newInstance(className, container, ann.getValues()); + if (!ret.shouldLoadInEnvironment()) + { + FMLLog.fine("Skipping mod %s, container opted to not load.", className); + return null; + } + return ret; } catch (Exception e) { FMLLog.log(Level.ERROR, e, "Unable to construct %s container", ann.getASMType().getClassName()); return null;