Well, it works, for a game, now.

This commit is contained in:
cpw 2018-06-21 15:37:32 -04:00 committed by LexManos
parent 06b16aaa19
commit d0ab0e166c
208 changed files with 2328 additions and 5883 deletions

View File

@ -40,7 +40,7 @@ public class FMLForgePlugin implements IFMLLoadingPlugin
@Override
public String getModContainerClass()
{
return "net.minecraftforge.common.ForgeModContainer";
return "net.minecraftforge.common.ForgeMod";
}
@Override

View File

@ -270,7 +270,7 @@ public class CloudRenderer implements ISelectiveResourceReloadListener
public void checkSettings()
{
boolean newEnabled = ForgeModContainer.forgeCloudsEnabled
boolean newEnabled = ForgeMod.forgeCloudsEnabled
&& mc.gameSettings.shouldRenderClouds() != 0
&& mc.world != null
&& mc.world.provider.isSurfaceWorld();
@ -489,4 +489,29 @@ public class CloudRenderer implements ISelectiveResourceReloadListener
reloadTextures();
}
}
private static CloudRenderer cloudRenderer;
private static CloudRenderer getCloudRenderer()
{
if (cloudRenderer == null)
cloudRenderer = new CloudRenderer();
return cloudRenderer;
}
public static void updateCloudSettings()
{
getCloudRenderer().checkSettings();
}
public static boolean renderClouds(int cloudTicks, float partialTicks, WorldClient world, Minecraft client)
{
IRenderHandler renderer = world.provider.getCloudRenderer();
if (renderer != null)
{
renderer.render(partialTicks, world, client);
return true;
}
return getCloudRenderer().render(cloudTicks, partialTicks);
}
}

View File

@ -125,7 +125,7 @@ import net.minecraftforge.client.model.animation.Animation;
import net.minecraftforge.client.resource.IResourceType;
import net.minecraftforge.client.resource.SelectiveReloadStateHandler;
import net.minecraftforge.client.resource.VanillaResourceType;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.model.IModelPart;
@ -284,7 +284,7 @@ public class ForgeHooksClient
skyInit = true;
GameSettings settings = Minecraft.getMinecraft().gameSettings;
int[] ranges = ForgeModContainer.blendRanges;
int[] ranges = ForgeMod.blendRanges;
int distance = 0;
if (settings.fancyGraphics && ranges.length > 0)
{

View File

@ -19,13 +19,13 @@
package net.minecraftforge.client;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class IRenderHandler
{
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public abstract void render(float partialTicks, WorldClient world, Minecraft mc);
}

View File

@ -24,6 +24,8 @@ import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.InventoryEffectRenderer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.input.Mouse;
import net.minecraft.client.gui.GuiButton;
@ -32,15 +34,13 @@ import net.minecraft.client.gui.ScaledResolution;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
/**
* Event classes for GuiScreen events.
*
* @author bspkrs
*/
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public class GuiScreenEvent extends Event
{
private final GuiScreen gui;

View File

@ -31,7 +31,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.ConfigElement;
@ -50,7 +50,7 @@ import net.minecraftforge.fml.client.config.GuiConfigEntries.BooleanEntry;
import net.minecraftforge.fml.client.config.IConfigElement;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.ModContainer;
import static net.minecraftforge.common.ForgeModContainer.VERSION_CHECK_CAT;
import static net.minecraftforge.common.ForgeMod.VERSION_CHECK_CAT;
/**
* This is the base GuiConfig screen class that all the other Forge-specific config screens will be called from.
@ -87,8 +87,8 @@ import static net.minecraftforge.common.ForgeModContainer.VERSION_CHECK_CAT;
* - etc.
*
* Other things to check out:
* ForgeModContainer.syncConfig()
* ForgeModContainer.onConfigChanged()
* ForgeMod.syncConfig()
* ForgeMod.onConfigChanged()
* ForgeChunkManager.syncConfigDefaults()
* ForgeChunkManager.loadConfiguration()
*/
@ -141,10 +141,10 @@ public class ForgeGuiFactory implements IModGuiFactory
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed. The parent
// GuiConfig object's entryList will also be refreshed to reflect the changes.
return new GuiConfig(this.owningScreen,
(new ConfigElement(ForgeModContainer.getConfig().getCategory(Configuration.CATEGORY_GENERAL))).getChildElements(),
(new ConfigElement(ForgeMod.getConfig().getCategory(Configuration.CATEGORY_GENERAL))).getChildElements(),
this.owningScreen.modID, Configuration.CATEGORY_GENERAL, this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
this.configElement.requiresMcRestart() || this.owningScreen.allRequireMcRestart,
GuiConfig.getAbridgedConfigPath(ForgeModContainer.getConfig().toString()));
GuiConfig.getAbridgedConfigPath(ForgeMod.getConfig().toString()));
}
}
@ -165,10 +165,10 @@ public class ForgeGuiFactory implements IModGuiFactory
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed. The parent
// GuiConfig object's entryList will also be refreshed to reflect the changes.
return new GuiConfig(this.owningScreen,
(new ConfigElement(ForgeModContainer.getConfig().getCategory(Configuration.CATEGORY_CLIENT))).getChildElements(),
(new ConfigElement(ForgeMod.getConfig().getCategory(Configuration.CATEGORY_CLIENT))).getChildElements(),
this.owningScreen.modID, Configuration.CATEGORY_CLIENT, this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
this.configElement.requiresMcRestart() || this.owningScreen.allRequireMcRestart,
GuiConfig.getAbridgedConfigPath(ForgeModContainer.getConfig().toString()));
GuiConfig.getAbridgedConfigPath(ForgeMod.getConfig().toString()));
}
}
@ -216,18 +216,18 @@ public class ForgeGuiFactory implements IModGuiFactory
@Override
protected GuiScreen buildChildScreen()
{
ConfigCategory cfg = ForgeModContainer.getConfig().getCategory(VERSION_CHECK_CAT);
ConfigCategory cfg = ForgeMod.getConfig().getCategory(VERSION_CHECK_CAT);
Map<String, Property> values = new HashMap<String, Property>(cfg.getValues());
values.remove("Global");
Property global = ForgeModContainer.getConfig().get(VERSION_CHECK_CAT, "Global", true);
Property global = ForgeMod.getConfig().get(VERSION_CHECK_CAT, "Global", true);
List<Property> props = new ArrayList<Property>();
for (ModContainer mod : ForgeVersion.gatherMods().keySet())
{
values.remove(mod.getModId());
props.add(ForgeModContainer.getConfig().get(VERSION_CHECK_CAT, mod.getModId(), true)); //Get or make the value in the config
props.add(ForgeMod.getConfig().get(VERSION_CHECK_CAT, mod.getModId(), true)); //Get or make the value in the config
}
props.addAll(values.values()); // Add any left overs from the config
props.sort(Comparator.comparing(Property::getName));
@ -244,7 +244,7 @@ public class ForgeGuiFactory implements IModGuiFactory
return new GuiConfig(this.owningScreen,
list,
this.owningScreen.modID, VERSION_CHECK_CAT, true, true,
GuiConfig.getAbridgedConfigPath(ForgeModContainer.getConfig().toString()));
GuiConfig.getAbridgedConfigPath(ForgeMod.getConfig().toString()));
}
}

View File

@ -25,15 +25,15 @@ import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.ForgeVersion.Status;
import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.client.ClientModLoader;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public class NotificationModUpdateScreen extends GuiScreen
{
@ -64,7 +64,7 @@ public class NotificationModUpdateScreen extends GuiScreen
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks)
{
if (showNotification == null || !showNotification.shouldDraw() || ForgeModContainer.disableVersionCheck)
if (showNotification == null || !showNotification.shouldDraw() || ForgeMod.disableVersionCheck)
{
return;
}

View File

@ -20,7 +20,7 @@
package net.minecraftforge.client.model;
import java.util.function.Function;
import java.util.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@ -36,7 +36,7 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import org.apache.commons.lang3.tuple.Pair;
@ -201,7 +201,7 @@ final class FancyMissingModel implements IModel
case HEAD:
break;
case GUI:
if (ForgeModContainer.zoomInMissingModelTextInGui)
if (ForgeMod.zoomInMissingModelTextInGui)
{
transform = new TRSRTransformation(null, new Quat4f(1, 1, 1, 1), new Vector3f(4, 4, 4), null);
big = false;

View File

@ -72,7 +72,7 @@ import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.IRegistry;
import net.minecraftforge.client.model.animation.AnimationItemOverrideList;
import net.minecraftforge.client.model.animation.ModelBlockAnimation;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.Models;
import net.minecraftforge.common.model.TRSRTransformation;
@ -81,7 +81,6 @@ import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.Properties;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fml.client.ClientModLoader;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.ProgressManager;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;

View File

@ -30,7 +30,7 @@ import net.minecraft.client.renderer.color.BlockColors;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeMod;
public class ForgeBlockModelRenderer extends BlockModelRenderer
{
@ -51,7 +51,7 @@ public class ForgeBlockModelRenderer extends BlockModelRenderer
@Override
public boolean renderModelFlat(IBlockAccess world, IBakedModel model, IBlockState state, BlockPos pos, BufferBuilder buffer, boolean checkSides, long rand)
{
if(ForgeModContainer.forgeLightPipelineEnabled)
if(ForgeMod.forgeLightPipelineEnabled)
{
if(buffer != lastRendererFlat.get())
{
@ -72,7 +72,7 @@ public class ForgeBlockModelRenderer extends BlockModelRenderer
@Override
public boolean renderModelSmooth(IBlockAccess world, IBakedModel model, IBlockState state, BlockPos pos, BufferBuilder buffer, boolean checkSides, long rand)
{
if(ForgeModContainer.forgeLightPipelineEnabled)
if(ForgeMod.forgeLightPipelineEnabled)
{
if(buffer != lastRendererSmooth.get())
{

View File

@ -57,12 +57,17 @@ import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldServerMulti;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import javax.annotation.Nullable;
public class DimensionManager
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker DIMMGR = MarkerManager.getMarker("DIMS");
private static class Dimension
{
private final DimensionType type;
@ -187,11 +192,11 @@ public class DimensionManager
int leakCount = leakedWorlds.count(System.identityHashCode(w));
if (leakCount == 5)
{
FMLLog.log.debug("The world {} ({}) may have leaked: first encounter (5 occurrences).\n", Integer.toHexString(System.identityHashCode(w)), w.getWorldInfo().getWorldName());
LOGGER.debug(DIMMGR,"The world {} ({}) may have leaked: first encounter (5 occurrences).\n", Integer.toHexString(System.identityHashCode(w)), w.getWorldInfo().getWorldName());
}
else if (leakCount % 5 == 0)
{
FMLLog.log.debug("The world {} ({}) may have leaked: seen {} times.\n", Integer.toHexString(System.identityHashCode(w)), w.getWorldInfo().getWorldName(), leakCount);
LOGGER.debug(DIMMGR,"The world {} ({}) may have leaked: seen {} times.\n", Integer.toHexString(System.identityHashCode(w)), w.getWorldInfo().getWorldName(), leakCount);
}
}
}
@ -210,13 +215,13 @@ public class DimensionManager
worlds.put(id, world);
weakWorldMap.put(world, world);
server.worldTickTimes.put(id, new long[100]);
FMLLog.log.info("Loading dimension {} ({}) ({})", id, world.getWorldInfo().getWorldName(), world.getMinecraftServer());
LOGGER.info(DIMMGR,"Loading dimension {} ({}) ({})", id, world.getWorldInfo().getWorldName(), world.getMinecraftServer());
}
else
{
worlds.remove(id);
server.worldTickTimes.remove(id);
FMLLog.log.info("Unloading dimension {}", id);
LOGGER.info(DIMMGR,"Unloading dimension {}", id);
}
ArrayList<WorldServer> tmp = new ArrayList<WorldServer>();
@ -253,7 +258,7 @@ public class DimensionManager
}
catch (Exception e)
{
FMLLog.log.error("Cannot Hotload Dim: {}", dim, e);
LOGGER.error(DIMMGR,"Cannot Hotload Dim: {}", dim, e);
return; // If a provider hasn't been registered then we can't hotload the dim
}
MinecraftServer mcServer = overworld.getMinecraftServer();
@ -321,7 +326,7 @@ public class DimensionManager
}
catch (Exception e)
{
FMLLog.log.error("An error occurred trying to create an instance of WorldProvider {} ({})",
LOGGER.error(DIMMGR,"An error occurred trying to create an instance of WorldProvider {} ({})",
dim, getProviderType(dim), e);
throw new RuntimeException(e);
}
@ -357,7 +362,7 @@ public class DimensionManager
if (unloadQueue.add(id))
{
FMLLog.log.debug("Queueing dimension {} to unload", id);
LOGGER.debug(DIMMGR,"Queueing dimension {} to unload", id);
}
}
@ -376,7 +381,7 @@ public class DimensionManager
{
int id = queueIterator.nextInt();
Dimension dimension = dimensions.get(id);
if (dimension.ticksWaited < ForgeModContainer.dimensionUnloadQueueDelay)
if (dimension.ticksWaited < ForgeMod.dimensionUnloadQueueDelay)
{
dimension.ticksWaited++;
continue;
@ -387,7 +392,7 @@ public class DimensionManager
// Don't unload the world if the status changed
if (w == null || !canUnloadWorld(w))
{
FMLLog.log.debug("Aborting unload for dimension {} as status changed", id);
LOGGER.debug(DIMMGR,"Aborting unload for dimension {} as status changed", id);
continue;
}
try
@ -396,7 +401,7 @@ public class DimensionManager
}
catch (MinecraftException e)
{
FMLLog.log.error("Caught an exception while saving all chunks:", e);
LOGGER.error(DIMMGR,"Caught an exception while saving all chunks:", e);
}
finally
{

View File

@ -49,6 +49,7 @@ import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.fml.ServerLifecycleHooks;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
@ -626,7 +627,7 @@ public class ForgeChunkManager
dormantChunkCache.remove(world);
}
// integrated server is shutting down
if (!FMLCommonHandler.instance().getMinecraftServerInstance().isServerRunning())
if (!ServerLifecycleHooks.getCurrentServer().isServerRunning())
{
playerTickets.clear();
tickets.clear();

View File

@ -24,13 +24,16 @@ import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -114,7 +117,6 @@ import net.minecraft.world.storage.loot.LootEntry;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraft.world.storage.loot.LootTableManager;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.DifficultyChangeEvent;
@ -142,13 +144,17 @@ import net.minecraftforge.event.entity.player.AdvancementEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.NoteBlockEvent;
import net.minecraftforge.fluids.IFluidBlock;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.LoaderState;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher.ConnectionType;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.network.ConnectionType;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
@ -157,10 +163,15 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
public class ForgeHooks
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker FORGEHOOKS = MarkerManager.getMarker("FORGEHOOKS");
//TODO: Loot tables?
static class SeedEntry extends WeightedRandom.Item
{
@ -645,7 +656,7 @@ public class ForgeHooks
{
boolean isSpectator = (entity instanceof EntityPlayer && ((EntityPlayer)entity).isSpectator());
if (isSpectator) return false;
if (!ForgeModContainer.fullBoundingBoxLadders)
if (!ForgeMod.fullBoundingBoxLadders)
{
return state.getBlock().isLadder(state, world, pos, entity);
}
@ -1304,13 +1315,10 @@ public class ForgeHooks
public static boolean loadAdvancements(Map<ResourceLocation, Advancement.Builder> map)
{
boolean errored = false;
setActiveModContainer(null);
//Loader.instance().getActiveModList().forEach((mod) -> loadFactories(mod));
for (ModContainer mod : Loader.instance().getActiveModList())
for (ModFileInfo mod : ModList.get().getModFiles())
{
errored |= !loadAdvancements(map, mod);
errored |= !loadAdvancements(map, mod.getFile());
}
setActiveModContainer(null);
return errored;
}
@ -1326,7 +1334,7 @@ public class ForgeHooks
return null;
}
private static void setActiveModContainer(ModContainer mod)
private static boolean loadAdvancements(Map<ResourceLocation, Advancement.Builder> map, ModFile mod)
{
if (Loader.instance().getLoaderState() != LoaderState.NOINIT) //Unit Tests..
Loader.instance().setActiveModContainer(mod);
@ -1357,12 +1365,12 @@ public class ForgeHooks
}
catch (JsonParseException jsonparseexception)
{
FMLLog.log.error("Parsing error loading built-in advancement " + key, (Throwable)jsonparseexception);
LOGGER.error("Parsing error loading built-in advancement " + key, (Throwable)jsonparseexception);
return false;
}
catch (IOException ioexception)
{
FMLLog.log.error("Couldn't read advancement " + key + " from " + file, (Throwable)ioexception);
LOGGER.error("Couldn't read advancement " + key + " from " + file, (Throwable)ioexception);
return false;
}
finally
@ -1385,13 +1393,11 @@ public class ForgeHooks
if (type == ConnectionType.VANILLA)
{
IForgeRegistry<IRecipe> vanilla = RegistryManager.VANILLA.getRegistry(IRecipe.class);
if (recipes.size() > 0)
recipes = recipes.stream().filter(e -> vanilla.containsValue(e)).collect(Collectors.toList());
if (display.size() > 0)
display = display.stream().filter(e -> vanilla.containsValue(e)).collect(Collectors.toList());
recipes = recipes.stream().filter(vanilla::containsValue).collect(Collectors.toList());
display = display.stream().filter(vanilla::containsValue).collect(Collectors.toList());
}
if (recipes.size() > 0 || display.size() > 0)
if (!recipes.isEmpty() || !display.isEmpty())
connection.sendPacket(new SPacketRecipeBook(state, recipes, display, isGuiOpen, isFilteringCraftable));
}

View File

@ -24,6 +24,7 @@ import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.WorldServer;
import net.minecraftforge.client.CloudRenderer;
import net.minecraftforge.common.util.FakePlayerFactory;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.world.WorldEvent;
@ -93,7 +94,7 @@ public class ForgeInternalHandler
public void checkSettings(ClientTickEvent event)
{
if (event.phase == Phase.END)
FMLClientHandler.instance().updateCloudSettings();
CloudRenderer.updateCloudSettings();
}
}

View File

@ -0,0 +1,456 @@
/*
* Minecraft Forge
* Copyright (c) 2016.
*
* 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.common;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.biome.Biome;
import static net.minecraftforge.common.config.Configuration.CATEGORY_CLIENT;
import static net.minecraftforge.common.config.Configuration.CATEGORY_GENERAL;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.minecraftforge.fml.ModLoadingClassLoader;
import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.WorldPersistenceHooks;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.fml.javafmlmod.ModLoadingContext;
import net.minecraftforge.fml.loading.DefaultModInfos;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.item.Item;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.StatList;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.common.model.animation.CapabilityAnimation;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.RegistryEvent.MissingMappings;
import net.minecraftforge.event.terraingen.DeferredBiomeDecorator;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.fluids.UniversalBucket;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.RecipeSorter;
import net.minecraftforge.server.command.ForgeCommand;
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
import net.minecraftforge.fml.common.event.FMLModIdMappingEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
{
public static final String VERSION_CHECK_CAT = "version_checking";
public static int clumpingThreshold = 64;
public static boolean removeErroringEntities = false;
public static boolean removeErroringTileEntities = false;
public static boolean fullBoundingBoxLadders = false;
public static double zombieSummonBaseChance = 0.1;
public static int[] blendRanges = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34 };
public static float zombieBabyChance = 0.05f;
public static boolean shouldSortRecipies = true;
public static boolean disableVersionCheck = false;
public static boolean forgeLightPipelineEnabled = true;
@Deprecated // TODO remove in 1.13
public static boolean replaceVanillaBucketModel = true;
public static boolean zoomInMissingModelTextInGui = false;
public static boolean forgeCloudsEnabled = true;
public static boolean disableStairSlabCulling = false; // Also known as the "DontCullStairsBecauseIUseACrappyTexturePackThatBreaksBasicBlockShapesSoICantTrustBasicBlockCulling" flag
public static boolean alwaysSetupTerrainOffThread = false; // In RenderGlobal.setupTerrain, always force the chunk render updates to be queued to the thread
public static int dimensionUnloadQueueDelay = 0;
public static boolean logCascadingWorldGeneration = true; // see Chunk#logCascadingWorldGeneration()
public static boolean fixVanillaCascading = false; // There are various places in vanilla that cause cascading worldgen. Enabling this WILL change where blocks are placed to prevent this.
// DO NOT contact Forge about worldgen not 'matching' vanilla if this flag is set.
static final Logger log = LogManager.getLogger(ForgeVersion.MOD_ID);
private static Configuration config;
private static ForgeMod INSTANCE;
public static ForgeMod getInstance()
{
return INSTANCE;
}
private URL updateJSONUrl = null;
public UniversalBucket universalBucket;
public ForgeMod()
{
INSTANCE = this;
ModLoadingContext.get().getModEventBus().addListener(this::preInit);
ModLoadingContext.get().getModEventBus().addListener(this::postInit);
ModLoadingContext.get().getModEventBus().addListener(this::onAvailable);
}
public static Configuration getConfig()
{
return config;
}
private static void remapGeneralPropertyToClient(String key)
{
ConfigCategory GENERAL = config.getCategory(CATEGORY_GENERAL);
if (GENERAL.containsKey(key))
{
FMLLog.log.debug("Remapping property {} from category general to client", key);
Property property = GENERAL.get(key);
GENERAL.remove(key);
config.getCategory(CATEGORY_CLIENT).put(key, property);
}
}
/**
* Synchronizes the local fields with the values in the Configuration object.
*/
private static void syncConfig(boolean load)
{
// By adding a property order list we are defining the order that the properties will appear both in the config file and on the GUIs.
// Property order lists are defined per-ConfigCategory.
List<String> propOrder = new ArrayList<String>();
if (!config.isChild)
{
if (load)
{
config.load();
}
Property enableGlobalCfg = config.get(Configuration.CATEGORY_GENERAL, "enableGlobalConfig", false).setShowInGui(false);
if (enableGlobalCfg.getBoolean(false))
{
Configuration.enableGlobalConfig();
}
}
Property prop;
// clean up old properties that are not used anymore
if (config.getCategory(CATEGORY_GENERAL).containsKey("defaultSpawnFuzz")) config.getCategory(CATEGORY_GENERAL).remove("defaultSpawnFuzz");
if (config.getCategory(CATEGORY_GENERAL).containsKey("spawnHasFuzz")) config.getCategory(CATEGORY_GENERAL).remove("spawnHasFuzz");
if (config.getCategory(CATEGORY_GENERAL).containsKey("disableStitchedFileSaving")) config.getCategory(CATEGORY_GENERAL).remove("disableStitchedFileSaving");
if (config.getCategory(CATEGORY_CLIENT).containsKey("java8Reminder")) config.getCategory(CATEGORY_CLIENT).remove("java8Reminder");
if (config.getCategory(CATEGORY_CLIENT).containsKey("replaceVanillaBucketModel")) config.getCategory(CATEGORY_CLIENT).remove("replaceVanillaBucketModel");
// remap properties wrongly listed as general properties to client properties
remapGeneralPropertyToClient("biomeSkyBlendRange");
remapGeneralPropertyToClient("forgeLightPipelineEnabled");
prop = config.get(CATEGORY_GENERAL, "disableVersionCheck", false);
prop.setComment("Set to true to disable Forge's version check mechanics. Forge queries a small json file on our server for version information. For more details see the ForgeVersion class in our github.");
// Language keys are a good idea to implement if you are using config GUIs. This allows you to use a .lang file that will hold the
// "pretty" version of the property name as well as allow others to provide their own localizations.
// This language key is also used to get the tooltip for a property. The tooltip language key is langKey + ".tooltip".
// If no tooltip language key is defined in your .lang file, the tooltip will default to the property comment field.
prop.setLanguageKey("forge.configgui.disableVersionCheck");
disableVersionCheck = prop.getBoolean(disableVersionCheck);
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_GENERAL, "clumpingThreshold", 64,
"Controls the number threshold at which Packet51 is preferred over Packet52, default and minimum 64, maximum 1024", 64, 1024);
prop.setLanguageKey("forge.configgui.clumpingThreshold").setRequiresWorldRestart(true);
clumpingThreshold = prop.getInt(64);
if (clumpingThreshold > 1024 || clumpingThreshold < 64)
{
clumpingThreshold = 64;
prop.set(64);
}
propOrder.add(prop.getName());
prop = config.get(CATEGORY_GENERAL, "sortRecipies", true);
prop.setComment("Set to true to enable the post initialization sorting of crafting recipes using Forge's sorter. May cause desyncing on conflicting recipes. MUST RESTART MINECRAFT IF CHANGED FROM THE CONFIG GUI.");
prop.setLanguageKey("forge.configgui.sortRecipies").setRequiresMcRestart(true);
shouldSortRecipies = prop.getBoolean(true);
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_GENERAL, "removeErroringEntities", false);
prop.setComment("Set this to true to remove any Entity that throws an error in its update method instead of closing the server and reporting a crash log. BE WARNED THIS COULD SCREW UP EVERYTHING USE SPARINGLY WE ARE NOT RESPONSIBLE FOR DAMAGES.");
prop.setLanguageKey("forge.configgui.removeErroringEntities").setRequiresWorldRestart(true);
removeErroringEntities = prop.getBoolean(false);
propOrder.add(prop.getName());
if (removeErroringEntities)
{
FMLLog.log.warn("Enabling removal of erroring Entities - USE AT YOUR OWN RISK");
}
prop = config.get(Configuration.CATEGORY_GENERAL, "removeErroringTileEntities", false);
prop.setComment("Set this to true to remove any TileEntity that throws an error in its update method instead of closing the server and reporting a crash log. BE WARNED THIS COULD SCREW UP EVERYTHING USE SPARINGLY WE ARE NOT RESPONSIBLE FOR DAMAGES.");
prop.setLanguageKey("forge.configgui.removeErroringTileEntities").setRequiresWorldRestart(true);
removeErroringTileEntities = prop.getBoolean(false);
propOrder.add(prop.getName());
if (removeErroringTileEntities)
{
FMLLog.log.warn("Enabling removal of erroring Tile Entities - USE AT YOUR OWN RISK");
}
prop = config.get(Configuration.CATEGORY_GENERAL, "fullBoundingBoxLadders", false);
prop.setComment("Set this to true to check the entire entity's collision bounding box for ladders instead of just the block they are in. Causes noticeable differences in mechanics so default is vanilla behavior. Default: false");
prop.setLanguageKey("forge.configgui.fullBoundingBoxLadders").setRequiresWorldRestart(true);
fullBoundingBoxLadders = prop.getBoolean(false);
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_GENERAL, "zombieBaseSummonChance", 0.1,
"Base zombie summoning spawn chance. Allows changing the bonus zombie summoning mechanic.", 0.0D, 1.0D);
prop.setLanguageKey("forge.configgui.zombieBaseSummonChance").setRequiresWorldRestart(true);
zombieSummonBaseChance = prop.getDouble(0.1);
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_GENERAL, "zombieBabyChance", 0.05,
"Chance that a zombie (or subclass) is a baby. Allows changing the zombie spawning mechanic.", 0.0D, 1.0D);
prop.setLanguageKey("forge.configgui.zombieBabyChance").setRequiresWorldRestart(true);
zombieBabyChance = (float) prop.getDouble(0.05);
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_GENERAL, "logCascadingWorldGeneration", true,
"Log cascading chunk generation issues during terrain population.");
logCascadingWorldGeneration = prop.getBoolean();
prop.setLanguageKey("forge.configgui.logCascadingWorldGeneration");
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_GENERAL, "fixVanillaCascading", false,
"Fix vanilla issues that cause worldgen cascading. This DOES change vanilla worldgen so DO NOT report bugs related to world differences if this flag is on.");
fixVanillaCascading = prop.getBoolean();
prop.setLanguageKey("forge.configgui.fixVanillaCascading");
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_GENERAL, "dimensionUnloadQueueDelay", 0,
"The time in ticks the server will wait when a dimension was queued to unload. " +
"This can be useful when rapidly loading and unloading dimensions, like e.g. throwing items through a nether portal a few time per second.");
dimensionUnloadQueueDelay = prop.getInt(0);
prop.setLanguageKey("forge.configgui.dimensionUnloadQueueDelay");
propOrder.add(prop.getName());
config.setCategoryPropertyOrder(CATEGORY_GENERAL, propOrder);
propOrder = new ArrayList<String>();
prop = config.get(VERSION_CHECK_CAT, "Global", true, "Enable the entire mod update check system. This only applies to mods using the Forge system.");
propOrder.add("Global");
config.setCategoryPropertyOrder(VERSION_CHECK_CAT, propOrder);
// Client-Side only properties
propOrder = new ArrayList<String>();
prop = config.get(Configuration.CATEGORY_CLIENT, "zoomInMissingModelTextInGui", false,
"Toggle off to make missing model text in the gui fit inside the slot.");
zoomInMissingModelTextInGui = prop.getBoolean(false);
prop.setLanguageKey("forge.configgui.zoomInMissingModelTextInGui");
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_CLIENT, "forgeCloudsEnabled", true,
"Enable uploading cloud geometry to the GPU for faster rendering.");
prop.setLanguageKey("forge.configgui.forgeCloudsEnabled");
forgeCloudsEnabled = prop.getBoolean();
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_CLIENT, "disableStairSlabCulling", false,
"Disable culling of hidden faces next to stairs and slabs. Causes extra rendering, but may fix some resource packs that exploit this vanilla mechanic.");
disableStairSlabCulling = prop.getBoolean(false);
prop.setLanguageKey("forge.configgui.disableStairSlabCulling");
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_CLIENT, "alwaysSetupTerrainOffThread", false,
"Enable forge to queue all chunk updates to the Chunk Update thread. May increase FPS significantly, but may also cause weird rendering lag. Not recommended for computers " +
"without a significant number of cores available.");
alwaysSetupTerrainOffThread = prop.getBoolean(false);
prop.setLanguageKey("forge.configgui.alwaysSetupTerrainOffThread");
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_CLIENT, "biomeSkyBlendRange", new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34 });
prop.setComment("Control the range of sky blending for colored skies in biomes.");
prop.setLanguageKey("forge.configgui.biomeSkyBlendRange");
blendRanges = prop.getIntList();
propOrder.add(prop.getName());
prop = config.get(Configuration.CATEGORY_CLIENT, "forgeLightPipelineEnabled", true,
"Enable the forge block rendering pipeline - fixes the lighting of custom models.");
forgeLightPipelineEnabled = prop.getBoolean(true);
prop.setLanguageKey("forge.configgui.forgeLightPipelineEnabled");
propOrder.add(prop.getName());
config.setCategoryPropertyOrder(CATEGORY_CLIENT, propOrder);
if (config.hasChanged())
{
config.save();
}
}
/**
* By subscribing to the OnConfigChangedEvent we are able to execute code when our config screens are closed.
* This implementation uses the optional configID string to handle multiple Configurations using one event handler.
*/
public void onConfigChanged(OnConfigChangedEvent event)
{
if (getModId().equals(event.getModID()))
{
if ("chunkLoader".equals(event.getConfigID()))
{
ForgeChunkManager.syncConfigDefaults();
ForgeChunkManager.loadConfiguration();
}
else
{
boolean tmpStairs = disableStairSlabCulling;
syncConfig(false);
if (event.isWorldRunning() && tmpStairs != disableStairSlabCulling)
{
FMLCommonHandler.instance().reloadRenderers();
}
}
}
}
public void missingMapping(RegistryEvent.MissingMappings<Item> event)
{
for (MissingMappings.Mapping<Item> entry : event.getAllMappings())
{
if (entry.key.toString().equals("minecraft:totem")) //This item changed from 1.11 -> 1.11.2
{
ResourceLocation newTotem = new ResourceLocation("minecraft:totem_of_undying");
entry.remap(ForgeRegistries.ITEMS.getValue(newTotem));
}
}
}
public void playerLogin(PlayerEvent.PlayerLoggedInEvent event)
{
UsernameCache.setUsername(event.player.getPersistentID(), event.player.getGameProfile().getName());
}
public void preInit(FMLPreInitializationEvent evt)
{
CapabilityItemHandler.register();
CapabilityFluidHandler.register();
CapabilityAnimation.register();
CapabilityEnergy.register();
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
// ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory());
MinecraftForge.EVENT_BUS.register(this);
if (!ForgeMod.disableVersionCheck)
{
VersionChecker.startVersionCheck();
}
}
public void registrItems(RegistryEvent.Register<Item> event)
{
// Add and register the forge universal bucket, if it's enabled
if(FluidRegistry.isUniversalBucketEnabled())
{
universalBucket = new UniversalBucket();
universalBucket.setUnlocalizedName("forge.bucketFilled");
event.getRegistry().register(universalBucket.setRegistryName(ForgeVersion.MOD_ID, "bucketFilled"));
MinecraftForge.EVENT_BUS.register(universalBucket);
}
}
public void postInit(FMLPostInitializationEvent evt)
{
registerAllBiomesAndGenerateEvents();
//ForgeChunkManager.loadConfiguration();
}
private static void registerAllBiomesAndGenerateEvents()
{
for (Biome biome : ForgeRegistries.BIOMES.getValuesCollection())
{
if (biome.decorator instanceof DeferredBiomeDecorator)
{
DeferredBiomeDecorator decorator = (DeferredBiomeDecorator)biome.decorator;
decorator.fireCreateEventAndReplace(biome);
}
BiomeDictionary.ensureHasTypes(biome);
}
}
public void onAvailable(FMLLoadCompleteEvent evt)
{
FluidRegistry.validateFluidRegistry();
}
@SubscribeEvent
public void serverStarting(FMLServerStartingEvent evt)
{
evt.registerServerCommand(new ForgeCommand());
}
@SubscribeEvent
public void serverStopping(FMLServerStoppingEvent evt)
{
WorldWorkerManager.clear();
}
@Override
public NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info)
{
NBTTagCompound forgeData = new NBTTagCompound();
NBTTagCompound dimData = DimensionManager.saveDimensionDataMap();
forgeData.setTag("DimensionData", dimData);
FluidRegistry.writeDefaultFluidList(forgeData);
return forgeData;
}
@Override
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
{
DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null);
FluidRegistry.loadFluidDefaults(tag);
}
public void mappingChanged(FMLModIdMappingEvent evt)
{
OreDictionary.rebakeMap();
StatList.reinit();
Ingredient.invalidateAll();
FMLCommonHandler.instance().reloadSearchTrees();
}
@Override
public String getModId()
{
return ForgeVersion.MOD_ID;
}
}

View File

@ -19,91 +19,13 @@
package net.minecraftforge.common;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.biome.Biome;
import static net.minecraftforge.common.config.Configuration.CATEGORY_CLIENT;
import static net.minecraftforge.common.config.Configuration.CATEGORY_GENERAL;
import net.minecraftforge.fml.ModLoadingClassLoader;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.fml.loading.DefaultModInfos;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.minecraft.crash.ICrashReportDetail;
import net.minecraft.item.Item;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.stats.StatList;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.classloading.FMLForgePlugin;
import net.minecraftforge.client.ForgeClientHandler;
import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.common.model.animation.CapabilityAnimation;
import net.minecraftforge.common.network.ForgeNetworkHandler;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.RegistryEvent.MissingMappings;
import net.minecraftforge.event.terraingen.DeferredBiomeDecorator;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.fluids.UniversalBucket;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.RecipeSorter;
import net.minecraftforge.server.command.ForgeCommand;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import net.minecraftforge.fml.client.FMLFileResourcePack;
import net.minecraftforge.fml.client.FMLFolderResourcePack;
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
import net.minecraftforge.fml.common.DummyModContainer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.ICrashCallable;
import net.minecraftforge.fml.common.LoadController;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.ModMetadata;
import net.minecraftforge.fml.common.WorldAccessContainer;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.common.discovery.json.JsonAnnotationLoader;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
import net.minecraftforge.fml.common.event.FMLModIdMappingEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.relauncher.Side;
import javax.annotation.Nullable;
@EventBusSubscriber(modid = "forge")
public class ForgeModContainer extends DummyModContainer implements WorldAccessContainer
public class ForgeModContainer extends FMLModContainer
{
/*
public static final String VERSION_CHECK_CAT = "version_checking";
public static int clumpingThreshold = 64;
public static boolean removeErroringEntities = false;
@ -192,7 +114,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
/**
* Synchronizes the local fields with the values in the Configuration object.
*/
* /
private static void syncConfig(boolean load)
{
// By adding a property order list we are defining the order that the properties will appear both in the config file and on the GUIs.
@ -376,7 +298,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
/**
* By subscribing to the OnConfigChangedEvent we are able to execute code when our config screens are closed.
* This implementation uses the optional configID string to handle multiple Configurations using one event handler.
*/
* /
@SubscribeEvent
public void onConfigChanged(OnConfigChangedEvent event)
{
@ -644,4 +566,10 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
return updateJSONUrl;
}
*/
public ForgeModContainer(ModLoadingClassLoader classLoader)
{
super(DefaultModInfos.forgeModInfo, "net.minecraftforge.common.ForgeMod", classLoader, null);
}
}

View File

@ -31,7 +31,7 @@ import javax.annotation.Nullable;
public class ForgeVersion
{
// This is Forge's Mod Id, used for the ForgeModContainer and resource locations
// This is Forge's Mod Id, used for the ForgeMod and resource locations
public static final String MOD_ID = "forge";
//This number is incremented every time we remove deprecated code/major API changes, never reset
public static final int majorVersion = 14;

View File

@ -22,8 +22,6 @@ package net.minecraftforge.common;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.ICrashCallable;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.eventbus.api.IEventBus;
import java.util.Collections;
@ -111,11 +109,11 @@ public class MinecraftForge
if (all.size() == 0)
return;
ForgeModContainer.log.debug("Preloading CrashReport Classes");
ForgeMod.log.debug("Preloading CrashReport Classes");
Collections.sort(all); //Sort it because I like pretty output ;)
for (String name : all)
{
ForgeModContainer.log.debug("\t{}", name);
ForgeMod.log.debug("\t{}", name);
try
{
Class.forName(name.replace('/', '.'), false, MinecraftForge.class.getClassLoader());

View File

@ -42,8 +42,6 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import net.minecraftforge.fml.relauncher.FMLInjectionData;
/**
* Caches player's last known usernames
* <p>

View File

@ -39,8 +39,6 @@ import net.minecraftforge.common.config.Config.Name;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation.EnumHolder;
import org.apache.commons.lang3.StringUtils;

View File

@ -57,7 +57,6 @@ import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
import net.minecraftforge.fml.client.config.IConfigElement;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.relauncher.FMLInjectionData;
import org.apache.commons.io.IOUtils;
/**

View File

@ -20,28 +20,26 @@
package net.minecraftforge.common.crafting;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import javax.annotation.Nonnull;
import net.minecraft.client.util.RecipeBookClient;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.SidedExecutor;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@ -57,7 +55,6 @@ import com.google.gson.JsonSyntaxException;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipes;
@ -68,10 +65,6 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.OreIngredient;
@ -80,14 +73,20 @@ import net.minecraftforge.oredict.ShapelessOreRecipe;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
import net.minecraftforge.registries.RegistryManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
public class CraftingHelper {
private static final boolean DEBUG_LOAD_MINECRAFT = false;
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker CRAFTHELPER = MarkerManager.getMarker("CRAFTHELPER");
private static Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
private static Map<ResourceLocation, IConditionFactory> conditions = Maps.newHashMap();
private static Map<ResourceLocation, IIngredientFactory> ingredients = Maps.newHashMap();
private static Map<ResourceLocation, IRecipeFactory> recipes = Maps.newHashMap();
private static Map<ResourceLocation, IConditionFactory> conditions = new HashMap<>();
private static Map<ResourceLocation, IIngredientFactory> ingredients = new HashMap<>();
private static Map<ResourceLocation, IRecipeFactory> recipes = new HashMap<>();
static {
init();
@ -420,7 +419,7 @@ public class CraftingHelper {
registerC("forge:mod_loaded", (context, json) -> {
String modid = JsonUtils.getString(json, "modid");
return () -> Loader.isModLoaded(modid);
return () -> ModList.get().isLoaded(modid);
});
registerC("minecraft:item_exists", (context, json) -> {
String itemName = context.appendModId(JsonUtils.getString(json, "item"));
@ -548,7 +547,7 @@ public class CraftingHelper {
register(new ResourceLocation(name), fac);
}
static void loadFactories(JsonObject json, JsonContext context)
private static void loadFactories(JsonObject json, JsonContext context)
{
if (json.has("ingredients"))
{
@ -581,11 +580,12 @@ public class CraftingHelper {
}
}
@SuppressWarnings("unchecked")
private static <T> T getClassInstance(String clsName, Class<T> expected)
{
try
{
Class<?> cls = Class.forName(clsName);
Class<?> cls = Class.forName(clsName, true, Thread.currentThread().getContextClassLoader());
if (!expected.isAssignableFrom(cls))
throw new JsonSyntaxException("Class '" + clsName + "' is not an " + expected.getSimpleName());
return (T)cls.newInstance();
@ -612,229 +612,97 @@ public class CraftingHelper {
reg.clear();
else if (revertFrozen)
GameData.revert(RegistryManager.FROZEN, GameData.RECIPES, false);
//ModContainer old = Loader.instance().activeModContainer();
Loader.instance().setActiveModContainer(null);
Loader.instance().getActiveModList().forEach(CraftingHelper::loadFactories);
Loader.instance().getActiveModList().forEach(CraftingHelper::loadRecipes);
Loader.instance().setActiveModContainer(null);
ModList.get().forEachModFile(CraftingHelper::loadFactories);
ModList.get().forEachModFile(CraftingHelper::loadRecipes);
GameData.fireRegistryEvents(rl -> rl.equals(GameData.RECIPES));
//reg.freeze();
FMLCommonHandler.instance().resetClientRecipeBook();
SidedExecutor.runOn(Dist.CLIENT, ()-> {
RecipeBookClient.rebuildTable();
return null;
});
}
private static void loadFactories(ModContainer mod)
private static void loadFactories(final ModFile modFile)
{
FileSystem fs = null;
BufferedReader reader = null;
try
{
JsonContext ctx = new JsonContext(mod.getModId());
Path fPath = null;
if (mod.getSource().isFile())
{
fs = FileSystems.newFileSystem(mod.getSource().toPath(), null);
fPath = fs.getPath("/assets/" + ctx.getModId() + "/recipes/_factories.json");
}
else if (mod.getSource().isDirectory())
{
fPath = mod.getSource().toPath().resolve("assets/" + ctx.getModId() + "/recipes/_factories.json");
}
modFile.getModInfos().forEach(modInfo-> {
final String modId = modInfo.getModId();
JsonContext ctx = new JsonContext(modId);
final Path fPath = modFile.getLocator().findPath(modFile, "assets", modId, "recipes","_factories.json");
if (fPath != null && Files.exists(fPath))
{
reader = Files.newBufferedReader(fPath);
JsonObject json = JsonUtils.fromJson(GSON, reader, JsonObject.class);
loadFactories(json, ctx);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
IOUtils.closeQuietly(fs);
IOUtils.closeQuietly(reader);
}
}
private static boolean loadRecipes(ModContainer mod)
{
JsonContext ctx = new JsonContext(mod.getModId());
return findFiles(mod, "assets/" + mod.getModId() + "/recipes",
root ->
{
Path fPath = root.resolve("_constants.json");
if (fPath != null && Files.exists(fPath))
try (final BufferedReader reader = Files.newBufferedReader(fPath))
{
BufferedReader reader = null;
try
{
reader = Files.newBufferedReader(fPath);
JsonObject[] json = JsonUtils.fromJson(GSON, reader, JsonObject[].class);
ctx.loadConstants(json);
}
catch (IOException e)
{
FMLLog.log.error("Error loading _constants.json: ", e);
return false;
}
finally
{
IOUtils.closeQuietly(reader);
}
}
return true;
},
(root, file) ->
{
Loader.instance().setActiveModContainer(mod);
String relative = root.relativize(file).toString();
if (!"json".equals(FilenameUtils.getExtension(file.toString())) || relative.startsWith("_"))
return true;
String name = FilenameUtils.removeExtension(relative).replaceAll("\\\\", "/");
ResourceLocation key = new ResourceLocation(ctx.getModId(), name);
BufferedReader reader = null;
try
{
reader = Files.newBufferedReader(file);
JsonObject json = JsonUtils.fromJson(GSON, reader, JsonObject.class);
if (json.has("conditions") && !CraftingHelper.processConditions(JsonUtils.getJsonArray(json, "conditions"), ctx))
return true;
IRecipe recipe = CraftingHelper.getRecipe(json, ctx);
ForgeRegistries.RECIPES.register(recipe.setRegistryName(key));
loadFactories(json, ctx);
}
catch (JsonParseException e)
catch (final IOException e)
{
FMLLog.log.error("Parsing error loading recipe {}", key, e);
return false;
LOGGER.error(CRAFTHELPER,"Encountered error reading recipe factories for {}", modId, e);
}
catch (IOException e)
{
FMLLog.log.error("Couldn't read recipe {} from {}", key, file, e);
return false;
}
finally
{
IOUtils.closeQuietly(reader);
}
return true;
},
true, true
);
}
});
}
/**
* @deprecated Use {@link CraftingHelper#findFiles(ModContainer, String, Function, BiFunction, boolean, boolean)} instead.
*/
@Deprecated
public static boolean findFiles(ModContainer mod, String base, Function<Path, Boolean> preprocessor, BiFunction<Path, Path, Boolean> processor)
private static boolean loadRecipes(final ModFile modFile)
{
return findFiles(mod, base, preprocessor, processor, false, false);
}
/**
* @deprecated Use {@link CraftingHelper#findFiles(ModContainer, String, Function, BiFunction, boolean, boolean)} instead.
*/
@Deprecated
public static boolean findFiles(ModContainer mod, String base, Function<Path, Boolean> preprocessor, BiFunction<Path, Path, Boolean> processor, boolean defaultUnfoundRoot)
{
return findFiles(mod, base, preprocessor, processor, defaultUnfoundRoot, false);
}
public static boolean findFiles(ModContainer mod, String base, Function<Path, Boolean> preprocessor, BiFunction<Path, Path, Boolean> processor, boolean defaultUnfoundRoot, boolean visitAllFiles)
{
FileSystem fs = null;
try
{
File source = mod.getSource();
if ("minecraft".equals(mod.getModId()))
final AtomicBoolean errored = new AtomicBoolean(false);
modFile.getModInfos().forEach(modInfo-> {
final String modId = modInfo.getModId();
JsonContext ctx = new JsonContext(modId);
final Path root = modFile.getLocator().findPath(modFile, "assets", modId, "recipes");
if (!Files.exists(root)) return;
final Path constants = modFile.getLocator().findPath(modFile, "assets", modId, "recipes", "_constants.json");
if (Files.exists(constants))
{
if (!DEBUG_LOAD_MINECRAFT)
return true;
try
try (BufferedReader reader = Files.newBufferedReader(constants))
{
URI tmp = CraftingManager.class.getResource("/assets/.mcassetsroot").toURI();
source = new File(tmp.resolve("..").getPath());
JsonObject[] json = JsonUtils.fromJson(GSON, reader, JsonObject[].class);
ctx.loadConstants(json);
}
catch (URISyntaxException e)
catch (final IOException e)
{
FMLLog.log.error("Error finding Minecraft jar: ", e);
return false;
LOGGER.error(CRAFTHELPER, "Error loading _constants.json: ", e);
errored.set(true);
}
}
Path root = null;
if (source.isFile())
try
{
try
{
fs = FileSystems.newFileSystem(source.toPath(), null);
root = fs.getPath("/" + base);
}
catch (IOException e)
{
FMLLog.log.error("Error loading FileSystem from jar: ", e);
return false;
}
Files.walk(root).
filter(p -> p.getFileName().toString().startsWith("_") || Objects.equals(FilenameUtils.getExtension(p.getFileName().toString()), "json")).
forEach(p -> {
final String relative = root.relativize(p).toString();
final String name = FilenameUtils.removeExtension(relative).replaceAll("\\\\", "/");
final ResourceLocation key = new ResourceLocation(modId, name);
try (BufferedReader reader = Files.newBufferedReader(constants))
{
JsonObject json = JsonUtils.fromJson(GSON, reader, JsonObject.class);
if (json.has("conditions") && !CraftingHelper.processConditions(JsonUtils.getJsonArray(json, "conditions"), ctx))
return;
IRecipe recipe = CraftingHelper.getRecipe(json, ctx);
ForgeRegistries.RECIPES.register(recipe.setRegistryName(key));
}
catch (final JsonParseException e)
{
LOGGER.error(CRAFTHELPER, "Parsing error loading recipe {}", key, e);
errored.set(true);
}
catch (final IOException e)
{
LOGGER.error(CRAFTHELPER, "Couldn't read recipe {} from {}", key, p, e);
errored.set(true);
}
});
}
else if (source.isDirectory())
catch (final IOException e)
{
root = source.toPath().resolve(base);
LOGGER.error(CRAFTHELPER, "Error occurred walking file tree", e);
errored.set(true);
}
if (root == null || !Files.exists(root))
return defaultUnfoundRoot;
if (preprocessor != null)
{
Boolean cont = preprocessor.apply(root);
if (cont == null || !cont.booleanValue())
return false;
}
boolean success = true;
if (processor != null)
{
Iterator<Path> itr = null;
try
{
itr = Files.walk(root).iterator();
}
catch (IOException e)
{
FMLLog.log.error("Error iterating filesystem for: {}", mod.getModId(), e);
return false;
}
while (itr != null && itr.hasNext())
{
Boolean cont = processor.apply(root, itr.next());
if (visitAllFiles)
{
success &= cont != null && cont;
}
else if (cont == null || !cont)
{
return false;
}
}
}
return success;
}
finally
{
IOUtils.closeQuietly(fs);
}
});
return errored.get();
}
}

View File

@ -39,14 +39,14 @@ import net.minecraft.client.renderer.block.model.ItemTransformVec3f;
import net.minecraft.client.renderer.block.model.ModelRotation;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.Vec3i;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import com.google.common.base.MoreObjects;
import java.util.Optional;
import com.google.common.collect.Maps;
/*
@ -93,50 +93,26 @@ public final class TRSRTransformation implements IModelState, ITransformation
full = true;
}
/** @deprecated use {@link #from(ItemTransformVec3f)} */
@Deprecated // TODO: remove / make private
@SideOnly(Side.CLIENT)
public TRSRTransformation(ItemTransformVec3f transform)
{
this(toVecmath(transform.translation), quatFromXYZDegrees(toVecmath(transform.rotation)), toVecmath(transform.scale), null);
}
/** @deprecated use {@link #from(ModelRotation)} */
@Deprecated // TODO: remove
@SideOnly(Side.CLIENT)
public TRSRTransformation(ModelRotation rotation)
{
this(rotation.getMatrix());
}
/** @deprecated use {@link #from(EnumFacing)} */
@Deprecated // TODO: remove
@SideOnly(Side.CLIENT)
public TRSRTransformation(EnumFacing facing)
{
this(getMatrix(facing));
}
@Deprecated
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static TRSRTransformation from(ItemTransformVec3f transform)
{
return transform.equals(ItemTransformVec3f.DEFAULT) ? identity : new TRSRTransformation(transform);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static TRSRTransformation from(ModelRotation rotation)
{
return Cache.get(rotation);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static TRSRTransformation from(EnumFacing facing)
{
return Cache.get(getRotation(facing));
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static Matrix4f getMatrix(EnumFacing facing)
{
return getRotation(facing).getMatrix();
@ -558,8 +534,8 @@ public final class TRSRTransformation implements IModelState, ITransformation
* Don't use this if you don't need to, conversion is lossy (second rotation component is lost).
*/
@Deprecated
@SideOnly(Side.CLIENT)
public ItemTransformVec3f toItemTransform()
@OnlyIn(Dist.CLIENT)
public net.minecraft.client.renderer.block.model.ItemTransformVec3f toItemTransform()
{
return new ItemTransformVec3f(toLwjgl(toXYZDegrees(getLeftRot())), toLwjgl(getTranslation()), toLwjgl(getScale()));
}
@ -712,19 +688,19 @@ public final class TRSRTransformation implements IModelState, ITransformation
return Objects.equals(matrix, other.matrix);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static Vector3f toVecmath(org.lwjgl.util.vector.Vector3f vec)
{
return new Vector3f(vec.x, vec.y, vec.z);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static Vector4f toVecmath(org.lwjgl.util.vector.Vector4f vec)
{
return new Vector4f(vec.x, vec.y, vec.z, vec.w);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static Matrix4f toVecmath(org.lwjgl.util.vector.Matrix4f m)
{
return new Matrix4f(
@ -734,19 +710,19 @@ public final class TRSRTransformation implements IModelState, ITransformation
m.m03, m.m13, m.m23, m.m33);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static org.lwjgl.util.vector.Vector3f toLwjgl(Vector3f vec)
{
return new org.lwjgl.util.vector.Vector3f(vec.x, vec.y, vec.z);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static org.lwjgl.util.vector.Vector4f toLwjgl(Vector4f vec)
{
return new org.lwjgl.util.vector.Vector4f(vec.x, vec.y, vec.z, vec.w);
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static org.lwjgl.util.vector.Matrix4f toLwjgl(Matrix4f m)
{
org.lwjgl.util.vector.Matrix4f r = new org.lwjgl.util.vector.Matrix4f();
@ -847,7 +823,7 @@ public final class TRSRTransformation implements IModelState, ITransformation
}
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
private static final class Cache
{
private static final Map<ModelRotation, TRSRTransformation> rotations = new EnumMap<>(ModelRotation.class);

View File

@ -43,14 +43,14 @@ import com.google.gson.stream.JsonWriter;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.animation.Event;
import net.minecraftforge.common.animation.ITimeValue;
import net.minecraftforge.common.animation.TimeValues;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.util.JsonUtils;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
@ -213,7 +213,7 @@ public final class AnimationStateMachine implements IAnimationStateMachine
/**
* Load a new instance if AnimationStateMachine at specified location, with specified custom parameters.
*/
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static IAnimationStateMachine load(IResourceManager manager, ResourceLocation location, ImmutableMap<String, ITimeValue> customParameters)
{
try (IResource resource = manager.getResource(location))

View File

@ -25,6 +25,7 @@ import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.animation.Event;
@ -33,8 +34,7 @@ import net.minecraftforge.common.model.IModelPart;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.tuple.Pair;
@ -88,7 +88,7 @@ public final class Clips
/**
* Retrieves the clip from the model.
*/
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public static IClip getModelClipNode(ResourceLocation modelLocation, String clipName)
{
IModel model = ModelLoaderRegistry.getModelOrMissing(modelLocation);

View File

@ -20,21 +20,22 @@
package net.minecraftforge.common.network;
import java.util.EnumMap;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.fml.common.network.FMLEmbeddedChannel;
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
import net.minecraftforge.fml.common.network.FMLOutboundHandler.OutboundTarget;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
public class ForgeNetworkHandler
{
private static EnumMap<Side, FMLEmbeddedChannel> channelPair;
public static void registerChannel(ForgeModContainer forgeModContainer, Side side)
public static void registerChannel(ForgeMod forgeMod, Side side)
{
channelPair = NetworkRegistry.INSTANCE.newChannel(forgeModContainer, "FORGE", new ForgeRuntimeCodec());
channelPair = NetworkRegistry.INSTANCE.newChannel(forgeMod, "FORGE", new ForgeRuntimeCodec());
if (side == Side.CLIENT)
{
addClientHandlers();
@ -46,7 +47,7 @@ public class ForgeNetworkHandler
serverChannel.pipeline().addAfter(handlerName, "ServerToClientConnection", new ServerToClientConnectionEstablishedHandler());
}
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
private static void addClientHandlers()
{
FMLEmbeddedChannel clientChannel = channelPair.get(Side.CLIENT);

View File

@ -394,7 +394,7 @@ public class ForgeEventFactory
public static void firePlayerLoadingEvent(EntityPlayer player, IPlayerFileData playerFileData, String uuidString)
{
SaveHandler sh = (SaveHandler) playerFileData;
File dir = ObfuscationReflectionHelper.getPrivateValue(SaveHandler.class, sh, "playersDirectory", "field_"+"75771_c");
File dir = sh.getPlayersDirectory();
MinecraftForge.EVENT_BUS.post(new PlayerEvent.LoadFromFile(player, dir, uuidString));
}

View File

@ -31,7 +31,7 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.Cancelable;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.api.distmarker.Dist;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

View File

@ -50,12 +50,13 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.property.ExtendedBlockState;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.common.property.Properties;
import net.minecraftforge.common.property.PropertyFloat;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
/**
* This is a base implementation for Fluid blocks.
@ -409,7 +410,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock
}
@Override
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
@Nonnull
public BlockRenderLayer getBlockLayer()
{
@ -763,7 +764,7 @@ public abstract class BlockFluidBase extends Block implements IFluidBlock
}
@Override
@SideOnly (Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public Vec3d getFogColor(World world, BlockPos pos, IBlockState state, Entity entity, Vec3d originalColor, float partialTicks)
{
if (!isWithinFluid(world, pos, ActiveRenderInfo.projectViewFromEntity(entity, partialTicks)))

View File

@ -25,7 +25,6 @@ import java.util.Map.Entry;
import java.util.Set;
import net.minecraftforge.fml.ModThreadContext;
import net.minecraftforge.fml.common.LoaderState;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
@ -44,11 +43,13 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.registries.IRegistryDelegate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import javax.annotation.Nullable;
@ -57,6 +58,8 @@ import javax.annotation.Nullable;
*/
public abstract class FluidRegistry
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker FLUIDS = MarkerManager.getMarker("FLUIDS");
static int maxID = 0;
static BiMap<String, Fluid> fluids = HashBiMap.create();
@ -124,13 +127,13 @@ public abstract class FluidRegistry
String derivedName = defaultName.split(":",2)[1];
String localDefault = defaultFluidName.get(derivedName);
if (localDefault == null) {
FMLLog.log.error("The fluid {} (specified as {}) is missing from this instance - it will be removed", derivedName, defaultName);
LOGGER.error(FLUIDS, "The fluid {} (specified as {}) is missing from this instance - it will be removed",derivedName,defaultName);
continue;
}
fluid = masterFluidReference.get(localDefault);
FMLLog.log.error("The fluid {} specified as default is not present - it will be reverted to default {}", defaultName, localDefault);
LOGGER.error(FLUIDS, "The fluid {} specified as default is not present - it will be reverted to default {}",defaultName,localDefault);
}
FMLLog.log.debug("The fluid {} has been selected as the default fluid for {}", defaultName, fluid.getName());
LOGGER.debug(FLUIDS, "The fluid {} has been selected as the default fluid for {}",defaultName,fluid.getName());
Fluid oldFluid = localFluids.put(fluid.getName(), fluid);
Integer id = localFluidIDs.remove(oldFluid);
localFluidIDs.put(fluid, id);
@ -177,7 +180,7 @@ public abstract class FluidRegistry
private static String uniqueName(Fluid fluid)
{
return ModThreadContext.get().getCurrentContainer().getPrefix() +":"+fluid.getName();
return ModThreadContext.get().getActiveContainer().getPrefix() +":"+fluid.getName();
}
/**
@ -255,16 +258,7 @@ public abstract class FluidRegistry
*/
public static void enableUniversalBucket()
{
if (Loader.instance().hasReachedState(LoaderState.PREINITIALIZATION))
{
ModContainer modContainer = Loader.instance().activeModContainer();
String modContainerName = modContainer == null ? null : modContainer.getName();
FMLLog.log.error("Trying to activate the universal filled bucket too late. Call it statically in your Mods class. Mod: {}", modContainerName);
}
else
{
universalBucketEnabled = true;
}
universalBucketEnabled = true;
}
public static boolean isUniversalBucketEnabled()
@ -357,7 +351,7 @@ public abstract class FluidRegistry
{
String name = masterFluidReference.inverse().get(key);
if (Strings.isNullOrEmpty(name)) {
FMLLog.log.error("The fluid registry is corrupted. A fluid {} {} is not properly registered. The mod that registered this is broken", key.getClass().getName(), key.getName());
LOGGER.error(FLUIDS, "The fluid registry is corrupted. A fluid {} {} is not properly registered. The mod that registered this is broken",key.getClass().getName(),key.getName());
throw new IllegalStateException("The fluid registry is corrupted");
}
return name;
@ -383,7 +377,7 @@ public abstract class FluidRegistry
Set<String> defaults = Sets.newHashSet();
if (tag.hasKey("DefaultFluidList",9))
{
FMLLog.log.debug("Loading persistent fluid defaults from world");
LOGGER.debug(FLUIDS, "Loading persistent fluid defaults from world");
NBTTagList tl = tag.getTagList("DefaultFluidList", 8);
for (int i = 0; i < tl.tagCount(); i++)
{
@ -392,7 +386,7 @@ public abstract class FluidRegistry
}
else
{
FMLLog.log.debug("World is missing persistent fluid defaults - using local defaults");
LOGGER.debug(FLUIDS,"World is missing persistent fluid defaults - using local defaults");
}
loadFluidDefaults(HashBiMap.create(fluidIDs), defaults);
}
@ -422,13 +416,13 @@ public abstract class FluidRegistry
if (!illegalFluids.isEmpty())
{
FMLLog.log.fatal("The fluid registry is corrupted. Something has inserted a fluid without registering it");
FMLLog.log.fatal("There is {} unregistered fluids", illegalFluids.size());
LOGGER.fatal(FLUIDS, "The fluid registry is corrupted. Something has inserted a fluid without registering it");
LOGGER.fatal(FLUIDS, "There is {} unregistered fluids",illegalFluids.size());
for (Fluid f: illegalFluids)
{
FMLLog.log.fatal(" Fluid name : {}, type: {}", f.getName(), f.getClass().getName());
LOGGER.fatal(FLUIDS, " Fluid name : {}, type: {}",f.getName(),f.getClass().getName());
}
FMLLog.log.fatal("The mods that own these fluids need to register them properly");
LOGGER.fatal(FLUIDS, "The mods that own these fluids need to register them properly");
throw new IllegalStateException("The fluid map contains fluids unknown to the master fluid registry");
}
}

View File

@ -39,7 +39,7 @@ import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
@ -742,7 +742,7 @@ public class FluidUtil
if (FluidRegistry.isUniversalBucketEnabled() && FluidRegistry.getBucketFluids().contains(fluid))
{
UniversalBucket bucket = ForgeModContainer.getInstance().universalBucket;
UniversalBucket bucket = ForgeMod.getInstance().universalBucket;
ItemStack filledBucket = new ItemStack(bucket);
FluidStack fluidContents = new FluidStack(fluidStack, bucket.getCapacity());

View File

@ -27,7 +27,7 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemBucketMilk;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fluids.Fluid;
@ -85,9 +85,9 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide
{
return FluidRegistry.getFluidStack("milk", Fluid.BUCKET_VOLUME);
}
else if (item == ForgeModContainer.getInstance().universalBucket)
else if (item == ForgeMod.getInstance().universalBucket)
{
return ForgeModContainer.getInstance().universalBucket.getFluid(container);
return ForgeMod.getInstance().universalBucket.getFluid(container);
}
else
{

View File

@ -19,10 +19,9 @@
package net.minecraftforge.fml;
import net.minecraftforge.api.Side;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.language.ModFileScanData;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation;
@ -47,6 +46,7 @@ public class AutomaticEventSubscriber
private static final Logger LOGGER = LogManager.getLogger("FML");
public static void inject(final ModContainer mod, final ModFileScanData scanData, final ClassLoader loader)
{
if (scanData == null) return;
LOGGER.debug(LOADING,"Attempting to inject @EventBusSubscriber classes into the eventbus for {}", mod.getModId());
List<ModFileScanData.AnnotationData> ebsTargets = scanData.getAnnotations().stream().
filter(annotationData -> Objects.equals(annotationData.getAnnotationType(), Type.getType(Mod.EventBusSubscriber.class))).
@ -55,11 +55,11 @@ public class AutomaticEventSubscriber
ebsTargets.forEach(ad -> {
@SuppressWarnings("unchecked")
final List<ModAnnotation.EnumHolder> sidesValue = (List<ModAnnotation.EnumHolder>)ad.getAnnotationData().
getOrDefault("value", Arrays.asList(new ModAnnotation.EnumHolder(null, "CLIENT"), new ModAnnotation.EnumHolder(null, "SERVER")));
final EnumSet<Side> sides = sidesValue.stream().map(eh -> Side.valueOf(eh.getValue())).
collect(Collectors.toCollection(() -> EnumSet.noneOf(Side.class)));
getOrDefault("value", Arrays.asList(new ModAnnotation.EnumHolder(null, "CLIENT"), new ModAnnotation.EnumHolder(null, "DEDICATED_SERVER")));
final EnumSet<Dist> sides = sidesValue.stream().map(eh -> Dist.valueOf(eh.getValue())).
collect(Collectors.toCollection(() -> EnumSet.noneOf(Dist.class)));
final String modId = (String)ad.getAnnotationData().getOrDefault("modId", mod.getModId());
if (Objects.equals(mod.getModId(), modId) && sides.contains(FMLEnvironment.side)) {
if (Objects.equals(mod.getModId(), modId) && sides.contains(FMLEnvironment.dist)) {
try
{
MinecraftForge.EVENT_BUS.register(Class.forName(ad.getClassType().getClassName(), true, loader));

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.client;
package net.minecraftforge.fml;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@ -25,6 +25,7 @@ import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.fml.ModList;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
@ -70,4 +71,9 @@ public class BrandingControl
public static String getClientBranding() {
return defaultClientBranding.stream().collect(Collectors.joining(","));
}
public static final List<String> defaultServerBranding = Arrays.asList("fml", "forge");
public static String getServerBranding() {
return defaultServerBranding.stream().collect(Collectors.joining(","));
}
}

View File

@ -19,13 +19,9 @@
package net.minecraftforge.fml;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraftforge.fml.common.ICrashCallable;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.relauncher.CoreModManager;
import java.util.ArrayList;
import java.util.List;

View File

@ -0,0 +1,143 @@
/*
* 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;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import com.google.common.collect.Multimap;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
import net.minecraftforge.registries.RegistryManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
/**
* @author cpw
*
*/
public final class FMLWorldPersistenceHook implements WorldPersistenceHooks.WorldPersistenceHook
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker WORLDPERSISTENCE = MarkerManager.getMarker("WP");
@Override
public String getModId()
{
return "fml";
}
@Override
public NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info)
{
NBTTagCompound fmlData = new NBTTagCompound();
NBTTagList modList = new NBTTagList();
ModList.get().getMods().forEach(mi->
{
final NBTTagCompound mod = new NBTTagCompound();
mod.setString("ModId", mi.getModId());
mod.setString("ModVersion", mi.getVersion().getVersionString());
modList.appendTag(mod);
});
fmlData.setTag("LoadingModList", modList);
NBTTagCompound registries = new NBTTagCompound();
fmlData.setTag("Registries", registries);
LOGGER.debug(WORLDPERSISTENCE,"Gathering id map for writing to world save {}", info.getWorldName());
for (Map.Entry<ResourceLocation, ForgeRegistry.Snapshot> e : RegistryManager.ACTIVE.takeSnapshot(true).entrySet())
{
registries.setTag(e.getKey().toString(), e.getValue().write());
}
return fmlData;
}
@Override
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
{
if (tag.hasKey("LoadingModList"))
{
NBTTagList modList = tag.getTagList("LoadingModList", (byte)10);
for (int i = 0; i < modList.tagCount(); i++)
{
NBTTagCompound mod = modList.getCompoundTagAt(i);
String modId = mod.getString("ModId");
String modVersion = mod.getString("ModVersion");
Optional<? extends ModContainer> container = ModList.get().getModContainerById(modId);
if (!container.isPresent())
{
LOGGER.error(WORLDPERSISTENCE,"This world was saved with mod {} which appears to be missing, things may not work well", modId);
continue;
}
if (!modVersion.equals(container.get().getModInfo().getVersion().getVersionString()))
{
LOGGER.info(WORLDPERSISTENCE,"This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, container.get().getModInfo().getVersion().getVersionString());
}
}
}
Multimap<ResourceLocation, ResourceLocation> failedElements = null;
if (tag.hasKey("ModItemData") || tag.hasKey("ItemData")) // Pre 1.7
{
StartupQuery.notify("This save predates 1.7.10, it can no longer be loaded here. Please load in 1.7.10 or 1.8 first");
StartupQuery.abort();
}
else if (tag.hasKey("Registries")) // 1.8, genericed out the 'registries' list
{
Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot = new HashMap<>();
NBTTagCompound regs = tag.getCompoundTag("Registries");
for (String key : regs.getKeySet())
{
snapshot.put(new ResourceLocation(key), ForgeRegistry.Snapshot.read(regs.getCompoundTag(key)));
}
failedElements = GameData.injectSnapshot(snapshot, true, true);
}
if (failedElements != null && !failedElements.isEmpty())
{
StringBuilder buf = new StringBuilder();
buf.append("Forge Mod Loader could not load this save.\n\n")
.append("There are ").append(failedElements.size()).append(" unassigned registry entries in this save.\n")
.append("You will not be able to load until they are present again.\n\n");
failedElements.asMap().forEach((name, entries) ->
{
buf.append("Missing ").append(name).append(":\n");
entries.forEach(rl -> buf.append(" ").append(rl).append("\n"));
});
StartupQuery.notify(buf.toString());
StartupQuery.abort();
}
}
}

View File

@ -1,6 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
* 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
@ -17,16 +17,9 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraftforge.fml.common.patcher.ClassPatchManager;
public class PatchingTransformer implements IClassTransformer {
@Override
public byte[] transform(String name, String transformedName, byte[] bytes)
{
return ClassPatchManager.INSTANCE.applyPatch(name, transformedName, bytes);
}
package net.minecraftforge.fml;
public enum LogicalSide
{
CLIENT, SERVER
}

View File

@ -20,6 +20,7 @@
package net.minecraftforge.fml;
import net.minecraftforge.fml.language.IModInfo;
import net.minecraftforge.fml.network.Networking;
import java.util.ArrayList;
import java.util.HashMap;
@ -51,7 +52,6 @@ public abstract class ModContainer
protected final Map<ModLoadingStage, Consumer<LifecycleEventProvider.LifecycleEvent>> triggerMap;
protected final Map<ExtensionPoint, Supplier<?>> extensionPoints = new IdentityHashMap<>();
protected final List<Throwable> modLoadingError;
public ModContainer(IModInfo info)
{
this.modId = info.getModId();

View File

@ -39,6 +39,7 @@ import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.FutureTask;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -157,4 +158,9 @@ public class ModList
return modFileScanData;
}
public void forEachModFile(Consumer<ModFile> fileConsumer)
{
modFiles.stream().map(ModFileInfo::getFile).forEach(fileConsumer);
}
}

View File

@ -19,7 +19,8 @@
package net.minecraftforge.fml;
import net.minecraftforge.api.Side;
import com.google.common.collect.Streams;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager;
@ -32,6 +33,7 @@ import net.minecraftforge.registries.GameData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -39,6 +41,9 @@ import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static net.minecraftforge.fml.Logging.CORE;
public class ModLoader
{
@ -69,16 +74,30 @@ public class ModLoader
public void loadMods() {
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
modList.setLoadedMods(loadingModList.getModFiles().stream().
final ModContainer forgeModContainer;
try
{
forgeModContainer = (ModContainer)Class.forName("net.minecraftforge.common.ForgeModContainer", true, modClassLoader).
getConstructor(ModLoadingClassLoader.class).newInstance(modClassLoader);
}
catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException e)
{
LOGGER.error(CORE,"Unable to load the Forge Mod Container", e);
throw new RuntimeException(e);
}
final Stream<ModContainer> modContainerStream = loadingModList.getModFiles().stream().
map(ModFileInfo::getFile).
map(mf -> buildMods(mf, modClassLoader)).
flatMap(Collection::stream).collect(Collectors.toList()));
flatMap(Collection::stream);
modList.setLoadedMods(Streams.concat(Stream.of(forgeModContainer), modContainerStream).collect(Collectors.toList()));
LifecycleEventProvider.CONSTRUCT.dispatch();
WorldPersistenceHooks.addHook(new FMLWorldPersistenceHook());
WorldPersistenceHooks.addHook((WorldPersistenceHooks.WorldPersistenceHook)forgeModContainer.getMod());
GameData.fireCreateRegistryEvents();
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
LifecycleEventProvider.PREINIT.dispatch();
GameData.fireRegistryEvents(rl -> !Objects.equals(rl, GameData.RECIPES));
SidedExecutor.runOn(Side.CLIENT, ModLoader::fireClientEvents);
SidedExecutor.runOn(Dist.CLIENT, ModLoader::fireClientEvents);
LifecycleEventProvider.SIDEDINIT.dispatch();
}
@ -97,5 +116,7 @@ public class ModLoader
LifecycleEventProvider.INIT.dispatch();
LifecycleEventProvider.POSTINIT.dispatch();
LifecycleEventProvider.COMPLETE.dispatch();
GameData.freezeData();
}
}

View File

@ -27,9 +27,13 @@ public class ModThreadContext
return context.get();
}
private ModContainer currentContainer;
private ModContainer activeContainer;
public ModContainer getCurrentContainer() {
return currentContainer == null ? DefaultModContainers.MINECRAFT : currentContainer;
public void setActiveContainer(final ModContainer container) {
this.activeContainer = container;
}
public ModContainer getActiveContainer() {
return activeContainer == null ? DefaultModContainers.MINECRAFT : activeContainer;
}
}

View File

@ -20,7 +20,6 @@
package net.minecraftforge.fml;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.RegistryManager;

View File

@ -0,0 +1,156 @@
/*
* 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.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.handshake.client.C00Handshake;
import net.minecraft.network.login.server.SPacketDisconnect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.common.event.FMLServerStartedEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppedEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.network.NetworkHooks;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
public class ServerLifecycleHooks
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker SERVERHOOKS = MarkerManager.getMarker("SERVERHOOKS");
private static volatile CountDownLatch exitLatch = null;
private static MinecraftServer currentServer;
public static boolean handleServerAboutToStart(final MinecraftServer server)
{
currentServer = server;
return !MinecraftForge.EVENT_BUS.post(new FMLServerAboutToStartEvent(server));
}
public static boolean handleServerStarting(final MinecraftServer server)
{
return !MinecraftForge.EVENT_BUS.post(new FMLServerStartingEvent(server));
}
public static void handleServerStarted()
{
MinecraftForge.EVENT_BUS.post(new FMLServerStartedEvent());
allowLogins.set(true);
}
public static void handleServerStopping()
{
allowLogins.set(false);
MinecraftForge.EVENT_BUS.post(new FMLServerStoppingEvent());
}
public static void expectServerStopped()
{
exitLatch = new CountDownLatch(1);
}
public static void handleServerStopped(final MinecraftServer server)
{
MinecraftForge.EVENT_BUS.post(new FMLServerStoppedEvent());
currentServer = null;
CountDownLatch latch = exitLatch;
if (latch != null)
{
latch.countDown();
exitLatch = null;
}
}
public static MinecraftServer getCurrentServer()
{
return currentServer;
}
private static AtomicBoolean allowLogins = new AtomicBoolean(false);
public static boolean handleServerLogin(final C00Handshake packet, final NetworkManager manager) {
if (!allowLogins.get())
{
TextComponentString text = new TextComponentString("Server is still starting! Please wait before reconnecting.");
LOGGER.info(SERVERHOOKS,"Disconnecting Player (server is still starting): {}", text.getUnformattedText());
manager.sendPacket(new SPacketDisconnect(text));
manager.closeChannel(text);
return false;
}
if (packet.getRequestedState() == EnumConnectionState.LOGIN && !NetworkHooks.accepts(packet))
{
manager.setConnectionState(EnumConnectionState.LOGIN);
TextComponentString text = new TextComponentString("This server has mods that require Forge to be installed on the client. Contact your server admin for more details.");
List<String> modNames = net.minecraftforge.fml.network.NetworkRegistry.getNonVanillaNetworkMods();
LOGGER.info(SERVERHOOKS,"Disconnecting vanilla connection attempt. Required mods {}", modNames);
manager.sendPacket(new SPacketDisconnect(text));
manager.closeChannel(text);
return false;
}
manager.channel().attr(NetworkRegistry.FML_MARKER).set(packet.getFMLVersion());
return true;
}
public void handleExit(int retVal)
{
/*
CountDownLatch latch = exitLatch;
if (latch != null)
{
try
{
FMLLog.log.info("Waiting for the server to terminate/save.");
if (!latch.await(10, TimeUnit.SECONDS))
{
FMLLog.log.warn("The server didn't stop within 10 seconds, exiting anyway.");
}
else
{
FMLLog.log.info("Server terminated.");
}
}
catch (InterruptedException e)
{
FMLLog.log.warn("Interrupted wait, exiting.");
}
}
*/
System.exit(retVal);
}
}

View File

@ -19,7 +19,7 @@
package net.minecraftforge.fml;
import net.minecraftforge.api.Side;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.loading.FMLEnvironment;
import java.util.concurrent.Callable;
@ -32,13 +32,13 @@ public final class SidedExecutor
/**
* Run the callable in the supplier only on the specified {@link Side}
*
* @param side The side to run on
* @param toRun A supplier of the callable to run (Supplier wrapper to ensure classloading only on the appropriate side)
* @param dist The dist to run on
* @param toRun A supplier of the callable to run (Supplier wrapper to ensure classloading only on the appropriate dist)
* @param <T> The return type from the callable
* @return The callable's result
*/
public static <T> T runOn(Side side, Supplier<Callable<T>> toRun) {
if (side == FMLEnvironment.side) {
public static <T> T runOn(Dist dist, Supplier<Callable<T>> toRun) {
if (dist == FMLEnvironment.dist) {
try
{
return toRun.get().call();
@ -52,11 +52,11 @@ public final class SidedExecutor
}
public static <T> T runSided(Supplier<Supplier<T>> clientTarget, Supplier<Supplier<T>> serverTarget) {
switch (FMLEnvironment.side)
switch (FMLEnvironment.dist)
{
case CLIENT:
return clientTarget.get().get();
case SERVER:
case DEDICATED_SERVER:
return serverTarget.get().get();
default:
throw new IllegalArgumentException("UNSIDED?");

View File

@ -21,13 +21,12 @@ package net.minecraftforge.fml;
import net.minecraft.client.Minecraft;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraftforge.api.Side;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.client.SplashProgress;
import net.minecraftforge.fml.common.event.FMLClientInitEvent;
import net.minecraftforge.fml.common.event.FMLServerInitEvent;
import net.minecraftforge.fml.loading.FMLEnvironment;
import sun.plugin.security.StripClassFile;
import java.util.function.Function;
import java.util.function.Supplier;
@ -38,7 +37,8 @@ public enum SidedProvider
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)),
STRIPCHARS((Function<Supplier<Minecraft>, Function<String, String>>)c-> SplashProgress::stripSpecialChars,
(Function<Supplier<DedicatedServer>, Function<String, String>>)s-> str->str);
(Function<Supplier<DedicatedServer>, Function<String, String>>)s-> str->str),
STARTUPQUERY(StartupQuery::clientQuery, StartupQuery::dedicatedServerQuery);
private static Supplier<Minecraft> client;
private static Supplier<DedicatedServer> server;
@ -64,10 +64,10 @@ public enum SidedProvider
@SuppressWarnings("unchecked")
public <T> T get() {
if (FMLEnvironment.side == Side.CLIENT) {
if (FMLEnvironment.dist == Dist.CLIENT) {
return (T)this.clientSide.apply(client);
}
else if (FMLEnvironment.side == Side.SERVER) {
else if (FMLEnvironment.dist == Dist.DEDICATED_SERVER) {
return (T)this.serverSide.apply(server);
}
else {

View File

@ -0,0 +1,322 @@
/*
* 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 java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Supplier;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.dedicated.PendingCommand;
import net.minecraftforge.fml.client.gui.GuiConfirmation;
import net.minecraftforge.fml.client.gui.GuiNotification;
import net.minecraftforge.fml.common.thread.EffectiveSide;
import net.minecraftforge.fml.loading.FMLEnvironment;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import javax.annotation.Nullable;
public class StartupQuery {
// internal class/functionality, do not use
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker SQ = MarkerManager.getMarker("STARTUPQUERY");
public static boolean confirm(String text)
{
StartupQuery query = new StartupQuery(text, new AtomicBoolean());
query.execute();
return query.getResult();
}
private InterruptedException exception;
public static void notify(String text)
{
StartupQuery query = new StartupQuery(text, null);
query.execute();
}
public static void abort()
{
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
if (server != null) server.initiateShutdown();
aborted = true; // to abort loading and go back to the main menu
throw new AbortedException(); // to halt the server
}
public static void reset()
{
pending = null;
aborted = false;
}
public static boolean check()
{
if (pending != null)
{
try
{
try
{
SidedProvider.STARTUPQUERY.<Consumer<StartupQuery>>get().accept(pending);
}
catch (RuntimeException e)
{
}
pending.throwException();
}
catch (InterruptedException e)
{
LOGGER.warn(SQ, "query interrupted");
abort();
}
pending = null;
}
return !aborted;
}
private void throwException() throws InterruptedException
{
if (exception != null) throw exception;
}
private static volatile StartupQuery pending;
private static volatile boolean aborted = false;
private StartupQuery(String text, @Nullable AtomicBoolean result)
{
this.text = text;
this.result = result;
}
@Nullable
public Boolean getResult()
{
return result == null ? null : result.get();
}
public void setResult(boolean result)
{
this.result.set(result);
}
public String getText()
{
return text;
}
public boolean isSynchronous()
{
return synchronous;
}
public void finish()
{
signal.countDown();
}
private void execute()
{
String prop = System.getProperty("fml.queryResult");
if (result != null && prop != null)
{
LOGGER.info(SQ, "Using fml.queryResult {} to answer the following query:\n{}", prop, text);
if (prop.equalsIgnoreCase("confirm"))
{
setResult(true);
return;
}
else if (prop.equalsIgnoreCase("cancel"))
{
setResult(false);
return;
}
LOGGER.warn(SQ, "Invalid value for fml.queryResult: {}, expected confirm or cancel", prop);
}
synchronous = false;
pending = this; // let the other thread start the query
// from the integrated server thread: the client will eventually check pending and execute the query
// from the client thread: synchronous execution
// dedicated server: command handling in mc is synchronous, execute the server-side query directly
if (FMLEnvironment.dist.isDedicatedServer() || EffectiveSide.get() == LogicalSide.CLIENT)
{
synchronous = true;
check();
}
try
{
signal.await();
reset();
}
catch (InterruptedException e)
{
LOGGER.warn(SQ, "query interrupted");
abort();
}
}
private String text;
@Nullable
private AtomicBoolean result;
private CountDownLatch signal = new CountDownLatch(1);
private volatile boolean synchronous;
/**
* Exception not being caught by the crash report generation logic.
*/
public static class AbortedException extends RuntimeException
{
private static final long serialVersionUID = -5933665223696833921L;
private AbortedException()
{
super();
}
}
public static Consumer<StartupQuery> clientQuery(Supplier<Minecraft> clientSupplier)
{
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)
{
if (Thread.interrupted()) {
query.exception = new InterruptedException();
throw new RuntimeException();
}
client.loadingScreen.displayLoadingString("");
try
{
Thread.sleep(50);
} catch (InterruptedException ie) {
query.exception = ie;
}
}
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 (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();
}
};
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.fml.common.thread.EffectiveSide;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WorldPersistenceHooks
{
private static List<WorldPersistenceHook> worldPersistenceHooks = new ArrayList<>();
public static void addHook(WorldPersistenceHook hook) {
worldPersistenceHooks.add(hook);
}
public static void handleWorldDataSave(final SaveHandler handler, final WorldInfo worldInfo, final NBTTagCompound tagCompound)
{
worldPersistenceHooks.forEach(wac->tagCompound.setTag(wac.getModId(), wac.getDataForWriting(handler, worldInfo)));
}
public static void handleWorldDataLoad(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
{
if (EffectiveSide.get() == LogicalSide.SERVER)
{
Map<String, NBTBase> additionalProperties = new HashMap<>();
worldInfo.setAdditionalProperties(additionalProperties);
worldPersistenceHooks.forEach(wac->wac.readData(handler, worldInfo, additionalProperties, tagCompound.getCompoundTag(wac.getModId())));
}
}
public static void confirmBackupLevelDatUse(SaveHandler handler)
{
/*
if (handlerToCheck == null || handlerToCheck.get() != handler) {
// only run if the save has been initially loaded
handlerToCheck = null;
return;
}
String text = "Forge Mod Loader detected that the backup level.dat is being used.\n\n" +
"This may happen due to a bug or corruption, continuing can damage\n" +
"your world beyond repair or lose data / progress.\n\n" +
"It's recommended to create a world backup before continuing.";
boolean confirmed = StartupQuery.confirm(text);
if (!confirmed) StartupQuery.abort();
*/
}
public interface WorldPersistenceHook
{
String getModId();
NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info);
void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag);
}
}

View File

@ -0,0 +1,197 @@
/*
* 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 com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonArray;
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.GuiWorldSelection;
import net.minecraft.client.gui.ServerListEntryNormal;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.ServerStatusResponse;
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.common.network.internal.FMLNetworkHandler;
import net.minecraftforge.registries.GameData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
public class ClientHooks
{
private static final Logger LOGGER = LogManager.getLogger("FML");
private static final Marker CLIENTHOOKS = MarkerManager.getMarker("CLIENTHOOKS");
private static Map<ServerStatusResponse,JsonObject> extraServerListData;
private static Map<ServerData, ExtendedServerListData> serverDataTag;
public static void setupServerList()
{
extraServerListData = Collections.synchronizedMap(new HashMap<>());
serverDataTag = Collections.synchronizedMap(new HashMap<>());
}
public static void captureAdditionalData(ServerStatusResponse serverstatusresponse, JsonObject jsonobject)
{
if (jsonobject.has("modinfo"))
{
JsonObject fmlData = jsonobject.get("modinfo").getAsJsonObject();
extraServerListData.put(serverstatusresponse, fmlData);
}
}
public static void bindServerListData(ServerData data, ServerStatusResponse originalResponse)
{
if (extraServerListData.containsKey(originalResponse))
{
JsonObject jsonData = extraServerListData.get(originalResponse);
String type = jsonData.get("type").getAsString();
JsonArray modDataArray = jsonData.get("modList").getAsJsonArray();
boolean moddedClientAllowed = !jsonData.has("clientModsAllowed") || jsonData.get("clientModsAllowed").getAsBoolean();
ImmutableMap.Builder<String, String> modListBldr = ImmutableMap.builder();
for (JsonElement obj : modDataArray)
{
JsonObject modObj = obj.getAsJsonObject();
modListBldr.put(modObj.get("modid").getAsString(), modObj.get("version").getAsString());
}
Map<String,String> modListMap = modListBldr.build();
String modRejections = FMLNetworkHandler.checkModList(modListMap, LogicalSide.SERVER);
serverDataTag.put(data, new ExtendedServerListData(type, modRejections == null, modListMap, !moddedClientAllowed));
}
else
{
String serverDescription = data.serverMOTD;
boolean moddedClientAllowed = true;
if (!Strings.isNullOrEmpty(serverDescription))
{
moddedClientAllowed = !serverDescription.endsWith(":NOFML§r");
}
serverDataTag.put(data, new ExtendedServerListData("VANILLA", false, ImmutableMap.of(), !moddedClientAllowed));
}
startupConnectionData.countDown();
}
private static final ResourceLocation iconSheet = new ResourceLocation("fml:textures/gui/icons.png");
private static final CountDownLatch startupConnectionData = new CountDownLatch(1);
@Nullable
public static String enhanceServerListEntry(ServerListEntryNormal serverListEntry, ServerData serverEntry, int x, int width, int y, int relativeMouseX, int relativeMouseY)
{
String tooltip;
int idx;
boolean blocked = false;
if (serverDataTag.containsKey(serverEntry))
{
ExtendedServerListData extendedData = serverDataTag.get(serverEntry);
if ("FML".equals(extendedData.type) && extendedData.isCompatible)
{
idx = 0;
tooltip = String.format("Compatible FML modded server\n%d mods present", extendedData.modData.size());
}
else if ("FML".equals(extendedData.type) && !extendedData.isCompatible)
{
idx = 16;
tooltip = String.format("Incompatible FML modded server\n%d mods present", extendedData.modData.size());
}
else if ("BUKKIT".equals(extendedData.type))
{
idx = 32;
tooltip = String.format("Bukkit modded server");
}
else if ("VANILLA".equals(extendedData.type))
{
idx = 48;
tooltip = String.format("Vanilla server");
}
else
{
idx = 64;
tooltip = String.format("Unknown server data");
}
blocked = extendedData.isBlocked;
}
else
{
return null;
}
Minecraft.getMinecraft().getTextureManager().bindTexture(iconSheet);
Gui.drawModalRectWithCustomSizedTexture(x + width - 18, y + 10, 0, (float)idx, 16, 16, 256.0f, 256.0f);
if (blocked)
{
Gui.drawModalRectWithCustomSizedTexture(x + width - 18, y + 10, 0, 80, 16, 16, 256.0f, 256.0f);
}
return relativeMouseX > width - 15 && relativeMouseX < width && relativeMouseY > 10 && relativeMouseY < 26 ? tooltip : null;
}
public static String fixDescription(String description)
{
return description.endsWith(":NOFML§r") ? description.substring(0, description.length() - 8)+"§r" : description;
}
static File getSavesDir()
{
return new File(Minecraft.getMinecraft().mcDataDir, "saves");
}
public static void tryLoadExistingWorld(GuiWorldSelection selectWorldGUI, WorldSummary comparator)
{
try
{
Minecraft.getMinecraft().launchIntegratedServer(comparator.getFileName(), comparator.getDisplayName(), null);
}
catch (StartupQuery.AbortedException e)
{
// ignore
}
}
private static NetworkManager getClientToServerNetworkManager()
{
return Minecraft.getMinecraft().getConnection()!=null ? Minecraft.getMinecraft().getConnection().getNetworkManager() : null;
}
public static void handleClientWorldClosing(WorldClient world)
{
NetworkManager client = getClientToServerNetworkManager();
// ONLY revert a non-local connection
if (client != null && !client.isLocalChannel())
{
GameData.revertToFrozen();
}
}
}

View File

@ -25,8 +25,8 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.data.MetadataSerializer;
import net.minecraftforge.api.Side;
import net.minecraftforge.api.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.SidedProvider;
import net.minecraftforge.fml.VersionChecker;
import net.minecraftforge.fml.ModLoader;
@ -37,7 +37,7 @@ import org.lwjgl.input.Mouse;
import java.io.IOException;
import java.util.List;
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public class ClientModLoader
{
private static boolean loading;

View File

@ -113,14 +113,12 @@ import net.minecraftforge.fml.common.MetadataCollection;
import net.minecraftforge.fml.common.MissingModsException;
import net.minecraftforge.fml.common.MultipleModsErrored;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModMetadata;
import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.StartupQuery;
import net.minecraftforge.fml.common.WrongMinecraftVersionException;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
import net.minecraftforge.fml.common.toposort.ModSortingException;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.registries.GameData;
import org.lwjgl.input.Mouse;

View File

@ -21,11 +21,10 @@ package net.minecraftforge.fml.client.gui;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiErrorScreen;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.common.EnhancedRuntimeException;
import net.minecraftforge.fml.common.IFMLHandledException;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
/**
* If a mod throws this exception during loading, it will be called back to render
@ -37,7 +36,7 @@ import net.minecraftforge.fml.relauncher.SideOnly;
* @author cpw
*
*/
@SideOnly(Side.CLIENT)
@OnlyIn(Dist.CLIENT)
public abstract class CustomModLoadingErrorDisplayException extends EnhancedRuntimeException implements IFMLHandledException, IDisplayableError
{
public CustomModLoadingErrorDisplayException() {

View File

@ -23,7 +23,7 @@ import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiOptionButton;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.StartupQuery;
public class GuiConfirmation extends GuiNotification
{

View File

@ -23,7 +23,7 @@ import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.StartupQuery;
public class GuiNotification extends GuiScreen
{

View File

@ -28,7 +28,7 @@ import net.minecraft.client.gui.GuiYesNo;
import net.minecraft.client.gui.GuiYesNoCallback;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.StartupQuery;
import net.minecraftforge.fml.StartupQuery;
import net.minecraftforge.fml.common.ZipperUtil;
public class GuiOldSaveLoadConfirm extends GuiYesNo implements GuiYesNoCallback {

View File

@ -52,7 +52,10 @@ import net.minecraftforge.client.model.animation.Animation;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.fml.client.BrandingControl;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.StartupQuery;
import net.minecraftforge.fml.WorldPersistenceHooks;
import net.minecraftforge.fml.BrandingControl;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.common.gameevent.InputEvent;
@ -63,7 +66,6 @@ import net.minecraftforge.fml.common.network.FMLNetworkEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.thread.SidedThreadGroup;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.server.FMLServerHandler;
import org.apache.logging.log4j.Logger;
@ -320,7 +322,7 @@ public class FMLCommonHandler
{
if (mc instanceof InjectedModContainer)
{
WorldAccessContainer wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
WorldPersistenceHooks.WorldPersistenceHook wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
if (wac != null)
{
NBTTagCompound dataForWriting = wac.getDataForWriting(handler, worldInfo);
@ -332,7 +334,7 @@ public class FMLCommonHandler
public void handleWorldDataLoad(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
{
if (getEffectiveSide()!=Side.SERVER)
if (getEffectiveSide()!=LogicalSide.SERVER)
{
return;
}
@ -348,7 +350,7 @@ public class FMLCommonHandler
{
if (mc instanceof InjectedModContainer)
{
WorldAccessContainer wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
WorldPersistenceHooks.WorldPersistenceHook wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
if (wac != null)
{
wac.readData(handler, worldInfo, additionalProperties, tagCompound.getCompoundTag(mc.getModId()));
@ -564,7 +566,7 @@ public class FMLCommonHandler
if (!shouldAllowPlayerLogins())
{
TextComponentString text = new TextComponentString("Server is still starting! Please wait before reconnecting.");
FMLLog.log.info("Disconnecting Player: {}", text.getUnformattedText());
LOGGER.info("Disconnecting Player: {}", text.getUnformattedText());
manager.sendPacket(new SPacketDisconnect(text));
manager.closeChannel(text);
return false;

View File

@ -1,227 +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.common;
import java.io.File;
import java.security.cert.Certificate;
import java.util.Arrays;
import java.util.Map;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.fml.client.FMLFileResourcePack;
import net.minecraftforge.fml.client.FMLFolderResourcePack;
import net.minecraftforge.fml.common.asm.FMLSanityChecker;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.network.NetworkCheckHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLNetworkHandler;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.GameData;
import net.minecraftforge.registries.RegistryManager;
import org.apache.logging.log4j.LogManager;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
/**
* @author cpw
*
*/
public final class FMLContainer extends DummyModContainer implements WorldAccessContainer
{
private static final Logger modTrackerLogger = LogManager.getLogger("FML.ModTracker");
public FMLContainer()
{
super(new ModMetadata());
ModMetadata meta = getMetadata();
meta.modId="FML";
meta.name="Forge Mod Loader";
meta.version=Loader.instance().getFMLVersionString();
meta.credits="Made possible with help from many people";
meta.authorList=Arrays.asList("cpw", "LexManos", "Player");
meta.description="The Forge Mod Loader provides the ability for systems to load mods " +
"from the file system. It also provides key capabilities for mods to be able " +
"to cooperate and provide a good modding environment. ";
meta.url="https://github.com/MinecraftForge/FML/wiki";
meta.screenshots=new String[0];
meta.logoFile="";
}
@Override
public boolean registerBus(EventBus bus, LoadController controller)
{
bus.register(this);
return true;
}
@Subscribe
public void modConstruction(FMLConstructionEvent evt)
{
NetworkRegistry.INSTANCE.register(this, this.getClass(), null, evt.getASMHarvestedData());
FMLNetworkHandler.registerChannel(this, evt.getSide());
}
@Subscribe
public void modPreinitialization(FMLPreInitializationEvent evt)
{
// Initialize all Forge/Vanilla registries {invoke the static init)
if (ForgeRegistries.ITEMS == null)
throw new RuntimeException("Something horrible went wrong in init, ForgeRegistres didn't create...");
}
@NetworkCheckHandler
public boolean checkModLists(Map<String,String> modList, Side side)
{
return Loader.instance().checkRemoteModList(modList,side);
}
@Override
public NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info)
{
NBTTagCompound fmlData = new NBTTagCompound();
NBTTagList modList = new NBTTagList();
for (ModContainer mc : Loader.instance().getActiveModList())
{
NBTTagCompound mod = new NBTTagCompound();
mod.setString("ModId", mc.getModId());
mod.setString("ModVersion", mc.getVersion());
modList.appendTag(mod);
}
fmlData.setTag("LoadingModList", modList);
NBTTagCompound registries = new NBTTagCompound();
fmlData.setTag("Registries", registries);
FMLLog.log.debug("Gathering id map for writing to world save {}", info.getWorldName());
for (Map.Entry<ResourceLocation, ForgeRegistry.Snapshot> e : RegistryManager.ACTIVE.takeSnapshot(true).entrySet())
{
registries.setTag(e.getKey().toString(), e.getValue().write());
}
return fmlData;
}
@Override
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
{
if (tag.hasKey("LoadingModList"))
{
NBTTagList modList = tag.getTagList("LoadingModList", (byte)10);
for (int i = 0; i < modList.tagCount(); i++)
{
NBTTagCompound mod = modList.getCompoundTagAt(i);
String modId = mod.getString("ModId");
String modVersion = mod.getString("ModVersion");
ModContainer container = Loader.instance().getIndexedModList().get(modId);
if (container == null)
{
modTrackerLogger.error("This world was saved with mod {} which appears to be missing, things may not work well", modId);
continue;
}
if (!modVersion.equals(container.getVersion()))
{
modTrackerLogger.info("This world was saved with mod {} version {} and it is now at version {}, things may not work well", modId, modVersion, container.getVersion());
}
}
}
Multimap<ResourceLocation, ResourceLocation> failedElements = null;
if (tag.hasKey("ModItemData") || tag.hasKey("ItemData")) // Pre 1.7
{
StartupQuery.notify("This save predates 1.7.10, it can no longer be loaded here. Please load in 1.7.10 or 1.8 first");
StartupQuery.abort();
}
else if (tag.hasKey("Registries")) // 1.8, genericed out the 'registries' list
{
Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot = Maps.newHashMap();
NBTTagCompound regs = tag.getCompoundTag("Registries");
for (String key : regs.getKeySet())
{
snapshot.put(new ResourceLocation(key), ForgeRegistry.Snapshot.read(regs.getCompoundTag(key)));
}
failedElements = GameData.injectSnapshot(snapshot, true, true);
}
if (failedElements != null && !failedElements.isEmpty())
{
StringBuilder buf = new StringBuilder();
buf.append("Forge Mod Loader could not load this save.\n\n")
.append("There are ").append(failedElements.size()).append(" unassigned registry entries in this save.\n")
.append("You will not be able to load until they are present again.\n\n");
failedElements.asMap().forEach((name, entries) ->
{
buf.append("Missing ").append(name).append(":\n");
entries.forEach(rl -> buf.append(" ").append(rl).append("\n"));
});
StartupQuery.notify(buf.toString());
StartupQuery.abort();
}
}
@Override
@Nullable
public Certificate getSigningCertificate()
{
Certificate[] certificates = getClass().getProtectionDomain().getCodeSource().getCertificates();
return certificates != null ? certificates[0] : null;
}
@Override
public File getSource()
{
return FMLSanityChecker.fmlLocation;
}
@Override
public Class<?> getCustomResourcePackClass()
{
return getSource().isDirectory() ? FMLFolderResourcePack.class : FMLFileResourcePack.class;
}
@Override
public String getGuiClassName()
{
return "net.minecraftforge.fml.client.FMLConfigGuiFactory";
}
@Override
public Object getMod()
{
return this;
}
}

View File

@ -19,12 +19,15 @@
package net.minecraftforge.fml.common;
import java.util.Locale;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.FMLRelaunchLog;
import net.minecraftforge.api.distmarker.Dist;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
/**
* FMLs logging class. <b>Internal use only, NOT FOR MOD LOGGING!</b> Mods use your own log, see {@link FMLPreInitializationEvent#getModLog()}.

View File

@ -30,7 +30,7 @@ import net.minecraft.util.IThreadListener;
import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.StartupQuery;
public interface IFMLSidedHandler
{

View File

@ -1,216 +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.common;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
public interface ILanguageAdapter {
Object getNewInstance(FMLModContainer container, Class<?> objectClass, ClassLoader classLoader, Method factoryMarkedAnnotation) throws Exception;
boolean supportsStatics();
void setProxy(Field target, Class<?> proxyTarget, Object proxy) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException;
void setInternalProxies(ModContainer mod, Side side, ClassLoader loader);
public static class ScalaAdapter implements ILanguageAdapter {
@Override
public Object getNewInstance(FMLModContainer container, Class<?> scalaObjectClass, ClassLoader classLoader, Method factoryMarkedAnnotation) throws Exception
{
Class<?> sObjectClass = Class.forName(scalaObjectClass.getName()+"$",true,classLoader);
return sObjectClass.getField("MODULE$").get(null);
}
@Override
public boolean supportsStatics()
{
return false;
}
@Override
public void setProxy(Field target, Class<?> proxyTarget, Object proxy) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException
{
try
{
// Get the actual singleton class. The two variants are from
// whether the @SidedProxy is declared in a the class block
// of the object directly, or in the object block, i.e.
// whether it's:
// class ModName {
// @SidedProxy ...
// }
// object ModName extends ModName {}
// which leads to us getting the outer class, or
// object ModName {
// @SidedProxy ...
// }
// which leads to us getting the inner class.
if (!proxyTarget.getName().endsWith("$"))
{
// Get internal class generated by Scala.
proxyTarget = Class.forName(proxyTarget.getName() + "$", true, proxyTarget.getClassLoader());
}
}
catch (ClassNotFoundException e)
{
// Not a singleton, look for @Instance field as a fallback.
FMLLog.log.info("An error occurred trying to load a proxy into {}.{}. Did you declare your mod as 'class' instead of 'object'?", proxyTarget.getSimpleName(), target.getName(), e);
return;
}
// Get the instance via the MODULE$ field which is
// automatically generated by the Scala compiler for
// singletons.
Object targetInstance = proxyTarget.getField("MODULE$").get(null);
try
{
// Find setter function. We do it this way because we can't
// necessarily use proxyTarget.getMethod(proxy.getClass()), as
// it might be a subclass and not the exact parameter type.
// All fields are private in Scala, wrapped by a getter and
// setter named <fieldname> and <fieldname>_$eq. To those
// familiar with scala.reflect.BeanProperty: these will always
// be there, set<Fieldname> and get<Fieldname> will always
// only be generated *additionally*.
final String setterName = target.getName() + "_$eq";
for (Method setter : proxyTarget.getMethods())
{
Class<?>[] setterParameters = setter.getParameterTypes();
if (setterName.equals(setter.getName()) &&
// Some more validation.
setterParameters.length == 1 &&
setterParameters[0].isAssignableFrom(proxy.getClass()))
{
// Here goes nothing...
setter.invoke(targetInstance, proxy);
return;
}
}
}
catch (InvocationTargetException e)
{
FMLLog.log.error("An error occurred trying to load a proxy into {}.{}", target.getName(), e);
throw new LoaderException(e);
}
// If we come here we could not find a setter for this proxy.
FMLLog.log.fatal("Failed loading proxy into {}.{}, could not find setter function. Did you declare the field with 'val' instead of 'var'?", proxyTarget.getSimpleName(), target.getName());
throw new LoaderException(String.format("Failed loading proxy into %s.%s, could not find setter function. Did you declare the field with 'val' instead of 'var'?", proxyTarget.getSimpleName(), target.getName()));
}
@Override
public void setInternalProxies(ModContainer mod, Side side, ClassLoader loader)
{
// For Scala mods, we want to enable authors to write them like so:
// object ModName {
// @SidedProxy(...)
// var proxy: ModProxy = null
// }
// For this to work, we have to search inside the inner class Scala
// generates for singletons, which is in called ModName$. These are
// not automatically handled, because the mod discovery code ignores
// internal classes.
// Note that it is alternatively possible to write this like so:
// class ModName {
// @SidedProxy(...)
// var proxy: ModProxy = null
// }
// object ModName extends ModName { ... }
// which will fall back to the normal injection code which calls
// setProxy in turn.
// Get the actual mod implementation, which will be the inner class
// if we have a singleton.
Class<?> proxyTarget = mod.getMod().getClass();
if (proxyTarget.getName().endsWith("$"))
{
// So we have a singleton class, check if there are targets.
for (Field target : proxyTarget.getDeclaredFields())
{
// This will not turn up anything if the alternative
// approach was taken (manually declaring the class).
// So we don't initialize the field twice.
if (target.getAnnotation(SidedProxy.class) != null)
{
String targetType = side.isClient() ? target.getAnnotation(SidedProxy.class).clientSide() : target.getAnnotation(SidedProxy.class).serverSide();
try
{
Object proxy = Class.forName(targetType, true, loader).newInstance();
if (!target.getType().isAssignableFrom(proxy.getClass()))
{
FMLLog.log.fatal("Attempted to load a proxy type {} into {}.{}, but the types don't match", targetType, proxyTarget.getSimpleName(), target.getName());
throw new LoaderException(String.format("Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, proxyTarget.getSimpleName(), target.getName()));
}
setProxy(target, proxyTarget, proxy);
}
catch (Exception e) {
FMLLog.log.error("An error occurred trying to load a proxy into {}.{}", target.getName(), e);
throw new LoaderException(e);
}
}
}
}
else
{
FMLLog.log.trace("Mod does not appear to be a singleton.");
}
}
}
public static class JavaAdapter implements ILanguageAdapter {
@Override
public Object getNewInstance(FMLModContainer container, Class<?> objectClass, ClassLoader classLoader, Method factoryMarkedMethod) throws Exception
{
if (factoryMarkedMethod != null)
{
return factoryMarkedMethod.invoke(null);
}
else
{
return objectClass.newInstance();
}
}
@Override
public boolean supportsStatics()
{
return true;
}
@Override
public void setProxy(Field target, Class<?> proxyTarget, Object proxy) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException,
SecurityException
{
target.set(null, proxy);
}
@Override
public void setInternalProxies(ModContainer mod, Side side, ClassLoader loader)
{
// Nothing to do here.
}
}
}

View File

@ -29,7 +29,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraftforge.common.util.TextTable;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import net.minecraftforge.fml.common.event.FMLLoadEvent;

View File

@ -41,14 +41,9 @@ import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.fml.common.LoaderState.ModState;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModContainer.Disableable;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ContainerType;
import net.minecraftforge.fml.common.discovery.ModCandidate;
import net.minecraftforge.fml.common.discovery.ModDiscoverer;
import net.minecraftforge.fml.common.event.FMLInterModComms;
import net.minecraftforge.fml.common.event.FMLLoadEvent;
import net.minecraftforge.fml.common.event.FMLModIdMappingEvent;
@ -60,11 +55,8 @@ import net.minecraftforge.fml.common.toposort.ModSortingException.SortingExcepti
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.common.versioning.DependencyParser;
import net.minecraftforge.fml.common.versioning.VersionParser;
import net.minecraftforge.fml.relauncher.CoreModManager;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.libraries.Artifact;
import net.minecraftforge.fml.relauncher.libraries.LibraryManager;
import net.minecraftforge.fml.relauncher.libraries.Repository;
import net.minecraftforge.fml.relauncher.ModListHelper;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.registries.GameData;
import net.minecraftforge.registries.ObjectHolderRegistry;

View File

@ -1,138 +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.common;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;
import net.minecraftforge.fml.common.event.FMLServerStartedEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppedEvent;
import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
import net.minecraftforge.fml.common.event.FMLStateEvent;
/**
* The state enum used to help track state progression for the loader
* @author cpw
*
*/
public enum LoaderState
{
NOINIT("Uninitialized",null),
LOADING("Loading",null),
CONSTRUCTING("Constructing mods",FMLConstructionEvent.class),
PREINITIALIZATION("Pre-initializing mods", FMLPreInitializationEvent.class),
INITIALIZATION("Initializing mods", FMLInitializationEvent.class),
POSTINITIALIZATION("Post-initializing mods", FMLPostInitializationEvent.class),
AVAILABLE("Mod loading complete", FMLLoadCompleteEvent.class),
SERVER_ABOUT_TO_START("Server about to start", FMLServerAboutToStartEvent.class),
SERVER_STARTING("Server starting", FMLServerStartingEvent.class),
SERVER_STARTED("Server started", FMLServerStartedEvent.class),
SERVER_STOPPING("Server stopping", FMLServerStoppingEvent.class),
SERVER_STOPPED("Server stopped", FMLServerStoppedEvent.class),
ERRORED("Mod Loading errored",null);
private Class<? extends FMLStateEvent> eventClass;
private String name;
private LoaderState(String name, Class<? extends FMLStateEvent> event)
{
this.name = name;
this.eventClass = event;
}
public LoaderState transition(boolean errored)
{
if (errored)
{
return ERRORED;
}
// stopping -> available
if (this == SERVER_STOPPED)
{
return AVAILABLE;
}
return values()[ordinal() < values().length ? ordinal()+1 : ordinal()];
}
public boolean hasEvent()
{
return eventClass != null;
}
public FMLStateEvent getEvent(Object... eventData)
{
try
{
return eventClass.getConstructor(Object[].class).newInstance((Object)eventData);
}
catch (ReflectiveOperationException e)
{
throw new RuntimeException(e);
}
}
public LoaderState requiredState()
{
if (this == NOINIT) return NOINIT;
return LoaderState.values()[this.ordinal()-1];
}
public String getPrettyName()
{
return name;
}
public enum ModState
{
UNLOADED ("Unloaded", "U"),
LOADED ("Loaded", "L"),
CONSTRUCTED ("Constructed", "C"),
PREINITIALIZED ("Pre-initialized", "H"),
INITIALIZED ("Initialized", "I"),
POSTINITIALIZED("Post-initialized", "J"),
AVAILABLE ("Available", "A"),
DISABLED ("Disabled", "D"),
ERRORED ("Errored", "E");
private String label;
private String marker;
private ModState(String label, String marker)
{
this.label = label;
this.marker = marker;
}
@Override
public String toString()
{
return this.label;
}
public String getMarker()
{
return this.marker;
}
}
}

View File

@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import net.minecraftforge.api.Side;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.common.event.ModLifecycleEvent;
import net.minecraftforge.fml.common.event.FMLFingerprintViolationEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
@ -108,7 +108,7 @@ public @interface Mod
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface EventBusSubscriber {
Side[] value() default { Side.CLIENT, Side.SERVER };
Dist[] value() default { Dist.CLIENT, Dist.DEDICATED_SERVER };
/**
* Optional value, only nessasary if tis annotation is not on the same class that has a @Mod annotation.

View File

@ -32,10 +32,6 @@ import java.util.Set;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.common.asm.transformers.ModAPITransformer;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import org.apache.logging.log4j.Level;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

View File

@ -1,90 +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.common;
import java.io.File;
import java.lang.reflect.Constructor;
import java.util.Map;
import net.minecraftforge.fml.common.discovery.ModCandidate;
import net.minecraftforge.fml.common.discovery.asm.ASMModParser;
import net.minecraftforge.fml.javafmlmod.FMLModContainer;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation;
import org.objectweb.asm.Type;
import com.google.common.collect.Maps;
import javax.annotation.Nullable;
public class ModContainerFactory
{
public static Map<Type, Constructor<? extends ModContainer>> modTypes = Maps.newHashMap();
private static ModContainerFactory INSTANCE = new ModContainerFactory();
private ModContainerFactory() {
// We always know about Mod type
registerContainerType(Type.getType(Mod.class), FMLModContainer.class);
}
public static ModContainerFactory instance() {
return INSTANCE;
}
public void registerContainerType(Type type, Class<? extends ModContainer> container)
{
try
{
Constructor<? extends ModContainer> constructor = container.getConstructor(new Class<?>[] { String.class, ModCandidate.class, Map.class });
modTypes.put(type, constructor);
}
catch (Exception e)
{
throw new RuntimeException("Critical error : cannot register mod container type " + container.getName() + ", it has an invalid constructor", e);
}
}
@Nullable
public ModContainer build(ASMModParser modParser, File modSource, ModCandidate container)
{
String className = modParser.getASMType().getClassName();
for (ModAnnotation ann : modParser.getAnnotations())
{
if (modTypes.containsKey(ann.getASMType()))
{
FMLLog.log.debug("Identified a mod of type {} ({}) - loading", ann.getASMType(), className);
try {
ModContainer ret = modTypes.get(ann.getASMType()).newInstance(className, container, ann.getValues());
if (!ret.shouldLoadInEnvironment())
{
FMLLog.log.debug("Skipping mod {}, container opted to not load.", className);
return null;
}
return ret;
} catch (Exception e) {
FMLLog.log.error("Unable to construct {} container", ann.getASMType().getClassName(), e);
return null;
}
}
}
return null;
}
}

View File

@ -1,94 +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.common;
import java.util.List;
import java.util.Set;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gson.annotations.SerializedName;
import net.minecraftforge.fml.ModContainer;
/**
* @author cpw
*
*/
public class ModMetadata
{
@SerializedName("modid")
public String modId;
public String name;
public String description = "";
public String url = "";
@Deprecated //Never really used for anything and format is undefined. See updateJSON for replacement.
public String updateUrl = "";
/**
* URL to update json file. Format is defined here: https://gist.github.com/LexManos/7aacb9aa991330523884
*/
public String updateJSON = "";
public String logoFile = "";
public String version = "";
public List<String> authorList = Lists.newArrayList();
public String credits = "";
public String parent = "";
public String[] screenshots;
// this field is not for use in the json
public transient ModContainer parentMod;
// this field is not for use in the json
public transient List<ModContainer> childMods = Lists.newArrayList();
public boolean useDependencyInformation;
public Set<ArtifactVersion> requiredMods = Sets.newHashSet();
public List<ArtifactVersion> dependencies = Lists.newArrayList();
public List<ArtifactVersion> dependants = Lists.newArrayList();
// this field is not for use in the json
public transient boolean autogenerated;
public ModMetadata()
{
}
public String getChildModCountString()
{
return String.format("%d child mod%s", childMods.size(), childMods.size() != 1 ? "s" : "");
}
public String getAuthorList()
{
return Joiner.on(", ").join(authorList);
}
public String getChildModList()
{
return Joiner.on(", ").join(childMods.stream().map(ModContainer::getName).iterator());
}
public String printableSortingRules()
{
return "";
}
}

View File

@ -21,13 +21,11 @@ package net.minecraftforge.fml.common;
import java.util.Arrays;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.common.asm.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.ReflectionHelper.UnableToAccessFieldException;
import net.minecraftforge.fml.relauncher.ReflectionHelper.UnableToFindFieldException;
import org.apache.logging.log4j.Level;
/**
* Some reflection helper code.
*

View File

@ -26,7 +26,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.stream.Collectors;
import net.minecraftforge.api.Side;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.SidedExecutor;
import net.minecraftforge.fml.SidedProvider;
import net.minecraftforge.fml.client.SplashProgress;
@ -62,7 +62,7 @@ public class ProgressManager
{
bar.timeEachStep();
}
SidedExecutor.runOn(Side.CLIENT, ()->SplashProgress::processMessages);
SidedExecutor.runOn(Dist.CLIENT, ()->SplashProgress::processMessages);
return bar;
}
@ -87,7 +87,7 @@ public class ProgressManager
else
fmlLog.debug(SPLASH, () -> new MessageFormatMessage("Bar Finished: {0} took {1,number,0.000}ms", bar.getTitle(), (newTime - bar.lastTime) / 1.0e6));
}
SidedExecutor.runOn(Side.CLIENT, ()->SplashProgress::processMessages);
SidedExecutor.runOn(Dist.CLIENT, ()->SplashProgress::processMessages);
}
/*

View File

@ -1,108 +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.common;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Set;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import com.google.common.base.Strings;
import com.google.common.collect.SetMultimap;
/**
* @author cpw
*
*/
public class ProxyInjector
{
public static void inject(ModContainer mod, ASMDataTable data, Side side, ILanguageAdapter languageAdapter)
{
FMLLog.log.debug("Attempting to inject @SidedProxy classes into {}", mod.getModId());
SetMultimap<String, ASMData> modData = data.getAnnotationsFor(mod);
Set<ASMData> mods = modData.get(Mod.class.getName());
Set<ASMData> targets = modData.get(SidedProxy.class.getName());
ClassLoader mcl = Loader.instance().getModClassLoader();
for (ASMData targ : targets)
{
try
{
String amodid = (String)targ.getAnnotationInfo().get("modId");
if (Strings.isNullOrEmpty(amodid))
{
amodid = ASMDataTable.getOwnerModID(mods, targ);
if (Strings.isNullOrEmpty(amodid))
{
FMLLog.bigWarning("Could not determine owning mod for @SidedProxy on {} for mod {}", targ.getClassName(), mod.getModId());
continue;
}
}
if (!mod.getModId().equals(amodid))
{
FMLLog.log.debug("Skipping proxy injection for {}.{} since it is not for mod {}", targ.getClassName(), targ.getObjectName(), mod.getModId());
continue;
}
Class<?> proxyTarget = Class.forName(targ.getClassName(), true, mcl);
Field target = proxyTarget.getDeclaredField(targ.getObjectName());
if (target == null)
{
// Impossible?
FMLLog.log.fatal("Attempted to load a proxy type into {}.{} but the field was not found", targ.getClassName(), targ.getObjectName());
throw new LoaderException(String.format("Attempted to load a proxy type into %s.%s but the field was not found", targ.getClassName(), targ.getObjectName()));
}
target.setAccessible(true);
SidedProxy annotation = target.getAnnotation(SidedProxy.class);
String targetType = side.isClient() ? annotation.clientSide() : annotation.serverSide();
if(targetType.equals(""))
{
targetType = targ.getClassName() + (side.isClient() ? "$ClientProxy" : "$ServerProxy");
}
Object proxy=Class.forName(targetType, true, mcl).newInstance();
if (languageAdapter.supportsStatics() && (target.getModifiers() & Modifier.STATIC) == 0 )
{
FMLLog.log.fatal("Attempted to load a proxy type {} into {}.{}, but the field is not static", targetType, targ.getClassName(), targ.getObjectName());
throw new LoaderException(String.format("Attempted to load a proxy type %s into %s.%s, but the field is not static", targetType, targ.getClassName(), targ.getObjectName()));
}
if (!target.getType().isAssignableFrom(proxy.getClass()))
{
FMLLog.log.fatal("Attempted to load a proxy type {} into {}.{}, but the types don't match", targetType, targ.getClassName(), targ.getObjectName());
throw new LoaderException(String.format("Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, targ.getClassName(), targ.getObjectName()));
}
languageAdapter.setProxy(target, proxyTarget, proxy);
}
catch (Exception e)
{
FMLLog.log.error("An error occurred trying to load a proxy into {}.{}", targ.getObjectName(), e);
throw new LoaderException(e);
}
}
// Allow language specific proxy injection.
languageAdapter.setInternalProxies(mod, side, mcl);
}
}

View File

@ -1,76 +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.common;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Sided proxies are loaded based on the specific environment they find themselves loaded into.
* They are used to ensure that client-specific code (such as GUIs) is only loaded into the game
* on the client side.
* It is applied to static fields of a class, anywhere in your mod code. FML will scan
* and load any classes with this annotation at mod construction time.
*
* <p>
* This example will load a CommonProxy on the server side, and a ClientProxy on the client side.
*
* <pre>{@code
* public class MySidedProxyHolder {
* {@literal @}SidedProxy(modId="MyModId",clientSide="mymod.ClientProxy", serverSide="mymod.CommonProxy")
* public static CommonProxy proxy;
* }
*
* public class CommonProxy {
* // Common or server stuff here that needs to be overridden on the client
* }
*
* public class ClientProxy extends CommonProxy {
* // Override common stuff with client specific stuff here
* }
* }
* </pre>
* @author cpw
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SidedProxy
{
/**
* The full name of the client side class to load and populate.
* Defaults to the nested class named "ClientProxy" in the current class.
*/
String clientSide() default "";
/**
* The full name of the server side class to load and populate.
* Defaults to the nested class named "ServerProxy" in the current class.
*/
String serverSide() default "";
/**
* The name of a mod to load this proxy for. This is required if this annotation is not in the class with @Mod annotation.
* Or there is no other way to determine the mod this annotation belongs to. When in doubt, add this value.
*/
String modId() default "";
}

View File

@ -1,183 +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.common;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import net.minecraft.server.MinecraftServer;
import javax.annotation.Nullable;
public class StartupQuery {
// internal class/functionality, do not use
public static boolean confirm(String text)
{
StartupQuery query = new StartupQuery(text, new AtomicBoolean());
query.execute();
return query.getResult();
}
public static void notify(String text)
{
StartupQuery query = new StartupQuery(text, null);
query.execute();
}
public static void abort()
{
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
if (server != null) server.initiateShutdown();
aborted = true; // to abort loading and go back to the main menu
throw new AbortedException(); // to halt the server
}
public static void reset()
{
pending = null;
aborted = false;
}
public static boolean check()
{
if (pending != null)
{
try
{
FMLCommonHandler.instance().queryUser(pending);
}
catch (InterruptedException e)
{
FMLLog.log.warn("query interrupted");
abort();
}
pending = null;
}
return !aborted;
}
private static volatile StartupQuery pending;
private static volatile boolean aborted = false;
private StartupQuery(String text, @Nullable AtomicBoolean result)
{
this.text = text;
this.result = result;
}
@Nullable
public Boolean getResult()
{
return result == null ? null : result.get();
}
public void setResult(boolean result)
{
this.result.set(result);
}
public String getText()
{
return text;
}
public boolean isSynchronous()
{
return synchronous;
}
public void finish()
{
signal.countDown();
}
private void execute()
{
String prop = System.getProperty("fml.queryResult");
if (result != null && prop != null)
{
FMLLog.log.info("Using fml.queryResult {} to answer the following query:\n{}", prop, text);
if (prop.equalsIgnoreCase("confirm"))
{
setResult(true);
return;
}
else if (prop.equalsIgnoreCase("cancel"))
{
setResult(false);
return;
}
FMLLog.log.warn("Invalid value for fml.queryResult: {}, expected confirm or cancel", prop);
}
synchronous = false;
pending = this; // let the other thread start the query
// from the integrated server thread: the client will eventually check pending and execute the query
// from the client thread: synchronous execution
// dedicated server: command handling in mc is synchronous, execute the server-side query directly
if (FMLCommonHandler.instance().getSide().isServer() ||
FMLCommonHandler.instance().getEffectiveSide().isClient())
{
synchronous = true;
check();
}
try
{
signal.await();
reset();
}
catch (InterruptedException e)
{
FMLLog.log.warn("query interrupted");
abort();
}
}
private String text;
@Nullable
private AtomicBoolean result;
private CountDownLatch signal = new CountDownLatch(1);
private volatile boolean synchronous;
/**
* Exception not being caught by the crash report generation logic.
*/
public static class AbortedException extends RuntimeException
{
private static final long serialVersionUID = -5933665223696833921L;
private AbortedException()
{
super();
}
}
}

View File

@ -17,12 +17,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers;
package net.minecraftforge.fml.common.asm;
import net.minecraft.launchwrapper.IClassNameTransformer;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLRemappingAdapter;
import net.minecraftforge.fml.common.asm.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.common.asm.deobf.FMLRemappingAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
@ -34,7 +34,7 @@ public class DeobfuscationTransformer implements IClassTransformer, IClassNameTr
private static final int WRITER_FLAGS = ClassWriter.COMPUTE_MAXS | (RECALC_FRAMES ? ClassWriter.COMPUTE_FRAMES : 0);
private static final int READER_FLAGS = RECALC_FRAMES ? ClassReader.SKIP_FRAMES : ClassReader.EXPAND_FRAMES;
// COMPUTE_FRAMES causes classes to be loaded, which could cause issues if the classes do not exist.
// However in testing this has not happened. {As we run post SideTransformer}
// However in testing this has not happened. {As we run post RuntimeDistCleaner}
// If reported we need to add a custom implementation of ClassWriter.getCommonSuperClass
// that does not cause class loading.

View File

@ -35,11 +35,9 @@ import org.apache.commons.io.IOUtils;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.common.CertificateHelper;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.common.asm.deobf.FMLDeobfuscatingRemapper;
import net.minecraftforge.fml.common.patcher.ClassPatchManager;
import net.minecraftforge.fml.relauncher.FMLLaunchHandler;
import net.minecraftforge.fml.relauncher.IFMLCallHook;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.api.distmarker.Dist;
import com.google.common.io.ByteStreams;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers;
package net.minecraftforge.fml.common.asm;
import java.util.ListIterator;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers;
package net.minecraftforge.fml.common.asm;
public class ItemBlockSpecialTransformer extends FieldRedirectTransformer
{

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers;
package net.minecraftforge.fml.common.asm;
public class ItemBlockTransformer extends FieldRedirectTransformer
{

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers;
package net.minecraftforge.fml.common.asm;
public class ItemStackTransformer extends FieldRedirectTransformer
{

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers;
package net.minecraftforge.fml.common.asm;
import org.objectweb.asm.*;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers.deobf;
package net.minecraftforge.fml.common.asm.deobf;
import java.io.File;
import java.io.FileInputStream;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers.deobf;
package net.minecraftforge.fml.common.asm.deobf;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.common.asm.transformers.deobf;
package net.minecraftforge.fml.common.asm.deobf;
import java.io.IOException;
import java.io.InputStream;

View File

@ -1,485 +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.common.asm.transformers;
import net.minecraftforge.fml.common.FMLLog;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import net.minecraft.launchwrapper.IClassTransformer;
import org.apache.commons.io.IOUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import com.google.common.base.Splitter;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.io.CharSource;
import com.google.common.io.LineProcessor;
import com.google.common.io.Resources;
public class AccessTransformer implements IClassTransformer
{
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugAccessTransformer", "false"));
class Modifier
{
public String name = "";
public String desc = "";
public int oldAccess = 0;
public int newAccess = 0;
public int targetAccess = 0;
public boolean changeFinal = false;
public boolean markFinal = false;
protected boolean modifyClassVisibility;
private void setTargetAccess(String name)
{
if (name.startsWith("public")) targetAccess = ACC_PUBLIC;
else if (name.startsWith("private")) targetAccess = ACC_PRIVATE;
else if (name.startsWith("protected")) targetAccess = ACC_PROTECTED;
if (name.endsWith("-f"))
{
changeFinal = true;
markFinal = false;
}
else if (name.endsWith("+f"))
{
changeFinal = true;
markFinal = true;
}
}
}
private Multimap<String, Modifier> modifiers = ArrayListMultimap.create();
public AccessTransformer() throws IOException
{
this("forge_at.cfg");
}
protected AccessTransformer(String rulesFile) throws IOException
{
readMapFile(rulesFile);
}
AccessTransformer(Class<? extends AccessTransformer> dummyClazz)
{
// This is a noop
}
void readMapFile(String rulesFile) throws IOException
{
File file = new File(rulesFile);
URL rulesResource;
if (file.exists())
{
rulesResource = file.toURI().toURL();
}
else
{
rulesResource = Resources.getResource(rulesFile);
}
processATFile(Resources.asCharSource(rulesResource, StandardCharsets.UTF_8));
FMLLog.log.debug("Loaded {} rules from AccessTransformer config file {}", modifiers.size(), rulesFile);
}
protected void processATFile(CharSource rulesResource) throws IOException
{
rulesResource.readLines(new LineProcessor<Void>()
{
@Override
public Void getResult()
{
return null;
}
@Override
public boolean processLine(String input) throws IOException
{
String line = Iterables.getFirst(Splitter.on('#').limit(2).split(input), "").trim();
if (line.length()==0)
{
return true;
}
List<String> parts = Lists.newArrayList(Splitter.on(" ").trimResults().split(line));
if (parts.size()>3)
{
throw new RuntimeException("Invalid config file line "+ input);
}
Modifier m = new Modifier();
m.setTargetAccess(parts.get(0));
if (parts.size() == 2)
{
m.modifyClassVisibility = true;
}
else
{
String nameReference = parts.get(2);
int parenIdx = nameReference.indexOf('(');
if (parenIdx>0)
{
m.desc = nameReference.substring(parenIdx);
m.name = nameReference.substring(0,parenIdx);
}
else
{
m.name = nameReference;
}
}
String className = parts.get(1).replace('/', '.');
modifiers.put(className, m);
if (DEBUG) FMLLog.log.debug("AT RULE: {} {} {} (type {})", toBinary(m.targetAccess), m.name, m.desc, className);
return true;
}
});
}
@Override
public byte[] transform(String name, String transformedName, byte[] bytes)
{
if (bytes == null) { return null; }
if (!modifiers.containsKey(transformedName)) { return bytes; }
if (DEBUG)
{
FMLLog.log.debug("Considering all methods and fields on {} ({})", transformedName, name);
}
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
Collection<Modifier> mods = modifiers.get(transformedName);
for (Modifier m : mods)
{
if (m.modifyClassVisibility)
{
classNode.access = getFixedAccess(classNode.access, m);
if (DEBUG)
{
FMLLog.log.debug("Class: {} {} -> {}", name, toBinary(m.oldAccess), toBinary(m.newAccess));
}
continue;
}
if (m.desc.isEmpty())
{
for (FieldNode n : classNode.fields)
{
if (n.name.equals(m.name) || m.name.equals("*"))
{
n.access = getFixedAccess(n.access, m);
if (DEBUG)
{
FMLLog.log.debug("Field: {}.{} {} -> {}", name, n.name, toBinary(m.oldAccess), toBinary(m.newAccess));
}
if (!m.name.equals("*"))
{
break;
}
}
}
}
else
{
List<MethodNode> nowOverrideable = Lists.newArrayList();
for (MethodNode n : classNode.methods)
{
if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*"))
{
n.access = getFixedAccess(n.access, m);
// constructors always use INVOKESPECIAL
if (!n.name.equals("<init>"))
{
// if we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL
// so that overridden methods will be called. Only need to scan this class, because obviously the method was private.
boolean wasPrivate = (m.oldAccess & ACC_PRIVATE) == ACC_PRIVATE;
boolean isNowPrivate = (m.newAccess & ACC_PRIVATE) == ACC_PRIVATE;
if (wasPrivate && !isNowPrivate)
{
nowOverrideable.add(n);
}
}
if (DEBUG)
{
FMLLog.log.debug("Method: {}.{}{} {} -> {}", name, n.name, n.desc, toBinary(m.oldAccess), toBinary(m.newAccess));
}
if (!m.name.equals("*"))
{
break;
}
}
}
replaceInvokeSpecial(classNode, nowOverrideable);
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
private void replaceInvokeSpecial(ClassNode clazz, List<MethodNode> toReplace)
{
for (MethodNode method : clazz.methods)
{
for (Iterator<AbstractInsnNode> it = method.instructions.iterator(); it.hasNext();)
{
AbstractInsnNode insn = it.next();
if (insn.getOpcode() == INVOKESPECIAL)
{
MethodInsnNode mInsn = (MethodInsnNode) insn;
for (MethodNode n : toReplace)
{
if (n.name.equals(mInsn.name) && n.desc.equals(mInsn.desc))
{
mInsn.setOpcode(INVOKEVIRTUAL);
break;
}
}
}
}
}
}
private String toBinary(int num)
{
return String.format("%16s", Integer.toBinaryString(num)).replace(' ', '0');
}
private int getFixedAccess(int access, Modifier target)
{
target.oldAccess = access;
int t = target.targetAccess;
int ret = (access & ~7);
switch (access & 7)
{
case ACC_PRIVATE:
ret |= t;
break;
case 0: // default
ret |= (t != ACC_PRIVATE ? t : 0 /* default */);
break;
case ACC_PROTECTED:
ret |= (t != ACC_PRIVATE && t != 0 /* default */? t : ACC_PROTECTED);
break;
case ACC_PUBLIC:
ret |= (t != ACC_PRIVATE && t != 0 /* default */&& t != ACC_PROTECTED ? t : ACC_PUBLIC);
break;
default:
throw new RuntimeException("The fuck?");
}
// Clear the "final" marker on fields only if specified in control field
if (target.changeFinal)
{
if (target.markFinal)
{
ret |= ACC_FINAL;
}
else
{
ret &= ~ACC_FINAL;
}
}
target.newAccess = ret;
return ret;
}
public static void main(String[] args)
{
if (args.length < 2)
{
System.out.println("Usage: AccessTransformer <JarPath> <MapFile> [MapFile2]... ");
System.exit(1);
}
boolean hasTransformer = false;
AccessTransformer[] trans = new AccessTransformer[args.length - 1];
for (int x = 1; x < args.length; x++)
{
try
{
trans[x - 1] = new AccessTransformer(args[x]);
hasTransformer = true;
}
catch (IOException e)
{
System.out.println("Could not read Transformer Map: " + args[x]);
e.printStackTrace();
}
}
if (!hasTransformer)
{
System.out.println("Could not find a valid transformer to perform");
System.exit(1);
}
File orig = new File(args[0]);
File temp = new File(args[0] + ".ATBack");
if (!orig.exists() && !temp.exists())
{
System.out.println("Could not find target jar: " + orig);
System.exit(1);
}
if (!orig.renameTo(temp))
{
System.out.println("Could not rename file: " + orig + " -> " + temp);
System.exit(1);
}
try
{
processJar(temp, orig, trans);
}
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
if (!temp.delete())
{
System.out.println("Could not delete temp file: " + temp);
}
}
private static void processJar(File inFile, File outFile, AccessTransformer[] transformers) throws IOException
{
ZipInputStream inJar = null;
ZipOutputStream outJar = null;
try
{
try
{
inJar = new ZipInputStream(new BufferedInputStream(new FileInputStream(inFile)));
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("Could not open input file: " + e.getMessage());
}
try
{
outJar = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("Could not open output file: " + e.getMessage());
}
ZipEntry entry;
while ((entry = inJar.getNextEntry()) != null)
{
if (entry.isDirectory())
{
outJar.putNextEntry(entry);
continue;
}
byte[] data = new byte[4096];
ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream();
int len;
do
{
len = inJar.read(data);
if (len > 0)
{
entryBuffer.write(data, 0, len);
}
}
while (len != -1);
byte[] entryData = entryBuffer.toByteArray();
String entryName = entry.getName();
if (entryName.endsWith(".class") && !entryName.startsWith("."))
{
ClassNode cls = new ClassNode();
ClassReader rdr = new ClassReader(entryData);
rdr.accept(cls, 0);
String name = cls.name.replace('/', '.').replace('\\', '.');
for (AccessTransformer trans : transformers)
{
entryData = trans.transform(name, name, entryData);
}
}
ZipEntry newEntry = new ZipEntry(entryName);
outJar.putNextEntry(newEntry);
outJar.write(entryData);
}
}
finally
{
IOUtils.closeQuietly(outJar);
IOUtils.closeQuietly(inJar);
}
}
Multimap<String, Modifier> getModifiers()
{
return modifiers;
}
boolean isEmpty()
{
return modifiers.isEmpty();
}
}

View File

@ -1,93 +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.common.asm.transformers;
import java.lang.reflect.Modifier;
import java.util.List;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
public class EventSubscriberTransformer implements IClassTransformer
{
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass)
{
if (basicClass == null) return null;
ClassNode classNode = new ClassNode();
new ClassReader(basicClass).accept(classNode, 0);
boolean isSubscriber = false;
for (MethodNode methodNode : classNode.methods)
{
List<AnnotationNode> anns = methodNode.visibleAnnotations;
if (anns != null && Iterables.any(anns, SubscribeEventPredicate.INSTANCE))
{
if (Modifier.isPrivate(methodNode.access))
{
String msg = "Cannot apply @SubscribeEvent to private method %s/%s%s";
throw new RuntimeException(String.format(msg, classNode.name, methodNode.name, methodNode.desc));
}
methodNode.access = toPublic(methodNode.access);
isSubscriber = true;
}
}
if (isSubscriber)
{
classNode.access = toPublic(classNode.access);
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
return basicClass;
}
private static int toPublic(int access)
{
return access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED) | Opcodes.ACC_PUBLIC;
}
private static class SubscribeEventPredicate implements Predicate<AnnotationNode>
{
static final SubscribeEventPredicate INSTANCE = new SubscribeEventPredicate();
@Override
public boolean apply(AnnotationNode input)
{
return input.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/SubscribeEvent;");
}
}
}

View File

@ -1,242 +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.common.asm.transformers;
import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ARETURN;
import static org.objectweb.asm.Opcodes.DUP;
import static org.objectweb.asm.Opcodes.F_SAME;
import static org.objectweb.asm.Opcodes.GETSTATIC;
import static org.objectweb.asm.Opcodes.IFNULL;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.NEW;
import static org.objectweb.asm.Opcodes.PUTSTATIC;
import static org.objectweb.asm.Opcodes.RETURN;
import static org.objectweb.asm.Opcodes.IRETURN;
import static org.objectweb.asm.Opcodes.ICONST_1;
import static org.objectweb.asm.Type.VOID_TYPE;
import static org.objectweb.asm.Type.BOOLEAN_TYPE;
import static org.objectweb.asm.Type.getMethodDescriptor;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.eventbus.api.Event;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.FrameNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
public class EventSubscriptionTransformer implements IClassTransformer
{
public EventSubscriptionTransformer()
{
}
@Override
public byte[] transform(String name, String transformedName, byte[] bytes)
{
if (bytes == null || name.equals("net.minecraftforge.fml.common.eventhandler.Event") || name.startsWith("net.minecraft.") || name.indexOf('.') == -1)
{
return bytes;
}
ClassReader cr = new ClassReader(bytes);
ClassNode classNode = new ClassNode();
cr.accept(classNode, 0);
try
{
if (buildEvents(classNode))
{
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
classNode.accept(cw);
return cw.toByteArray();
}
return bytes;
}
catch (ClassNotFoundException ex)
{
// Discard silently- it's just noise
}
catch (Exception e)
{
FMLLog.log.error("Error building events.", e);
}
return bytes;
}
private boolean buildEvents(ClassNode classNode) throws Exception
{
// Yes, this recursively loads classes until we get this base class. THIS IS NOT A ISSUE. Coremods should handle re-entry just fine.
// If they do not this a COREMOD issue NOT a Forge/LaunchWrapper issue.
Class<?> parent = this.getClass().getClassLoader().loadClass(classNode.superName.replace('/', '.'));
if (!net.minecraftforge.eventbus.api.Event.class.isAssignableFrom(parent))
{
return false;
}
//Class<?> listenerListClazz = Class.forName("net.minecraftforge.fml.common.eventhandler.ListenerList", false, getClass().getClassLoader());
Type tList = Type.getType("Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
boolean edited = false;
boolean hasSetup = false;
boolean hasGetListenerList = false;
boolean hasDefaultCtr = false;
boolean hasCancelable = false;
boolean hasResult = false;
String voidDesc = Type.getMethodDescriptor(VOID_TYPE);
String boolDesc = Type.getMethodDescriptor(BOOLEAN_TYPE);
String listDesc = tList.getDescriptor();
String listDescM = Type.getMethodDescriptor(tList);
for (MethodNode method : classNode.methods)
{
if (method.name.equals("setup") && method.desc.equals(voidDesc) && (method.access & ACC_PROTECTED) == ACC_PROTECTED) hasSetup = true;
if ((method.access & ACC_PUBLIC) == ACC_PUBLIC)
{
if (method.name.equals("getListenerList") && method.desc.equals(listDescM)) hasGetListenerList = true;
if (method.name.equals("isCancelable") && method.desc.equals(boolDesc)) hasCancelable = true;
if (method.name.equals("hasResult") && method.desc.equals(boolDesc)) hasResult = true;
}
if (method.name.equals("<init>") && method.desc.equals(voidDesc)) hasDefaultCtr = true;
}
if (classNode.visibleAnnotations != null)
{
for (AnnotationNode node : classNode.visibleAnnotations)
{
if (!hasResult && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Event$HasResult;"))
{
/* Add:
* public boolean hasResult()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "hasResult", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
}
else if (!hasCancelable && node.desc.equals("Lnet/minecraftforge/fml/common/eventhandler/Cancelable;"))
{
/* Add:
* public boolean isCancelable()
* {
* return true;
* }
*/
MethodNode method = new MethodNode(ACC_PUBLIC, "isCancelable", boolDesc, null, null);
method.instructions.add(new InsnNode(ICONST_1));
method.instructions.add(new InsnNode(IRETURN));
classNode.methods.add(method);
edited = true;
}
}
}
if (hasSetup)
{
if (!hasGetListenerList)
throw new RuntimeException("Event class defines setup() but does not define getListenerList! " + classNode.name);
else
return edited;
}
Type tSuper = Type.getType(classNode.superName);
//Add private static ListenerList LISTENER_LIST
classNode.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, "LISTENER_LIST", listDesc, null, null));
/*Add:
* public <init>()
* {
* super();
* }
*/
if (!hasDefaultCtr)
{
MethodNode method = new MethodNode(ACC_PUBLIC, "<init>", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "<init>", voidDesc, false));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
}
/*Add:
* protected void setup()
* {
* super.setup();
* if (LISTENER_LIST != NULL)
* {
* return;
* }
* LISTENER_LIST = new ListenerList(super.getListenerList());
* }
*/
MethodNode method = new MethodNode(ACC_PROTECTED, "setup", voidDesc, null, null);
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "setup", voidDesc, false));
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
LabelNode initListener = new LabelNode();
method.instructions.add(new JumpInsnNode(IFNULL, initListener));
method.instructions.add(new InsnNode(RETURN));
method.instructions.add(initListener);
method.instructions.add(new FrameNode(F_SAME, 0, null, 0, null));
method.instructions.add(new TypeInsnNode(NEW, tList.getInternalName()));
method.instructions.add(new InsnNode(DUP));
method.instructions.add(new VarInsnNode(ALOAD, 0));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tSuper.getInternalName(), "getListenerList", listDescM, false));
method.instructions.add(new MethodInsnNode(INVOKESPECIAL, tList.getInternalName(), "<init>", getMethodDescriptor(VOID_TYPE, tList), false));
method.instructions.add(new FieldInsnNode(PUTSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(RETURN));
classNode.methods.add(method);
/*Add:
* public ListenerList getListenerList()
* {
* return this.LISTENER_LIST;
* }
*/
method = new MethodNode(ACC_PUBLIC, "getListenerList", listDescM, null, null);
method.instructions.add(new FieldInsnNode(GETSTATIC, classNode.name, "LISTENER_LIST", listDesc));
method.instructions.add(new InsnNode(ARETURN));
classNode.methods.add(method);
return true;
}
}

View File

@ -1,210 +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.common.asm.transformers;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModAPIManager;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Sets;
public class ModAPITransformer implements IClassTransformer {
private static final boolean logDebugInfo = Boolean.valueOf(System.getProperty("fml.debugAPITransformer", "false"));
private ListMultimap<String, ASMData> optionals;
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass)
{
String lookupName = name;
if(name.endsWith("$class"))
{
lookupName = name.substring(0, name.length() - 6);
}
if (optionals == null || !optionals.containsKey(lookupName))
{
return basicClass;
}
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(basicClass);
classReader.accept(classNode, 0);
if (logDebugInfo) FMLLog.log.trace("Optional removal - found optionals for class {} - processing", name);
for (ASMData optional : optionals.get(lookupName))
{
String modId = (String) optional.getAnnotationInfo().get("modid");
if (Loader.isModLoaded(modId) || ModAPIManager.INSTANCE.hasAPI(modId))
{
if (logDebugInfo) FMLLog.log.trace("Optional removal skipped - mod present {}", modId);
continue;
}
if (logDebugInfo) FMLLog.log.trace("Optional on {} triggered - mod missing {}", name, modId);
if (optional.getAnnotationInfo().containsKey("iface"))
{
Boolean stripRefs = (Boolean)optional.getAnnotationInfo().get("striprefs");
if (stripRefs == null) stripRefs = Boolean.FALSE;
stripInterface(classNode,(String)optional.getAnnotationInfo().get("iface"), stripRefs);
}
else
{
stripMethod(classNode, optional.getObjectName());
}
}
if (logDebugInfo) FMLLog.log.trace("Optional removal - class {} processed", name);
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
private void stripMethod(ClassNode classNode, String methodDescriptor)
{
if(classNode.name.endsWith("$class"))
{
String subName = classNode.name.substring(0, classNode.name.length() - 6);
int pos = methodDescriptor.indexOf('(') + 1;
methodDescriptor = methodDescriptor.substring(0, pos) + 'L' + subName + ';' + methodDescriptor.substring(pos);
}
for (ListIterator<MethodNode> iterator = classNode.methods.listIterator(); iterator.hasNext();)
{
MethodNode method = iterator.next();
if (methodDescriptor.equals(method.name+method.desc))
{
iterator.remove();
if (logDebugInfo) FMLLog.log.debug("Optional removal - method {} removed", methodDescriptor);
return;
}
}
if (logDebugInfo) FMLLog.log.debug("Optional removal - method {} NOT removed - not found", methodDescriptor);
}
private void stripInterface(ClassNode classNode, String interfaceName, boolean stripRefs)
{
final String ifaceName = interfaceName.replace('.', '/');
boolean found = classNode.interfaces.remove(ifaceName);
if (found && classNode.signature != null)
{
SignatureReader sr = new SignatureReader(classNode.signature);
final RemovingSignatureWriter signatureWriter = new RemovingSignatureWriter(ifaceName);
sr.accept(signatureWriter);
classNode.signature = signatureWriter.toString();
if (logDebugInfo) FMLLog.log.debug("Optional removal - interface {} removed from type signature", interfaceName);
}
if (found && logDebugInfo) FMLLog.log.debug("Optional removal - interface {} removed", interfaceName);
if (!found && logDebugInfo) FMLLog.log.debug("Optional removal - interface {} NOT removed - not found", interfaceName);
if (found && stripRefs)
{
if (logDebugInfo) FMLLog.log.debug("Optional removal - interface {} - stripping method signature references", interfaceName);
for (Iterator<MethodNode> iterator = classNode.methods.iterator(); iterator.hasNext();)
{
MethodNode node = iterator.next();
if (node.desc.contains(ifaceName))
{
if (logDebugInfo) FMLLog.log.debug("Optional removal - interface {} - stripping method containing reference {}", interfaceName, node.name);
iterator.remove();
}
}
if (logDebugInfo) FMLLog.log.debug("Optional removal - interface {} - all method signature references stripped", interfaceName);
}
else if (found)
{
if (logDebugInfo) FMLLog.log.debug("Optional removal - interface {} - NOT stripping method signature references", interfaceName);
}
}
public void initTable(ASMDataTable dataTable)
{
optionals = ArrayListMultimap.create();
Set<ASMData> interfaceLists = dataTable.getAll("net.minecraftforge.fml.common.Optional$InterfaceList");
addData(unpackInterfaces(interfaceLists));
Set<ASMData> interfaces = dataTable.getAll("net.minecraftforge.fml.common.Optional$Interface");
addData(interfaces);
Set<ASMData> methods = dataTable.getAll("net.minecraftforge.fml.common.Optional$Method");
addData(methods);
}
private Set<ASMData> unpackInterfaces(Set<ASMData> packedInterfaces)
{
Set<ASMData> result = Sets.newHashSet();
for (ASMData data : packedInterfaces)
{
@SuppressWarnings("unchecked")
List<Map<String,Object>> packedList = (List<Map<String,Object>>) data.getAnnotationInfo().get("value");
for (Map<String,Object> packed : packedList)
{
ASMData newData = data.copy(packed);
result.add(newData);
}
}
return result;
}
private void addData(Set<ASMData> interfaces)
{
for (ASMData data : interfaces)
{
optionals.put(data.getClassName(),data);
}
}
private static class RemovingSignatureWriter extends SignatureWriter
{
private final String ifaceName;
RemovingSignatureWriter(String ifaceName)
{
this.ifaceName = ifaceName;
}
@Override
public void visitClassType(String name)
{
if (name.equals(ifaceName)) {
super.visitClassType("java/lang/Object");
}
else
{
super.visitClassType(name);
}
}
}
}

View File

@ -1,91 +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.common.asm.transformers;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import net.minecraftforge.fml.common.FMLLog;
import com.google.common.collect.Maps;
import com.google.common.io.ByteSource;
import com.google.common.io.CharSource;
public class ModAccessTransformer extends AccessTransformer
{
public static final Attributes.Name FMLAT = new Attributes.Name("FMLAT");
private static Map<String, String> embedded = Maps.newHashMap(); //Needs to be primitive so that both classloaders get the same class.
@SuppressWarnings("unchecked")
public ModAccessTransformer() throws Exception
{
super(ModAccessTransformer.class);
//We are in the new ClassLoader here, so we need to get the static field from the other ClassLoader.
ClassLoader classLoader = this.getClass().getClassLoader().getClass().getClassLoader(); //Bit odd but it gets the class loader that loaded our current class loader yay java!
Class<?> otherClazz = Class.forName(this.getClass().getName(), true, classLoader);
Field otherField = otherClazz.getDeclaredField("embedded");
otherField.setAccessible(true);
embedded = (Map<String, String>)otherField.get(null);
for (Map.Entry<String, String> e : embedded.entrySet())
{
int old_count = getModifiers().size();
processATFile(CharSource.wrap(e.getValue()));
int added = getModifiers().size() - old_count;
if (added > 0)
{
FMLLog.log.debug("Loaded {} rules from AccessTransformer mod jar file {}\n", added, e.getKey());
}
}
}
public static void addJar(JarFile jar, String atList) throws IOException
{
for (String at : atList.split(" "))
{
JarEntry jarEntry = jar.getJarEntry("META-INF/"+at);
if (jarEntry != null)
{
embedded.put(String.format("%s!META-INF/%s", jar.getName(), at),
new JarByteSource(jar,jarEntry).asCharSource(StandardCharsets.UTF_8).read());
}
}
}
private static class JarByteSource extends ByteSource
{
private JarFile jar;
private JarEntry entry;
public JarByteSource(JarFile jar, JarEntry entry)
{
this.jar = jar;
this.entry = entry;
}
@Override
public InputStream openStream() throws IOException
{
return jar.getInputStream(entry);
}
}
}

View File

@ -1,166 +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.common.discovery;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.base.Predicate;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import net.minecraftforge.fml.ModContainer;
public class ASMDataTable
{
public final static class ASMData implements Cloneable
{
private ModCandidate candidate;
private String annotationName;
private String className;
private String objectName;
private int classVersion;
private Map<String,Object> annotationInfo;
public ASMData(ModCandidate candidate, String annotationName, String className, @Nullable String objectName, @Nullable Map<String,Object> info)
{
this.candidate = candidate;
this.annotationName = annotationName;
this.className = className;
this.objectName = objectName;
this.annotationInfo = info;
}
public ModCandidate getCandidate()
{
return candidate;
}
public String getAnnotationName()
{
return annotationName;
}
public String getClassName()
{
return className;
}
public String getObjectName()
{
return objectName;
}
public Map<String, Object> getAnnotationInfo()
{
return annotationInfo;
}
public ASMData copy(Map<String,Object> newAnnotationInfo)
{
try
{
ASMData clone = (ASMData) this.clone();
clone.annotationInfo = newAnnotationInfo;
return clone;
}
catch (CloneNotSupportedException e)
{
throw new RuntimeException("Unpossible", e);
}
}
}
private static class ModContainerPredicate implements Predicate<ASMData>
{
private ModContainer container;
public ModContainerPredicate(ModContainer container)
{
this.container = container;
}
@Override
public boolean apply(ASMData data)
{
return container.getSource().equals(data.candidate.getModContainer());
}
}
private SetMultimap<String, ASMData> globalAnnotationData = HashMultimap.create();
private Map<ModContainer, SetMultimap<String,ASMData>> containerAnnotationData;
private List<ModContainer> containers = Lists.newArrayList();
private SetMultimap<String,ModCandidate> packageMap = HashMultimap.create();
public SetMultimap<String,ASMData> getAnnotationsFor(ModContainer container)
{
if (containerAnnotationData == null)
{
ImmutableMap.Builder<ModContainer, SetMultimap<String, ASMData>> mapBuilder = ImmutableMap.builder();
for (ModContainer cont : containers)
{
Multimap<String, ASMData> values = Multimaps.filterValues(globalAnnotationData, new ModContainerPredicate(cont));
mapBuilder.put(cont, ImmutableSetMultimap.copyOf(values));
}
containerAnnotationData = mapBuilder.build();
}
return containerAnnotationData.get(container);
}
public Set<ASMData> getAll(String annotation)
{
return globalAnnotationData.get(annotation);
}
public void addASMData(ModCandidate candidate, String annotation, String className, @Nullable String objectName, @Nullable Map<String,Object> annotationInfo)
{
globalAnnotationData.put(annotation, new ASMData(candidate, annotation, className, objectName, annotationInfo));
}
public void addContainer(ModContainer container)
{
this.containers.add(container);
}
public void registerPackage(ModCandidate modCandidate, String pkg)
{
this.packageMap.put(pkg,modCandidate);
}
public Set<ModCandidate> getCandidatesFor(String pkg)
{
return this.packageMap.get(pkg);
}
@Nullable
public static String getOwnerModID(Set<ASMData> mods, ASMData targ)
{
if (mods.size() == 1) {
return (String)mods.iterator().next().getAnnotationInfo().get("modid");
} else {
for (ASMData m : mods) {
if (targ.getClassName().startsWith(m.getClassName())) {
return (String)m.getAnnotationInfo().get("modid");
}
}
}
return null;
}
}

View File

@ -1,49 +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.common.discovery;
import java.util.List;
import net.minecraftforge.fml.ModContainer;
public enum ContainerType
{
JAR(JarDiscoverer.class),
DIR(DirectoryDiscoverer.class);
private ITypeDiscoverer discoverer;
private ContainerType(Class<? extends ITypeDiscoverer> discovererClass)
{
try
{
this.discoverer = discovererClass.newInstance();
}
catch (ReflectiveOperationException e)
{
throw new RuntimeException(e);
}
}
public List<ModContainer> findMods(ModCandidate candidate, ASMDataTable table)
{
return discoverer.discover(candidate, table);
}
}

View File

@ -1,147 +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.common.discovery;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.MetadataCollection;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModContainerFactory;
import net.minecraftforge.fml.common.discovery.asm.ASMModParser;
import org.apache.commons.io.IOUtils;
import com.google.common.collect.Lists;
import javax.annotation.Nullable;
public class DirectoryDiscoverer implements ITypeDiscoverer
{
private class ClassFilter implements FileFilter
{
@Override
public boolean accept(File file)
{
return (file.isFile() && classFile.matcher(file.getName()).matches()) || file.isDirectory();
}
}
private ASMDataTable table;
@Override
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
{
this.table = table;
List<ModContainer> found = Lists.newArrayList();
FMLLog.log.debug("Examining directory {} for potential mods", candidate.getModContainer().getName());
exploreFileSystem("", candidate.getModContainer(), found, candidate, null);
for (ModContainer mc : found)
{
table.addContainer(mc);
}
return found;
}
public void exploreFileSystem(String path, File modDir, List<ModContainer> harvestedMods, ModCandidate candidate, @Nullable MetadataCollection mc)
{
if (path.length() == 0)
{
File metadata = new File(modDir, "mcmod.info");
try
{
FileInputStream fis = new FileInputStream(metadata);
try
{
mc = MetadataCollection.from(fis, modDir.getName());
}
finally
{
IOUtils.closeQuietly(fis);
}
FMLLog.log.debug("Found an mcmod.info file in directory {}", modDir.getName());
}
catch (Exception e)
{
mc = MetadataCollection.from(null,"");
FMLLog.log.debug("No mcmod.info file found in directory {}", modDir.getName());
}
}
File[] content = modDir.listFiles(new ClassFilter());
// Always sort our content
Arrays.sort(content);
for (File file : content)
{
if (file.isDirectory())
{
FMLLog.log.trace("Recursing into package {}", path + file.getName());
exploreFileSystem(path + file.getName() + "/", file, harvestedMods, candidate, mc);
continue;
}
Matcher match = classFile.matcher(file.getName());
if (match.matches())
{
ASMModParser modParser = null;
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
modParser = new ASMModParser(fis);
candidate.addClassEntry(path+file.getName());
}
catch (LoaderException e)
{
FMLLog.log.error("There was a problem reading the file {} - probably this is a corrupt file", file.getPath(), e);
throw e;
}
catch (IOException e)
{
throw new RuntimeException(e);
}
finally
{
IOUtils.closeQuietly(fis);
}
modParser.validate();
modParser.sendToTable(table, candidate);
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
if (container!=null)
{
harvestedMods.add(container);
container.bindMetadata(mc);
}
}
}
}
}

View File

@ -1,168 +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.common.discovery;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.jar.JarFile;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.MetadataCollection;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModContainerFactory;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.common.discovery.asm.ASMModParser;
import net.minecraftforge.fml.common.discovery.json.JsonAnnotationLoader;
import java.util.regex.Matcher;
import java.util.zip.ZipEntry;
import org.objectweb.asm.Type;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
public class JarDiscoverer implements ITypeDiscoverer
{
private static final boolean ENABLE_JSON_TEST = "true".equals(System.getProperty("fml.enableJsonAnnotations", "false"));
@Override
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
{
List<ModContainer> foundMods = Lists.newArrayList();
FMLLog.log.debug("Examining file {} for potential mods", candidate.getModContainer().getName());
try (JarFile jar = new JarFile(candidate.getModContainer()))
{
ZipEntry modInfo = jar.getEntry("mcmod.info");
MetadataCollection mc = null;
if (modInfo != null)
{
FMLLog.log.trace("Located mcmod.info file in file {}", candidate.getModContainer().getName());
try (InputStream inputStream = jar.getInputStream(modInfo))
{
mc = MetadataCollection.from(inputStream, candidate.getModContainer().getName());
}
}
else
{
FMLLog.log.debug("The mod container {} appears to be missing an mcmod.info file", candidate.getModContainer().getName());
mc = MetadataCollection.from(null, "");
}
if (ENABLE_JSON_TEST && jar.getEntry(JsonAnnotationLoader.ANNOTATION_JSON) != null)
findClassesJSON(candidate, table, jar, foundMods, mc);
else
findClassesASM(candidate, table, jar, foundMods, mc);
}
catch (Exception e)
{
FMLLog.log.warn("Zip file {} failed to read properly, it will be ignored", candidate.getModContainer().getName(), e);
}
return foundMods;
}
private void findClassesASM(ModCandidate candidate, ASMDataTable table, JarFile jar, List<ModContainer> foundMods, MetadataCollection mc) throws IOException
{
for (ZipEntry ze : Collections.list(jar.entries()))
{
if (ze.getName()!=null && ze.getName().startsWith("__MACOSX"))
{
continue;
}
Matcher match = classFile.matcher(ze.getName());
if (match.matches())
{
ASMModParser modParser;
try
{
try (InputStream inputStream = jar.getInputStream(ze))
{
modParser = new ASMModParser(inputStream);
}
candidate.addClassEntry(ze.getName());
}
catch (LoaderException e)
{
FMLLog.log.error("There was a problem reading the entry {} in the jar {} - probably a corrupt zip", candidate.getModContainer().getPath(), e);
jar.close();
throw e;
}
modParser.validate();
modParser.sendToTable(table, candidate);
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
if (container!=null)
{
table.addContainer(container);
foundMods.add(container);
container.bindMetadata(mc);
container.setClassVersion(modParser.getClassVersion());
}
}
}
}
private void findClassesJSON(ModCandidate candidate, ASMDataTable table, JarFile jar, List<ModContainer> foundMods, MetadataCollection mc) throws IOException
{
FMLLog.log.info("Loading jar {} annotation data from json", candidate.getModContainer().getPath());
ZipEntry json = jar.getEntry(JsonAnnotationLoader.ANNOTATION_JSON);
Multimap<String, ASMData> annos = JsonAnnotationLoader.loadJson(jar.getInputStream(json), candidate, table);
for (ZipEntry e : Collections.list(jar.entries()))
{
if (!e.getName().startsWith("__MACOSX") && !e.getName().startsWith("META-INF/") && e.getName().endsWith(".class"))
{
candidate.addClassEntry(e.getName());
}
}
for (Entry<Type, Constructor<? extends ModContainer>> entry : ModContainerFactory.modTypes.entrySet())
{
Type type = entry.getKey();
Constructor<? extends ModContainer> ctr = entry.getValue();
for (ASMData data : annos.get(type.getClassName()))
{
FMLLog.log.debug("Identified a mod of type {} ({}) - loading", type.getClassName(), data.getClassName());
try
{
ModContainer ret = ctr.newInstance(data.getClassName(), candidate, data.getAnnotationInfo());
if (!ret.shouldLoadInEnvironment())
FMLLog.log.debug("Skipping mod {}, container opted to not load.", data.getClassName());
else
{
table.addContainer(ret);
foundMods.add(ret);
ret.bindMetadata(mc);
//ret.setClassVersion(classVersion); // Not really needed anymore as we're forcing J8. Maybe think of reinstating for J9 support? After LaunchWraper re-do.
}
}
catch (Exception e)
{
FMLLog.log.error("Unable to construct {} container", data.getClassName(), e);
}
}
}
}
}

View File

@ -1,112 +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.common.discovery;
import java.io.File;
import java.util.List;
import java.util.Set;
import net.minecraftforge.fml.ModContainer;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class ModCandidate
{
private File classPathRoot;
private File modContainer;
private ContainerType sourceType;
private boolean classpath;
private boolean isMinecraft;
private Set<String> foundClasses = Sets.newHashSet();
private List<ModContainer> mods;
private List<String> packages = Lists.newArrayList();
private ASMDataTable table;
public ModCandidate(File classPathRoot, File modContainer, ContainerType sourceType)
{
this(classPathRoot, modContainer, sourceType, false, false);
}
public ModCandidate(File classPathRoot, File modContainer, ContainerType sourceType, boolean isMinecraft, boolean classpath)
{
this.classPathRoot = classPathRoot;
this.modContainer = modContainer;
this.sourceType = sourceType;
this.isMinecraft = isMinecraft;
this.classpath = classpath;
}
public File getClassPathRoot()
{
return classPathRoot;
}
public File getModContainer()
{
return modContainer;
}
public ContainerType getSourceType()
{
return sourceType;
}
public List<ModContainer> explore(ASMDataTable table)
{
this.table = table;
this.mods = sourceType.findMods(this, table);
return this.mods;
}
public void addClassEntry(String name)
{
String className = name.substring(0, name.lastIndexOf('.')); // strip the .class
foundClasses.add(className);
className = className.replace('/','.');
int pkgIdx = className.lastIndexOf('.');
if (pkgIdx > -1)
{
String pkg = className.substring(0,pkgIdx);
packages.add(pkg);
this.table.registerPackage(this,pkg);
}
}
public boolean isClasspath()
{
return classpath;
}
public boolean isMinecraftJar()
{
return isMinecraft;
}
public Set<String> getClassList()
{
return foundClasses;
}
public List<ModContainer> getContainedMods()
{
return mods;
}
public List<String> getContainedPackages()
{
return packages;
}
}

View File

@ -1,134 +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.common.discovery;
import java.io.File;
import java.util.List;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.ModClassLoader;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.relauncher.CoreModManager;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
public class ModDiscoverer
{
private List<ModCandidate> candidates = Lists.newArrayList();
private ASMDataTable dataTable = new ASMDataTable();
private List<File> nonModLibs = Lists.newArrayList();
public void findClasspathMods(ModClassLoader modClassLoader)
{
List<String> knownLibraries = ImmutableList.<String>builder()
// skip default libs
.addAll(modClassLoader.getDefaultLibraries())
// skip loaded coremods
.addAll(CoreModManager.getIgnoredMods())
// skip reparse coremods here
.addAll(CoreModManager.getReparseableCoremods())
.build();
File[] minecraftSources = modClassLoader.getParentSources();
if (minecraftSources.length == 1 && minecraftSources[0].isFile())
{
FMLLog.log.debug("Minecraft is a file at {}, loading", minecraftSources[0].getAbsolutePath());
addCandidate(new ModCandidate(minecraftSources[0], minecraftSources[0], ContainerType.JAR, true, true));
}
else
{
int i = 0;
for (File source : minecraftSources)
{
if (source.isFile())
{
if (knownLibraries.contains(source.getName()) || modClassLoader.isDefaultLibrary(source))
{
FMLLog.log.trace("Skipping known library file {}", source.getAbsolutePath());
}
else
{
FMLLog.log.debug("Found a minecraft related file at {}, examining for mod candidates", source.getAbsolutePath());
addCandidate(new ModCandidate(source, source, ContainerType.JAR, i==0, true));
}
}
else if (minecraftSources[i].isDirectory())
{
FMLLog.log.debug("Found a minecraft related directory at {}, examining for mod candidates", source.getAbsolutePath());
addCandidate(new ModCandidate(source, source, ContainerType.DIR, i==0, true));
}
i++;
}
}
}
public List<ModContainer> identifyMods()
{
List<ModContainer> modList = Lists.newArrayList();
for (ModCandidate candidate : candidates)
{
try
{
List<ModContainer> mods = candidate.explore(dataTable);
if (mods.isEmpty() && !candidate.isClasspath())
{
nonModLibs.add(candidate.getModContainer());
}
else
{
modList.addAll(mods);
}
}
catch (LoaderException le)
{
FMLLog.log.warn("Identified a problem with the mod candidate {}, ignoring this source", candidate.getModContainer(), le);
}
}
return modList;
}
public ASMDataTable getASMTable()
{
return dataTable;
}
public List<File> getNonModLibs()
{
return nonModLibs;
}
public void addCandidate(ModCandidate candidate)
{
for (ModCandidate c : candidates)
{
if (c.getModContainer().equals(candidate.getModContainer()))
{
FMLLog.log.trace(" Skipping already in list {}", candidate.getModContainer());
return;
}
}
candidates.add(candidate);
}
}

View File

@ -1,179 +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.common.discovery.asm;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Set;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoaderException;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ModCandidate;
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation;
import net.minecraftforge.fml.loading.moddiscovery.ModClassVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class ASMModParser
{
private Type asmType;
private int classVersion;
private Type asmSuperType;
private LinkedList<ModAnnotation> annotations = Lists.newLinkedList();
private Set<String> interfaces = Sets.newHashSet();
static enum AnnotationType
{
CLASS, FIELD, METHOD, SUBTYPE;
}
public ASMModParser(InputStream stream) throws IOException
{
try
{
ClassReader reader = new ClassReader(stream);
reader.accept(new ModClassVisitor(this), 0);
}
catch (Exception ex)
{
FMLLog.log.error("Unable to read a class file correctly", ex);
throw new LoaderException(ex);
}
}
public void beginNewTypeName(String typeQName, int classVersion, String superClassQName, String[] interfaces)
{
this.asmType = Type.getObjectType(typeQName);
this.classVersion = classVersion;
this.asmSuperType = !Strings.isNullOrEmpty(superClassQName) ? Type.getObjectType(superClassQName) : null;
for (String intf : interfaces)
this.interfaces.add(intf);
}
public void startClassAnnotation(String annotationName)
{
ModAnnotation ann = new ModAnnotation(AnnotationType.CLASS, Type.getType(annotationName), this.asmType.getClassName());
annotations.addFirst(ann);
}
public void addAnnotationProperty(String key, Object value)
{
annotations.getFirst().addProperty(key, value);
}
public void startFieldAnnotation(String fieldName, String annotationName)
{
ModAnnotation ann = new ModAnnotation(AnnotationType.FIELD, Type.getType(annotationName), fieldName);
annotations.addFirst(ann);
}
@Override
public String toString()
{
return MoreObjects.toStringHelper("ASMAnnotationDiscoverer")
.add("className", asmType.getClassName())
.add("classVersion", classVersion)
.add("superName", asmSuperType.getClassName())
.add("annotations", annotations)
.toString();
}
public Type getASMType()
{
return asmType;
}
public int getClassVersion()
{
return classVersion;
}
public Type getASMSuperType()
{
return asmSuperType;
}
public LinkedList<ModAnnotation> getAnnotations()
{
return annotations;
}
public void validate()
{
}
public void sendToTable(ASMDataTable table, ModCandidate candidate)
{
for (ModAnnotation ma : annotations)
{
table.addASMData(candidate, ma.asmType.getClassName(), this.asmType.getClassName(), ma.member, ma.values);
}
for (String intf : interfaces)
{
table.addASMData(candidate, intf, this.asmType.getInternalName(), null, null);
}
}
public void addAnnotationArray(String name)
{
annotations.getFirst().addArray(name);
}
public void addAnnotationEnumProperty(String name, String desc, String value)
{
annotations.getFirst().addEnumProperty(name, desc, value);
}
public void endArray()
{
annotations.getFirst().endArray();
}
public void addSubAnnotation(String name, String desc)
{
ModAnnotation ma = annotations.getFirst();
annotations.addFirst(ma.addChildAnnotation(name, desc));
}
public void endSubAnnotation()
{
// take the child and stick it at the end
ModAnnotation child = annotations.removeFirst();
annotations.addLast(child);
}
public void startMethodAnnotation(String methodName, String methodDescriptor, String annotationName)
{
ModAnnotation ann = new ModAnnotation(AnnotationType.METHOD, Type.getType(annotationName), methodName+methodDescriptor);
annotations.addFirst(ann);
}
}

View File

@ -33,9 +33,6 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData;
import net.minecraftforge.fml.common.discovery.ModCandidate;
import net.minecraftforge.fml.common.discovery.json.ASMInfo.Annotation;
import net.minecraftforge.fml.common.discovery.json.ASMInfo.TargetType;

View File

@ -28,8 +28,6 @@ import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.ModThreadContext;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.LoaderState;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.Mod.Instance;
@ -379,11 +377,11 @@ public class FMLInterModComms {
private static boolean enqueueStartupMessage(String modTarget, IMCMessage message)
{
if (ModThreadContext.get().getCurrentContainer() == null)
if (ModThreadContext.get().getActiveContainer() == null)
{
return false;
}
enqueueMessage(ModThreadContext.get().getCurrentContainer(), modTarget, message);
enqueueMessage(ModThreadContext.get().getActiveContainer(), modTarget, message);
return ModList.get().isLoaded(modTarget);
}

View File

@ -20,7 +20,6 @@
package net.minecraftforge.fml.common.event;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.common.ModMetadata;
/**
* Called before {@link FMLInitializationEvent} during mod startup.

View File

@ -20,7 +20,6 @@
package net.minecraftforge.fml.common.event;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.common.LoaderState.ModState;
/**
* Called before the server begins loading anything. Called after {@link FMLPostInitializationEvent} on the dedicated
@ -32,17 +31,11 @@ import net.minecraftforge.fml.common.LoaderState.ModState;
*/
public class FMLServerAboutToStartEvent extends FMLStateEvent {
private MinecraftServer server;
private final MinecraftServer server;
public FMLServerAboutToStartEvent(Object... data)
public FMLServerAboutToStartEvent(MinecraftServer server)
{
super(data);
this.server = (MinecraftServer) data[0];
}
@Override
public ModState getModState()
{
return ModState.AVAILABLE;
this.server = (MinecraftServer) server;
}
public MinecraftServer getServer()

View File

@ -19,8 +19,6 @@
package net.minecraftforge.fml.common.event;
import net.minecraftforge.fml.common.LoaderState.ModState;
/**
* Called after {@link FMLServerStartingEvent} when the server is available and ready to play.
*
@ -30,15 +28,7 @@ import net.minecraftforge.fml.common.LoaderState.ModState;
public class FMLServerStartedEvent extends FMLStateEvent
{
public FMLServerStartedEvent(Object... data)
public FMLServerStartedEvent()
{
super(data);
}
@Override
public ModState getModState()
{
return ModState.AVAILABLE;
}
}

View File

@ -22,7 +22,6 @@ package net.minecraftforge.fml.common.event;
import net.minecraft.command.CommandHandler;
import net.minecraft.command.ICommand;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.common.LoaderState.ModState;
/**
* Called after {@link FMLServerAboutToStartEvent} and before {@link FMLServerStartedEvent}.
@ -35,17 +34,11 @@ import net.minecraftforge.fml.common.LoaderState.ModState;
public class FMLServerStartingEvent extends FMLStateEvent
{
private MinecraftServer server;
private final MinecraftServer server;
public FMLServerStartingEvent(Object... data)
public FMLServerStartingEvent(final MinecraftServer server)
{
super(data);
this.server = (MinecraftServer) data[0];
}
@Override
public ModState getModState()
{
return ModState.AVAILABLE;
this.server = (MinecraftServer) server;
}
public MinecraftServer getServer()

View File

@ -19,8 +19,6 @@
package net.minecraftforge.fml.common.event;
import net.minecraftforge.fml.common.LoaderState.ModState;
/**
* Called after {@link FMLServerStoppingEvent} when the server has completely shut down.
* Called immediately before shutting down, on the dedicated server, and before returning
@ -30,15 +28,4 @@ import net.minecraftforge.fml.common.LoaderState.ModState;
* @author cpw
*/
public class FMLServerStoppedEvent extends FMLStateEvent {
public FMLServerStoppedEvent(Object... data)
{
super(data);
}
@Override
public ModState getModState()
{
return ModState.AVAILABLE;
}
}

Some files were not shown because too many files have changed in this diff Show More