diff --git a/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java b/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java index c1b9626460..1fb035e1ac 100644 --- a/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java +++ b/src/main/java/net/minecraftforge/classloading/FMLForgePlugin.java @@ -22,44 +22,9 @@ package net.minecraftforge.classloading; import java.io.File; import java.util.Map; -import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; - import javax.annotation.Nullable; -public class FMLForgePlugin implements IFMLLoadingPlugin +public class FMLForgePlugin { public static boolean RUNTIME_DEOBF = false; - public static File forgeLocation; - - @Override - public String[] getASMTransformerClass() - { - return new String[0]; - } - - @Override - public String getModContainerClass() - { - return "net.minecraftforge.common.ForgeMod"; - } - - @Override - @Nullable - public String getSetupClass() - { - return null; - } - - @Override - public void injectData(Map data) - { - RUNTIME_DEOBF = (Boolean)data.get("runtimeDeobfuscationEnabled"); - forgeLocation = (File)data.get("coremodLocation"); - } - - @Override - public String getAccessTransformerClass() - { - return null; - } } diff --git a/src/main/java/net/minecraftforge/fml/ExtensionPoint.java b/src/main/java/net/minecraftforge/fml/ExtensionPoint.java index c6d554d647..8351446e2f 100644 --- a/src/main/java/net/minecraftforge/fml/ExtensionPoint.java +++ b/src/main/java/net/minecraftforge/fml/ExtensionPoint.java @@ -22,6 +22,7 @@ package net.minecraftforge.fml; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.IResourcePack; +import net.minecraftforge.fml.client.ModFileResourcePack; import java.util.function.BiFunction; import java.util.function.Function; @@ -29,5 +30,10 @@ import java.util.function.Function; public class ExtensionPoint { public static final ExtensionPoint> GUIFACTORY = new ExtensionPoint<>(); - public static final ExtensionPoint> RESOURCEPACK = new ExtensionPoint<>(); + public static final ExtensionPoint> RESOURCEPACK = new ExtensionPoint<>(); + private Class type; + + private ExtensionPoint() { + } + } diff --git a/src/main/java/net/minecraftforge/fml/LaunchTesting.java b/src/main/java/net/minecraftforge/fml/LaunchTesting.java index 5de4a32561..c8f07a0576 100644 --- a/src/main/java/net/minecraftforge/fml/LaunchTesting.java +++ b/src/main/java/net/minecraftforge/fml/LaunchTesting.java @@ -61,7 +61,7 @@ public class LaunchTesting logcontext.updateLoggers(); System.setProperty("fml.explodedDir", "/home/cpw/projects/mods/inventorysorter/classes"); hackNatives(); - Launcher.main("--launchTarget", "devfmlclient","--gameDir", "projects/run", + Launcher.main("--launchTarget", System.getProperty("target"),"--gameDir", ".", "--accessToken", "blah", "--version", "FMLDev", "--assetIndex", "1.12", "--assetsDir","/home/cpw/.gradle/caches/minecraft/assets", "--userProperties", "{}"); diff --git a/src/main/java/net/minecraftforge/fml/LogicalSidedProvider.java b/src/main/java/net/minecraftforge/fml/LogicalSidedProvider.java new file mode 100644 index 0000000000..d50487c880 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/LogicalSidedProvider.java @@ -0,0 +1,57 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * This library 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 version 2.1 + * of the License. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml; + +import net.minecraft.client.Minecraft; +import net.minecraft.server.MinecraftServer; + +import java.util.function.Function; +import java.util.function.Supplier; + +public enum LogicalSidedProvider +{ + WORKQUEUE((c)->c.get(), (s)->s.get()); + private static Supplier client; + private static Supplier server; + + LogicalSidedProvider(Function, ?> clientSide, Function, ?> serverSide) + { + this.clientSide = clientSide; + this.serverSide = serverSide; + } + + public static void setClient(Supplier client) + { + LogicalSidedProvider.client = client; + } + public static void setServer(Supplier server) + { + LogicalSidedProvider.server = server; + } + + + private final Function, ?> clientSide; + private final Function, ?> serverSide; + + @SuppressWarnings("unchecked") + public T get(final LogicalSide side) { + return (T)(side==LogicalSide.CLIENT ? clientSide.apply(client) : serverSide.apply(server)); + } +} diff --git a/src/main/java/net/minecraftforge/fml/ServerLifecycleHooks.java b/src/main/java/net/minecraftforge/fml/ServerLifecycleHooks.java index 06861d627e..7930cfbd7b 100644 --- a/src/main/java/net/minecraftforge/fml/ServerLifecycleHooks.java +++ b/src/main/java/net/minecraftforge/fml/ServerLifecycleHooks.java @@ -51,6 +51,7 @@ public class ServerLifecycleHooks public static boolean handleServerAboutToStart(final MinecraftServer server) { currentServer = server; + LogicalSidedProvider.setServer(()->server); return !MinecraftForge.EVENT_BUS.post(new FMLServerAboutToStartEvent(server)); } @@ -80,6 +81,7 @@ public class ServerLifecycleHooks { MinecraftForge.EVENT_BUS.post(new FMLServerStoppedEvent()); currentServer = null; + LogicalSidedProvider.setServer(null); CountDownLatch latch = exitLatch; if (latch != null) diff --git a/src/main/java/net/minecraftforge/fml/SidedProvider.java b/src/main/java/net/minecraftforge/fml/SidedProvider.java index cab3cb3bea..32d1a03299 100644 --- a/src/main/java/net/minecraftforge/fml/SidedProvider.java +++ b/src/main/java/net/minecraftforge/fml/SidedProvider.java @@ -33,12 +33,14 @@ import java.util.function.Supplier; public enum SidedProvider { + // All of these need to be careful not to directly dereference the client and server elements in their signatures DATAFIXER(c->c.get().getDataFixer(), s->s.get().getDataFixer()), - SIDEDINIT((Function, Function>)c-> mc->new FMLClientInitEvent(c.get(), mc), - (Function, Function>)s-> mc->new FMLServerInitEvent(s.get(), mc)), + SIDEDINIT((Function, Function>)c-> mc->new FMLClientInitEvent(c, mc), + (Function, Function>)s-> mc->new FMLServerInitEvent(s, mc)), STRIPCHARS((Function, Function>)c-> SplashProgress::stripSpecialChars, (Function, Function>)s-> str->str), - STARTUPQUERY(StartupQuery::clientQuery, StartupQuery::dedicatedServerQuery); + @SuppressWarnings("Convert2MethodRef") // need to not be methodrefs to avoid classloading all of StartupQuery's data + STARTUPQUERY(c->StartupQuery.QueryWrapper.clientQuery(c), s->StartupQuery.QueryWrapper.dedicatedServerQuery(s)); private static Supplier client; private static Supplier server; diff --git a/src/main/java/net/minecraftforge/fml/StartupQuery.java b/src/main/java/net/minecraftforge/fml/StartupQuery.java index 9e84c8e9c6..644c71b6a9 100644 --- a/src/main/java/net/minecraftforge/fml/StartupQuery.java +++ b/src/main/java/net/minecraftforge/fml/StartupQuery.java @@ -211,112 +211,118 @@ public class StartupQuery { } - - public static Consumer clientQuery(Supplier clientSupplier) + public static class QueryWrapper { - return (query) -> { - Minecraft client = clientSupplier.get(); - if (query.getResult() == null) - { - client.displayGuiScreen(new GuiNotification(query)); - } - else - { - client.displayGuiScreen(new GuiConfirmation(query)); - } - - if (query.isSynchronous()) - { - while (client.currentScreen instanceof GuiNotification) + public static Consumer clientQuery(Supplier clientSupplier) + { + return (query) -> { + Minecraft client = clientSupplier.get(); + if (query.getResult() == null) { - if (Thread.interrupted()) { - query.exception = new InterruptedException(); - throw new RuntimeException(); - } - - client.loadingScreen.displayLoadingString(""); - - try - { - Thread.sleep(50); - } catch (InterruptedException ie) { - query.exception = ie; - } + client.displayGuiScreen(new GuiNotification(query)); + } + else + { + client.displayGuiScreen(new GuiConfirmation(query)); } - client.loadingScreen.displayLoadingString(""); // make sure the blank screen is being drawn at the end - } - }; - } - - public static Consumer dedicatedServerQuery(Supplier serverSupplier) - { - return (query) -> { - DedicatedServer server = serverSupplier.get(); - if (query.getResult() == null) - { - LOGGER.warn(SQ, query.getText()); - query.finish(); - } - else - { - String text = query.getText() + - "\n\nRun the command /fml confirm or or /fml cancel to proceed." + - "\nAlternatively start the server with -Dfml.queryResult=confirm or -Dfml.queryResult=cancel to preselect the answer."; - LOGGER.warn(SQ, text); - - if (!query.isSynchronous()) return; // no-op until mc does commands in another thread (if ever) - - boolean done = false; - - while (!done && server.isServerRunning()) + if (query.isSynchronous()) { - if (Thread.interrupted()) + while (client.currentScreen instanceof GuiNotification) { - query.exception = new InterruptedException(); - throw new RuntimeException(); - } - - DedicatedServer dedServer = (DedicatedServer)server; - - // rudimentary command processing, check for fml confirm/cancel and stop commands - synchronized (dedServer.pendingCommandList) - { - for (Iterator it = dedServer.pendingCommandList.iterator(); it.hasNext(); ) + if (Thread.interrupted()) { - String cmd = it.next().command.trim().toLowerCase(); + query.exception = new InterruptedException(); + throw new RuntimeException(); + } - if (cmd.equals("/fml confirm")) - { - LOGGER.info(SQ, "confirmed"); - query.setResult(true); - done = true; - it.remove(); - } - else if (cmd.equals("/fml cancel")) - { - LOGGER.info(SQ, "cancelled"); - query.setResult(false); - done = true; - it.remove(); - } - else if (cmd.equals("/stop")) - { - StartupQuery.abort(); - } + client.loadingScreen.displayLoadingString(""); + + try + { + Thread.sleep(50); + } + catch (InterruptedException ie) + { + query.exception = ie; } } - try - { - Thread.sleep(10L); - } catch (InterruptedException ie) { - query.exception = ie; - } + + client.loadingScreen.displayLoadingString(""); // make sure the blank screen is being drawn at the end } + }; + } - query.finish(); - } - }; + public static Consumer dedicatedServerQuery(Supplier serverSupplier) + { + return (query) -> { + DedicatedServer server = serverSupplier.get(); + if (query.getResult() == null) + { + LOGGER.warn(SQ, query.getText()); + query.finish(); + } + else + { + String text = query.getText() + + "\n\nRun the command /fml confirm or or /fml cancel to proceed." + + "\nAlternatively start the server with -Dfml.queryResult=confirm or -Dfml.queryResult=cancel to preselect the answer."; + LOGGER.warn(SQ, text); + + if (!query.isSynchronous()) return; // no-op until mc does commands in another thread (if ever) + + boolean done = false; + + while (!done && server.isServerRunning()) + { + if (Thread.interrupted()) + { + query.exception = new InterruptedException(); + throw new RuntimeException(); + } + + DedicatedServer dedServer = (DedicatedServer)server; + + // rudimentary command processing, check for fml confirm/cancel and stop commands + synchronized (dedServer.pendingCommandList) + { + for (Iterator it = dedServer.pendingCommandList.iterator(); it.hasNext(); ) + { + String cmd = it.next().command.trim().toLowerCase(); + + if (cmd.equals("/fml confirm")) + { + LOGGER.info(SQ, "confirmed"); + query.setResult(true); + done = true; + it.remove(); + } + else if (cmd.equals("/fml cancel")) + { + LOGGER.info(SQ, "cancelled"); + query.setResult(false); + done = true; + it.remove(); + } + else if (cmd.equals("/stop")) + { + StartupQuery.abort(); + } + } + } + try + { + Thread.sleep(10L); + } + catch (InterruptedException ie) + { + query.exception = ie; + } + } + + query.finish(); + } + }; + } } - } diff --git a/src/main/java/net/minecraftforge/fml/client/ClientHooks.java b/src/main/java/net/minecraftforge/fml/client/ClientHooks.java index 437a89e810..dcfbda51ea 100644 --- a/src/main/java/net/minecraftforge/fml/client/ClientHooks.java +++ b/src/main/java/net/minecraftforge/fml/client/ClientHooks.java @@ -26,8 +26,10 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiWorldSelection; import net.minecraft.client.gui.ServerListEntryNormal; +import net.minecraft.client.multiplayer.GuiConnecting; import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.network.NetworkManager; @@ -36,6 +38,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.world.storage.WorldSummary; import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.StartupQuery; +import net.minecraftforge.fml.client.gui.GuiAccessDenied; import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler; import net.minecraftforge.registries.GameData; import org.apache.logging.log4j.LogManager; @@ -194,4 +197,17 @@ public class ClientHooks } } + public static void connectToServer(GuiScreen guiMultiplayer, ServerData serverEntry) + { + ExtendedServerListData extendedData = serverDataTag.get(serverEntry); + if (extendedData != null && extendedData.isBlocked) + { + Minecraft.getMinecraft().displayGuiScreen(new GuiAccessDenied(guiMultiplayer, serverEntry)); + } + else + { + Minecraft.getMinecraft().displayGuiScreen(new GuiConnecting(guiMultiplayer, Minecraft.getMinecraft(), serverEntry)); + } + } + } diff --git a/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java b/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java index 09808fe505..9b0d32a20a 100644 --- a/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java +++ b/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java @@ -27,6 +27,7 @@ import net.minecraft.client.resources.IResourcePack; import net.minecraft.client.resources.data.MetadataSerializer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.LogicalSidedProvider; import net.minecraftforge.fml.SidedProvider; import net.minecraftforge.fml.VersionChecker; import net.minecraftforge.fml.ModLoader; @@ -43,20 +44,15 @@ public class ClientModLoader private static boolean loading; private static Minecraft mc; - /** - * Mod loading entrypoint for the client - * @param minecraft - * @param defaultResourcePacks - * @param mcResourceManager - * @param metadataSerializer_ - */ public static void begin(final Minecraft minecraft, final List defaultResourcePacks, final IReloadableResourceManager mcResourceManager, MetadataSerializer metadataSerializer_) { loading = true; ClientModLoader.mc = minecraft; SidedProvider.setClient(()->minecraft); + LogicalSidedProvider.setClient(()->minecraft); SplashProgress.start(); ModLoader.get().loadMods(); + ResourcePackLoader.loadResourcePacks(defaultResourcePacks); minecraft.refreshResources(); } diff --git a/src/main/java/net/minecraftforge/fml/client/ModFileResourcePack.java b/src/main/java/net/minecraftforge/fml/client/ModFileResourcePack.java new file mode 100644 index 0000000000..8b7c983201 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/client/ModFileResourcePack.java @@ -0,0 +1,76 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * This library 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 version 2.1 + * of the License. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.client; + +import net.minecraft.client.resources.AbstractResourcePack; +import net.minecraftforge.fml.loading.moddiscovery.ModFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; + +public class ModFileResourcePack extends AbstractResourcePack +{ + private final ModFile modFile; + + public ModFileResourcePack(final ModFile modFile) + { + super(new File("dummy")); + this.modFile = modFile; + } + + public ModFile getModFile() { + return this.modFile; + } + + @Override + public String getPackName() + { + return modFile.getFileName(); + } + + @Override + protected InputStream getInputStreamByName(String name) throws IOException + { + return Files.newInputStream(modFile.getLocator().findPath(modFile, name)); + } + + @Override + protected boolean hasResourceName(String name) + { + return Files.exists(modFile.getLocator().findPath(modFile, name)); + } + + @Override + public Set getResourceDomains() + { + try { + return Files.walk(modFile.getLocator().findPath(modFile, "assets"),1).map(p->p.getFileName().toString()).collect(Collectors.toSet()); + } + catch (IOException e) + { + return Collections.emptySet(); + } + } +} diff --git a/src/main/java/net/minecraftforge/fml/client/ResourcePackLoader.java b/src/main/java/net/minecraftforge/fml/client/ResourcePackLoader.java index 1e75f6c886..c4a1c4deaf 100644 --- a/src/main/java/net/minecraftforge/fml/client/ResourcePackLoader.java +++ b/src/main/java/net/minecraftforge/fml/client/ResourcePackLoader.java @@ -19,12 +19,38 @@ package net.minecraftforge.fml.client; +import net.minecraft.client.resources.AbstractResourcePack; +import net.minecraft.client.resources.FileResourcePack; +import net.minecraft.client.resources.FolderResourcePack; import net.minecraft.client.resources.IResourcePack; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.loading.FMLLoader; +import net.minecraftforge.fml.loading.moddiscovery.ModFile; + +import java.nio.file.Files; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; public class ResourcePackLoader { + private static Map modResourcePacks; + private static AbstractResourcePack forgePack; + public static IResourcePack getResourcePackFor(String modId) { - return null; + return modResourcePacks.get(ModList.get().getModFileById(modId).getFile()); + } + + public static void loadResourcePacks(List resourcePacks) { + modResourcePacks = ModList.get().getModFiles().stream(). + map(mf -> new ModFileResourcePack(mf.getFile())). + collect(Collectors.toMap(ModFileResourcePack::getModFile, Function.identity())); + forgePack = Files.isDirectory(FMLLoader.getForgePath()) ? + new FolderResourcePack(FMLLoader.getForgePath().toFile()) : + new FileResourcePack(FMLLoader.getForgePath().toFile()); + resourcePacks.add(forgePack); + resourcePacks.addAll(modResourcePacks.values()); } } diff --git a/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java b/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java index f784dca3eb..5d6816a4bc 100644 --- a/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java +++ b/src/main/java/net/minecraftforge/fml/common/FMLCommonHandler.java @@ -558,7 +558,7 @@ public class FMLCommonHandler * Also verifies the client has the FML marker. * * @param packet Handshake Packet - * @param manager Network connection + * @param manager NetworkDirection connection * @return True to allow connection, otherwise False. */ public boolean handleServerHandshake(C00Handshake packet, NetworkManager manager) diff --git a/src/main/java/net/minecraftforge/fml/common/event/FMLClientInitEvent.java b/src/main/java/net/minecraftforge/fml/common/event/FMLClientInitEvent.java index 4ec66f31d7..4ab650f85e 100644 --- a/src/main/java/net/minecraftforge/fml/common/event/FMLClientInitEvent.java +++ b/src/main/java/net/minecraftforge/fml/common/event/FMLClientInitEvent.java @@ -22,10 +22,20 @@ package net.minecraftforge.fml.common.event; import net.minecraft.client.Minecraft; import net.minecraftforge.fml.ModContainer; +import java.util.function.Supplier; + public class FMLClientInitEvent extends ModLifecycleEvent { - public FMLClientInitEvent(Minecraft mc, ModContainer container) + private final Supplier minecraftSupplier; + + public FMLClientInitEvent(Supplier mc, ModContainer container) { super(container); + this.minecraftSupplier = mc; + } + + public Supplier getMinecraftSupplier() + { + return minecraftSupplier; } } diff --git a/src/main/java/net/minecraftforge/fml/common/event/FMLServerInitEvent.java b/src/main/java/net/minecraftforge/fml/common/event/FMLServerInitEvent.java index 1b94a35727..39e146d668 100644 --- a/src/main/java/net/minecraftforge/fml/common/event/FMLServerInitEvent.java +++ b/src/main/java/net/minecraftforge/fml/common/event/FMLServerInitEvent.java @@ -19,13 +19,23 @@ package net.minecraftforge.fml.common.event; -import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; import net.minecraftforge.fml.ModContainer; +import java.util.function.Supplier; + public class FMLServerInitEvent extends ModLifecycleEvent { - public FMLServerInitEvent(MinecraftServer server, ModContainer container) + private final Supplier serverSupplier; + + public FMLServerInitEvent(Supplier server, ModContainer container) { super(container); + this.serverSupplier = server; + } + + public Supplier getServerSupplier() + { + return serverSupplier; } } diff --git a/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java b/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java index 50bcd9f4e3..a986127abe 100644 --- a/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java +++ b/src/main/java/net/minecraftforge/fml/common/network/handshake/NetworkDispatcher.java @@ -318,7 +318,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler> im private void kickWithMessage(String message) { - FMLLog.log.error("Network Disconnect: {}", message); + FMLLog.log.error("NetworkDirection Disconnect: {}", message); final TextComponentString TextComponentString = new TextComponentString(message); if (side == Side.CLIENT) { diff --git a/src/main/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java b/src/main/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java index 1e28108462..5203727022 100644 --- a/src/main/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java +++ b/src/main/java/net/minecraftforge/fml/loading/FMLCommonLaunchHandler.java @@ -23,6 +23,8 @@ import cpw.mods.modlauncher.api.IEnvironment; import cpw.mods.modlauncher.api.ITransformingClassLoader; import net.minecraftforge.api.distmarker.Dist; +import java.nio.file.Path; + public abstract class FMLCommonLaunchHandler { public void setup(final IEnvironment environment) @@ -32,8 +34,8 @@ public abstract class FMLCommonLaunchHandler public abstract Dist getDist(); - protected void beforeStart(ITransformingClassLoader launchClassLoader) + protected void beforeStart(ITransformingClassLoader launchClassLoader, Path forgePath) { - FMLLoader.beforeStart(launchClassLoader); + FMLLoader.beforeStart(launchClassLoader, forgePath); } } diff --git a/src/main/java/net/minecraftforge/fml/loading/FMLDevClientLaunchProvider.java b/src/main/java/net/minecraftforge/fml/loading/FMLDevClientLaunchProvider.java index 7bb55eab49..503d400a6f 100644 --- a/src/main/java/net/minecraftforge/fml/loading/FMLDevClientLaunchProvider.java +++ b/src/main/java/net/minecraftforge/fml/loading/FMLDevClientLaunchProvider.java @@ -51,27 +51,32 @@ public class FMLDevClientLaunchProvider extends FMLCommonLaunchHandler implement "net.minecraftforge.fml.common.versioning." ); - @Override - public Path[] identifyTransformationTargets() + private static final Path myPath; + + static { try { - return new Path[] { - Paths.get(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()) - }; + myPath = Paths.get(FMLDevClientLaunchProvider.class.getProtectionDomain().getCodeSource().getLocation().toURI()); } catch (URISyntaxException e) { - throw new RuntimeException("I can't find myself!"); + throw new RuntimeException("HUH?"); } } + @Override + public Path[] identifyTransformationTargets() + { + return new Path[] { myPath }; + } + @Override public Callable launchService(String[] arguments, ITransformingClassLoader launchClassLoader) { return () -> { fmlLog.debug(CORE, "Launching minecraft in {} with arguments {}", launchClassLoader, arguments); - super.beforeStart(launchClassLoader); + super.beforeStart(launchClassLoader, myPath); launchClassLoader.addTargetPackageFilter(cn -> SKIPPACKAGES.stream().noneMatch(cn::startsWith)); Field scl = ClassLoader.class.getDeclaredField("scl"); // Get system class loader scl.setAccessible(true); // Set accessible diff --git a/src/main/java/net/minecraftforge/fml/loading/FMLDevServerLaunchProvider.java b/src/main/java/net/minecraftforge/fml/loading/FMLDevServerLaunchProvider.java new file mode 100644 index 0000000000..86eb28e6cf --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/loading/FMLDevServerLaunchProvider.java @@ -0,0 +1,101 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * This library 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 version 2.1 + * of the License. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.loading; + +import cpw.mods.modlauncher.api.IEnvironment; +import cpw.mods.modlauncher.api.ILaunchHandlerService; +import cpw.mods.modlauncher.api.ITransformingClassLoader; +import net.minecraftforge.api.distmarker.Dist; + +import java.lang.reflect.Field; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Callable; + +import static net.minecraftforge.fml.Logging.CORE; +import static net.minecraftforge.fml.Logging.fmlLog; + +public class FMLDevServerLaunchProvider extends FMLCommonLaunchHandler implements ILaunchHandlerService +{ + @Override + public String name() + { + return "devfmlserver"; + } + + private static final List SKIPPACKAGES = Arrays.asList( + "joptsimple.", "org.lwjgl.", "com.mojang.", "com.google.", + "org.apache.commons.", "io.netty.", "net.minecraftforge.fml.loading.", "net.minecraftforge.fml.language.", + "net.minecraftforge.eventbus.", "it.unimi.dsi.fastutil.", "net.minecraftforge.api.", + "paulscode.sound.", "com.ibm.icu.", "sun.", "gnu.trove.", "com.electronwill.nightconfig.", + "net.minecraftforge.fml.common.versioning." + ); + + private static final Path myPath; + + static + { + try + { + myPath = Paths.get(FMLDevServerLaunchProvider.class.getProtectionDomain().getCodeSource().getLocation().toURI()); + } + catch (URISyntaxException e) + { + throw new RuntimeException("HUH?"); + } + } + + @Override + public Path[] identifyTransformationTargets() + { + return new Path[] { myPath }; + } + + @Override + public Callable launchService(String[] arguments, ITransformingClassLoader launchClassLoader) + { + return () -> { + fmlLog.debug(CORE, "Launching minecraft in {} with arguments {}", launchClassLoader, arguments); + super.beforeStart(launchClassLoader, myPath); + launchClassLoader.addTargetPackageFilter(cn -> SKIPPACKAGES.stream().noneMatch(cn::startsWith)); + Field scl = ClassLoader.class.getDeclaredField("scl"); // Get system class loader + scl.setAccessible(true); // Set accessible + scl.set(null, launchClassLoader.getInstance()); // Update it to your class loader + Thread.currentThread().setContextClassLoader(launchClassLoader.getInstance()); + Class.forName("net.minecraft.server.MinecraftServer", true, launchClassLoader.getInstance()).getMethod("main", String[].class).invoke(null, (Object)arguments); + return null; + }; + } + + @Override + public void setup(IEnvironment environment) + { + fmlLog.debug(CORE, "No jar creation necessary. Launch is dev environment"); + } + + @Override + public Dist getDist() + { + return Dist.DEDICATED_SERVER; + } +} diff --git a/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java b/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java index 7b1893ec8e..396201bae7 100644 --- a/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java +++ b/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java @@ -58,6 +58,7 @@ public class FMLLoader private static ClassLoader launchClassLoader; private static RuntimeDistCleaner runtimeDistCleaner; private static Path gamePath; + private static Path forgePath; static void onInitialLoad(IEnvironment environment, Set otherServices) throws IncompatibleEnvironmentException { @@ -178,9 +179,10 @@ public class FMLLoader return dist; } - public static void beforeStart(ITransformingClassLoader launchClassLoader) + public static void beforeStart(ITransformingClassLoader launchClassLoader, Path forgePath) { FMLLoader.launchClassLoader = launchClassLoader.getInstance(); + FMLLoader.forgePath = forgePath; } @@ -199,4 +201,8 @@ public class FMLLoader { return gamePath; } + + public static Path getForgePath() { + return forgePath; + } } diff --git a/src/main/java/net/minecraftforge/fml/network/Network.java b/src/main/java/net/minecraftforge/fml/network/NetworkDirection.java similarity index 64% rename from src/main/java/net/minecraftforge/fml/network/Network.java rename to src/main/java/net/minecraftforge/fml/network/NetworkDirection.java index 43d77dc685..cc65356aee 100644 --- a/src/main/java/net/minecraftforge/fml/network/Network.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkDirection.java @@ -20,26 +20,33 @@ package net.minecraftforge.fml.network; import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.LogicalSide; import java.util.function.BiFunction; import java.util.function.Supplier; -public enum Network +public enum NetworkDirection { - PLAYSERVER(NetworkEvent.ClientCustomPayloadEvent::new), - PLAYCLIENT(NetworkEvent.ServerCustomPayloadEvent::new), - LOGINSERVER(NetworkEvent.ClientCustomPayloadEvent::new), - LOGINCLIENT(NetworkEvent.ServerCustomPayloadEvent::new); + PLAYSERVER(NetworkEvent.ClientCustomPayloadEvent::new, LogicalSide.CLIENT), + PLAYCLIENT(NetworkEvent.ServerCustomPayloadEvent::new, LogicalSide.SERVER), + LOGINSERVER(NetworkEvent.ClientCustomPayloadEvent::new, LogicalSide.CLIENT), + LOGINCLIENT(NetworkEvent.ServerCustomPayloadEvent::new, LogicalSide.SERVER); private final BiFunction, NetworkEvent> eventSupplier; + private final LogicalSide logicalSide; - Network(BiFunction, NetworkEvent> eventSupplier) + NetworkDirection(BiFunction, NetworkEvent> eventSupplier, LogicalSide logicalSide) { this.eventSupplier = eventSupplier; + this.logicalSide = logicalSide; } public NetworkEvent getEvent(final PacketBuffer buffer, final Supplier manager) { return this.eventSupplier.apply(buffer, manager); } + public LogicalSide getLogicalSide() + { + return logicalSide; + } } diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java b/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java index 0948d4cb97..c452fa6530 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkEvent.java @@ -19,12 +19,15 @@ package net.minecraftforge.fml.network; +import com.google.common.util.concurrent.ListenableFuture; import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.network.INetHandler; import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.NetworkManager; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IThreadListener; import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.LogicalSidedProvider; import java.util.function.Supplier; @@ -74,17 +77,17 @@ public class NetworkEvent extends Event private final INetHandler netHandler; /** - * The {@link Network} this message has been received on + * The {@link NetworkDirection} this message has been received on */ - private final Network side; + private final NetworkDirection side; - Context(NetworkManager netHandler, Network side) + Context(NetworkManager netHandler, NetworkDirection side) { this.netHandler = netHandler.getNetHandler(); this.side = side; } - public Network getSide() { + public NetworkDirection getSide() { return side; } @@ -97,5 +100,10 @@ public class NetworkEvent extends Event { return (NetHandlerPlayClient) netHandler; } + + @SuppressWarnings("unchecked") + public ListenableFuture enqueueWork(Runnable runnable) { + return (ListenableFuture)LogicalSidedProvider.WORKQUEUE.get(getSide().getLogicalSide()).addScheduledTask(runnable); + } } } diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java b/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java index 40503d3895..6ba5dd01ab 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java @@ -62,22 +62,22 @@ public class NetworkHooks public static void onServerCustomPayload(final SPacketCustomPayload packet, final NetworkManager manager) { NetworkRegistry.findTarget(new ResourceLocation(packet.getChannelName())). - ifPresent(ni->ni.dispatch(Network.PLAYSERVER, packet.getBufferData(), manager)); + ifPresent(ni->ni.dispatch(NetworkDirection.PLAYSERVER, packet.getBufferData(), manager)); } public static void onClientCustomPayload(final CPacketCustomPayload packet, final NetworkManager manager) { NetworkRegistry.findTarget(new ResourceLocation(packet.getChannelName())). - ifPresent(ni->ni.dispatch(Network.PLAYCLIENT, packet.getBufferData(), manager)); + ifPresent(ni->ni.dispatch(NetworkDirection.PLAYCLIENT, packet.getBufferData(), manager)); } public static void onServerLoginCustomPayload(final SPacketCustomPayload packet, final NetworkManager manager) { NetworkRegistry.findTarget(new ResourceLocation(packet.getChannelName())). - ifPresent(ni->ni.dispatch(Network.LOGINSERVER, packet.getBufferData(), manager)); + ifPresent(ni->ni.dispatch(NetworkDirection.LOGINSERVER, packet.getBufferData(), manager)); } public static void onClientLoginCustomPayload(final CPacketCustomPayload packet, final NetworkManager manager) { NetworkRegistry.findTarget(new ResourceLocation(packet.getChannelName())). - ifPresent(ni->ni.dispatch(Network.LOGINCLIENT, packet.getBufferData(), manager)); + ifPresent(ni->ni.dispatch(NetworkDirection.LOGINCLIENT, packet.getBufferData(), manager)); } public static void registerServerChannel(NetworkManager manager, C00Handshake packet) diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java b/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java index ad4dbeb045..b6e372906d 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkInstance.java @@ -70,7 +70,7 @@ public class NetworkInstance this.networkEventBus.unregister(object); } - void dispatch(final Network side, final PacketBuffer bufferData, final NetworkManager manager) + void dispatch(final NetworkDirection side, final PacketBuffer bufferData, final NetworkManager manager) { this.networkEventBus.post(side.getEvent(bufferData,()->new NetworkEvent.Context(manager, side))); } diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java b/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java index 5fd89e264b..4fa6b74904 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java @@ -61,8 +61,8 @@ public class NetworkRegistry { final NetworkInstance networkInstance = new NetworkInstance(name, networkProtocolVersion, clientAcceptedVersions, serverAcceptedVersions); if (instances.containsKey(name)) { - LOGGER.error(NETREGISTRY, "Network channel {} already registered.", name); - throw new IllegalArgumentException("Network Channel {"+ name +"} already registered"); + LOGGER.error(NETREGISTRY, "NetworkDirection channel {} already registered.", name); + throw new IllegalArgumentException("NetworkDirection Channel {"+ name +"} already registered"); } instances.put(name, networkInstance); return networkInstance; @@ -72,4 +72,48 @@ public class NetworkRegistry { return Optional.ofNullable(instances.get(resourceLocation)); } + + public static class ChannelBuilder { + private ResourceLocation channelName; + private Supplier networkProtocolVersion; + private Predicate clientAcceptedVersions; + private Predicate serverAcceptedVersions; + + public static ChannelBuilder named(ResourceLocation channelName) + { + ChannelBuilder builder = new ChannelBuilder(); + builder.channelName = channelName; + return builder; + } + + public ChannelBuilder networkProtocolVersion(Supplier networkProtocolVersion) + { + this.networkProtocolVersion = networkProtocolVersion; + return this; + } + + public ChannelBuilder clientAcceptedVersions(Predicate clientAcceptedVersions) + { + this.clientAcceptedVersions = clientAcceptedVersions; + return this; + } + + public ChannelBuilder serverAcceptedVersions(Predicate serverAcceptedVersions) + { + this.serverAcceptedVersions = serverAcceptedVersions; + return this; + } + + private NetworkInstance createNetworkInstance() { + return createInstance(channelName, networkProtocolVersion, clientAcceptedVersions, serverAcceptedVersions); + } + + public SimpleChannel simpleChannel() { + return new SimpleChannel(createNetworkInstance()); + } + + public EventNetworkChannel eventNetworkChannel() { + return new EventNetworkChannel(createNetworkInstance()); + } + } } diff --git a/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java b/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java index 79dfc6296c..a7547a0306 100644 --- a/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java +++ b/src/main/java/net/minecraftforge/fml/network/simple/SimpleChannel.java @@ -61,4 +61,40 @@ public class SimpleChannel final CPacketCustomPayload payload = new CPacketCustomPayload(instance.getChannelName(), bufIn); Minecraft.getMinecraft().getConnection().sendPacket(payload); } + + public static class MessageBuilder { + private SimpleChannel channel; + private Class type; + private int id; + private BiConsumer encoder; + private Function decoder; + private BiConsumer> consumer; + + public static MessageBuilder forType(final SimpleChannel channel, final Class type, int id) { + MessageBuilder builder = new MessageBuilder<>(); + builder.channel = channel; + builder.id = id; + builder.type = type; + return builder; + } + + public MessageBuilder encoder(BiConsumer encoder) { + this.encoder = encoder; + return this; + } + + public MessageBuilder decoder(Function decoder) { + this.decoder = decoder; + return this; + } + + public MessageBuilder consumer(BiConsumer> consumer) { + this.consumer = consumer; + return this; + } + + public void add() { + this.channel.registerMessage(this.id, this.type, this.encoder, this.decoder, this.consumer); + } + } } diff --git a/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java b/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java deleted file mode 100644 index 69a2e2f829..0000000000 --- a/src/main/java/net/minecraftforge/fml/relauncher/IFMLLoadingPlugin.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2018. - * - * This library 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 version 2.1 - * of the License. - * - * This library 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 this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package net.minecraftforge.fml.relauncher; - -import javax.annotation.Nullable; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.Map; - -/** - * The base plugin that provides class name meta information to FML to - * enhance the classloading lifecycle for mods in FML - * - * @author cpw - * - */ -public interface IFMLLoadingPlugin -{ - /** - * Return a list of classes that implements the IClassTransformer interface - * @return a list of classes that implements the IClassTransformer interface - */ - String[] getASMTransformerClass(); - - /** - * Return a class name that implements "ModContainer" for injection into the mod list - * The "getName" function should return a name that other mods can, if need be, - * depend on. - * Trivially, this modcontainer will be loaded before all regular mod containers, - * which means it will be forced to be "immutable" - not susceptible to normal - * sorting behaviour. - * All other mod behaviours are available however- this container can receive and handle - * normal loading events - */ - String getModContainerClass(); - - /** - * Return the class name of an implementor of "IFMLCallHook", that will be run, in the - * main thread, to perform any additional setup this coremod may require. It will be - * run prior to Minecraft starting, so it CANNOT operate on minecraft - * itself. The game will deliberately crash if this code is detected to trigger a - * minecraft class loading - * TODO: implement crash ;) - */ - @Nullable - String getSetupClass(); - - /** - * Inject coremod data into this coremod - * This data includes: - * "mcLocation" : the location of the minecraft directory, - * "coremodList" : the list of coremods - * "coremodLocation" : the file this coremod loaded from, - */ - void injectData(Map data); - - /** - * Return an optional access transformer class for this coremod. It will be injected post-deobf - * so ensure your ATs conform to the new srgnames scheme. - * @return the name of an access transformer class or null if none is provided - */ - String getAccessTransformerClass(); - - /** - * Annotate your load plugin with a list of package prefixes that will *not* be - * processed by the ASM transformation stack. - * - * Your plugin, and any transformers should *definitely* be in this list, because - * otherwise you can face problems with the classloader trying to transform classes - * with your transformer, whilst it is *loading* your transformer. Not pretty. - * - * @author cpw - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - @interface TransformerExclusions - { - String[] value() default ""; - } - - /** - * Use this to target a specific minecraft version for your coremod. It will refuse to load with an error if - * minecraft is not this exact version. - * - * @author cpw - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - @interface MCVersion - { - String value() default ""; - } - - /** - * Name this coremod something other than the "short class name" - * @author cpw - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - @interface Name - { - String value() default ""; - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - @interface DependsOn - { - String[] value() default {}; - } - - /** - * A simple sorting index, interleaved with other tweakers from other sources, as well as FML - * @author cpw - * - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.TYPE) - @interface SortingIndex - { - int value() default 0; - } - -} diff --git a/src/main/java/net/minecraftforge/fml/server/ServerModLoader.java b/src/main/java/net/minecraftforge/fml/server/ServerModLoader.java new file mode 100644 index 0000000000..edf818c9a7 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/server/ServerModLoader.java @@ -0,0 +1,40 @@ +/* + * Minecraft Forge + * Copyright (c) 2018. + * + * This library 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 version 2.1 + * of the License. + * + * This library 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 this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.fml.server; + +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraftforge.fml.LogicalSidedProvider; +import net.minecraftforge.fml.ModLoader; +import net.minecraftforge.fml.SidedProvider; + +public class ServerModLoader +{ + private static DedicatedServer server; + public static void begin(DedicatedServer dedicatedServer) { + ServerModLoader.server = dedicatedServer; + SidedProvider.setServer(()->dedicatedServer); + LogicalSidedProvider.setServer(()->dedicatedServer); + ModLoader.get().loadMods(); + } + + public static void end() { + ModLoader.get().finishMods(); + } +} diff --git a/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService index 0ee4f188fc..eb484bf441 100644 --- a/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService +++ b/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService @@ -1,2 +1,3 @@ net.minecraftforge.fml.loading.FMLLaunchProvider -net.minecraftforge.fml.loading.FMLDevClientLaunchProvider \ No newline at end of file +net.minecraftforge.fml.loading.FMLDevClientLaunchProvider +net.minecraftforge.fml.loading.FMLDevServerLaunchProvider \ No newline at end of file diff --git a/src/main/resources/assets/forge/lang/en_US.lang b/src/main/resources/assets/forge/lang/en_us.lang similarity index 100% rename from src/main/resources/assets/forge/lang/en_US.lang rename to src/main/resources/assets/forge/lang/en_us.lang diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100644 index 0000000000..66a82f62ed --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 4, + "description": "Forge resource pack" + } +} \ No newline at end of file diff --git a/src/test/java/net/minecraftforge/fml/debug/FaultyCoreMod.java b/src/test/java/net/minecraftforge/fml/debug/FaultyCoreMod.java index a88b7a2506..c55dbd6514 100644 --- a/src/test/java/net/minecraftforge/fml/debug/FaultyCoreMod.java +++ b/src/test/java/net/minecraftforge/fml/debug/FaultyCoreMod.java @@ -20,7 +20,6 @@ package net.minecraftforge.fml.debug; import net.minecraft.launchwrapper.IClassTransformer; -import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import java.util.Map;