Dediserver runs and talks to clients.
This commit is contained in:
parent
506b51f189
commit
689ebd8036
31 changed files with 605 additions and 324 deletions
|
@ -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<String, Object> data)
|
||||
{
|
||||
RUNTIME_DEOBF = (Boolean)data.get("runtimeDeobfuscationEnabled");
|
||||
forgeLocation = (File)data.get("coremodLocation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessTransformerClass()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<T>
|
||||
{
|
||||
public static final ExtensionPoint<BiFunction<Minecraft, GuiScreen, GuiScreen>> GUIFACTORY = new ExtensionPoint<>();
|
||||
public static final ExtensionPoint<Function<Minecraft, IResourcePack>> RESOURCEPACK = new ExtensionPoint<>();
|
||||
public static final ExtensionPoint<BiFunction<Minecraft, ModFileResourcePack, IResourcePack>> RESOURCEPACK = new ExtensionPoint<>();
|
||||
private Class<T> type;
|
||||
|
||||
private ExtensionPoint() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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", "{}");
|
||||
|
|
|
@ -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<Minecraft> client;
|
||||
private static Supplier<MinecraftServer> server;
|
||||
|
||||
LogicalSidedProvider(Function<Supplier<Minecraft>, ?> clientSide, Function<Supplier<MinecraftServer>, ?> serverSide)
|
||||
{
|
||||
this.clientSide = clientSide;
|
||||
this.serverSide = serverSide;
|
||||
}
|
||||
|
||||
public static void setClient(Supplier<Minecraft> client)
|
||||
{
|
||||
LogicalSidedProvider.client = client;
|
||||
}
|
||||
public static void setServer(Supplier<MinecraftServer> server)
|
||||
{
|
||||
LogicalSidedProvider.server = server;
|
||||
}
|
||||
|
||||
|
||||
private final Function<Supplier<Minecraft>, ?> clientSide;
|
||||
private final Function<Supplier<MinecraftServer>, ?> serverSide;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(final LogicalSide side) {
|
||||
return (T)(side==LogicalSide.CLIENT ? clientSide.apply(client) : serverSide.apply(server));
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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<Supplier<Minecraft>, Function<ModContainer, Event>>)c-> mc->new FMLClientInitEvent(c.get(), mc),
|
||||
(Function<Supplier<DedicatedServer>, Function<ModContainer, Event>>)s-> mc->new FMLServerInitEvent(s.get(), mc)),
|
||||
SIDEDINIT((Function<Supplier<Minecraft>, Function<ModContainer, Event>>)c-> mc->new FMLClientInitEvent(c, mc),
|
||||
(Function<Supplier<DedicatedServer>, Function<ModContainer, Event>>)s-> mc->new FMLServerInitEvent(s, mc)),
|
||||
STRIPCHARS((Function<Supplier<Minecraft>, Function<String, String>>)c-> SplashProgress::stripSpecialChars,
|
||||
(Function<Supplier<DedicatedServer>, Function<String, String>>)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<Minecraft> client;
|
||||
private static Supplier<DedicatedServer> server;
|
||||
|
|
|
@ -211,112 +211,118 @@ public class StartupQuery {
|
|||
}
|
||||
|
||||
|
||||
|
||||
public static Consumer<StartupQuery> clientQuery(Supplier<Minecraft> 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<StartupQuery> clientQuery(Supplier<Minecraft> 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<StartupQuery> dedicatedServerQuery(Supplier<DedicatedServer> 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<PendingCommand> 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<StartupQuery> dedicatedServerQuery(Supplier<DedicatedServer> 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<PendingCommand> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<IResourcePack> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<ModFile, ModFileResourcePack> 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<IResourcePack> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<Minecraft> minecraftSupplier;
|
||||
|
||||
public FMLClientInitEvent(Supplier<Minecraft> mc, ModContainer container)
|
||||
{
|
||||
super(container);
|
||||
this.minecraftSupplier = mc;
|
||||
}
|
||||
|
||||
public Supplier<Minecraft> getMinecraftSupplier()
|
||||
{
|
||||
return minecraftSupplier;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<DedicatedServer> serverSupplier;
|
||||
|
||||
public FMLServerInitEvent(Supplier<DedicatedServer> server, ModContainer container)
|
||||
{
|
||||
super(container);
|
||||
this.serverSupplier = server;
|
||||
}
|
||||
|
||||
public Supplier<DedicatedServer> getServerSupplier()
|
||||
{
|
||||
return serverSupplier;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -318,7 +318,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet<?>> 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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Void> 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
|
||||
|
|
|
@ -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<String> 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<Void> 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;
|
||||
}
|
||||
}
|
|
@ -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<String> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<PacketBuffer, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier;
|
||||
private final LogicalSide logicalSide;
|
||||
|
||||
Network(BiFunction<PacketBuffer, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier)
|
||||
NetworkDirection(BiFunction<PacketBuffer, Supplier<NetworkEvent.Context>, NetworkEvent> eventSupplier, LogicalSide logicalSide)
|
||||
{
|
||||
this.eventSupplier = eventSupplier;
|
||||
this.logicalSide = logicalSide;
|
||||
}
|
||||
|
||||
public NetworkEvent getEvent(final PacketBuffer buffer, final Supplier<NetworkEvent.Context> manager) {
|
||||
return this.eventSupplier.apply(buffer, manager);
|
||||
}
|
||||
|
||||
public LogicalSide getLogicalSide()
|
||||
{
|
||||
return logicalSide;
|
||||
}
|
||||
}
|
|
@ -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 <V> ListenableFuture<V> enqueueWork(Runnable runnable) {
|
||||
return (ListenableFuture<V>)LogicalSidedProvider.WORKQUEUE.<IThreadListener>get(getSide().getLogicalSide()).addScheduledTask(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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<String> networkProtocolVersion;
|
||||
private Predicate<String> clientAcceptedVersions;
|
||||
private Predicate<String> serverAcceptedVersions;
|
||||
|
||||
public static ChannelBuilder named(ResourceLocation channelName)
|
||||
{
|
||||
ChannelBuilder builder = new ChannelBuilder();
|
||||
builder.channelName = channelName;
|
||||
return builder;
|
||||
}
|
||||
|
||||
public ChannelBuilder networkProtocolVersion(Supplier<String> networkProtocolVersion)
|
||||
{
|
||||
this.networkProtocolVersion = networkProtocolVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChannelBuilder clientAcceptedVersions(Predicate<String> clientAcceptedVersions)
|
||||
{
|
||||
this.clientAcceptedVersions = clientAcceptedVersions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ChannelBuilder serverAcceptedVersions(Predicate<String> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,4 +61,40 @@ public class SimpleChannel
|
|||
final CPacketCustomPayload payload = new CPacketCustomPayload(instance.getChannelName(), bufIn);
|
||||
Minecraft.getMinecraft().getConnection().sendPacket(payload);
|
||||
}
|
||||
|
||||
public static class MessageBuilder<MSG> {
|
||||
private SimpleChannel channel;
|
||||
private Class<MSG> type;
|
||||
private int id;
|
||||
private BiConsumer<MSG, PacketBuffer> encoder;
|
||||
private Function<PacketBuffer, MSG> decoder;
|
||||
private BiConsumer<MSG, Supplier<NetworkEvent.Context>> consumer;
|
||||
|
||||
public static <MSG> MessageBuilder<MSG> forType(final SimpleChannel channel, final Class<MSG> type, int id) {
|
||||
MessageBuilder<MSG> builder = new MessageBuilder<>();
|
||||
builder.channel = channel;
|
||||
builder.id = id;
|
||||
builder.type = type;
|
||||
return builder;
|
||||
}
|
||||
|
||||
public MessageBuilder<MSG> encoder(BiConsumer<MSG, PacketBuffer> encoder) {
|
||||
this.encoder = encoder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder<MSG> decoder(Function<PacketBuffer, MSG> decoder) {
|
||||
this.decoder = decoder;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageBuilder<MSG> consumer(BiConsumer<MSG, Supplier<NetworkEvent.Context>> consumer) {
|
||||
this.consumer = consumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void add() {
|
||||
this.channel.registerMessage(this.id, this.type, this.encoder, this.decoder, this.consumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <strong>prior</strong> 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<String, Object> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
net.minecraftforge.fml.loading.FMLLaunchProvider
|
||||
net.minecraftforge.fml.loading.FMLDevClientLaunchProvider
|
||||
net.minecraftforge.fml.loading.FMLDevServerLaunchProvider
|
6
src/main/resources/pack.mcmeta
Normal file
6
src/main/resources/pack.mcmeta
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"pack": {
|
||||
"pack_format": 4,
|
||||
"description": "Forge resource pack"
|
||||
}
|
||||
}
|
|
@ -20,7 +20,6 @@
|
|||
package net.minecraftforge.fml.debug;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
|
Loading…
Reference in a new issue