From eac693e785d89d965113c84bda6333dd4ef55419 Mon Sep 17 00:00:00 2001 From: LexManos Date: Thu, 6 Sep 2018 06:27:24 -0700 Subject: [PATCH] Introduce rework of Capability provider. And reduce errors to <2000 --- .../minecraftforge/client/CloudRenderer.java | 8 +- .../client/FluidContainerColorer.java | 2 +- .../client/ForgeClientHandler.java | 7 +- .../client/model/Attributes.java | 4 +- .../client/model/ForgeBlockStateV1.java | 11 +- .../client/model/ICustomModelLoader.java | 8 +- .../client/model/ItemLayerModel.java | 12 +- .../client/model/ModelDynBucket.java | 21 +- .../client/model/ModelFluid.java | 20 +- .../client/model/ModelLoader.java | 29 +- .../client/model/MultiLayerModel.java | 18 +- .../client/model/SimpleModelFontRenderer.java | 3 +- .../client/model/b3d/B3DLoader.java | 25 +- .../client/model/obj/OBJLoader.java | 24 +- .../ISelectiveResourceReloadListener.java | 6 +- .../minecraftforge/common/UsernameCache.java | 10 +- .../common/WorldSpecificSaveHandler.java | 11 +- .../asm/CapabilityInjectDefinalize.java | 72 +++++ .../capabilities/CapabilityDispatcher.java | 25 +- .../capabilities/CapabilityManager.java | 6 +- .../capabilities/ICapabilityProvider.java | 50 ++-- .../common/capabilities/NonNullSupplier.java | 29 ++ .../OptionalCapabilityInstance.java | 247 ++++++++++++++++++ .../fluids/UniversalBucket.java | 12 +- ...odlauncher.serviceapi.ILaunchPluginService | 1 + 25 files changed, 485 insertions(+), 176 deletions(-) create mode 100644 src/main/java/net/minecraftforge/common/asm/CapabilityInjectDefinalize.java create mode 100644 src/main/java/net/minecraftforge/common/capabilities/NonNullSupplier.java create mode 100644 src/main/java/net/minecraftforge/common/capabilities/OptionalCapabilityInstance.java diff --git a/src/main/java/net/minecraftforge/client/CloudRenderer.java b/src/main/java/net/minecraftforge/client/CloudRenderer.java index 747aa055b..c98a7b318 100644 --- a/src/main/java/net/minecraftforge/client/CloudRenderer.java +++ b/src/main/java/net/minecraftforge/client/CloudRenderer.java @@ -380,7 +380,7 @@ public class CloudRenderer implements ISelectiveResourceReloadListener { vbo.bindBuffer(); - int stride = FORMAT.getNextOffset(); + int stride = FORMAT.getSize(); GlStateManager.glVertexPointer(3, GL11.GL_FLOAT, stride, 0); GlStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY); GlStateManager.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 12); @@ -390,9 +390,9 @@ public class CloudRenderer implements ISelectiveResourceReloadListener } else { - buffer.limit(FORMAT.getNextOffset()); + buffer.limit(FORMAT.getSize()); for (int i = 0; i < FORMAT.getElementCount(); i++) - FORMAT.getElements().get(i).getUsage().preDraw(FORMAT, i, FORMAT.getNextOffset(), buffer); + FORMAT.getElements().get(i).getUsage().preDraw(FORMAT, i, FORMAT.getSize(), buffer); buffer.position(0); } @@ -451,7 +451,7 @@ public class CloudRenderer implements ISelectiveResourceReloadListener buffer.limit(0); for (int i = 0; i < FORMAT.getElementCount(); i++) - FORMAT.getElements().get(i).getUsage().postDraw(FORMAT, i, FORMAT.getNextOffset(), buffer); + FORMAT.getElements().get(i).getUsage().postDraw(FORMAT, i, FORMAT.getSize(), buffer); buffer.position(0); // Disable our coloring. diff --git a/src/main/java/net/minecraftforge/client/FluidContainerColorer.java b/src/main/java/net/minecraftforge/client/FluidContainerColorer.java index cdfc53ec8..bf10b2fb3 100644 --- a/src/main/java/net/minecraftforge/client/FluidContainerColorer.java +++ b/src/main/java/net/minecraftforge/client/FluidContainerColorer.java @@ -29,7 +29,7 @@ import javax.annotation.Nonnull; public class FluidContainerColorer implements IItemColor { @Override - public int colorMultiplier(@Nonnull ItemStack stack, int tintIndex) + public int getColor(@Nonnull ItemStack stack, int tintIndex) { if (tintIndex != 1) return 0xFFFFFFFF; FluidStack fluidStack = FluidUtil.getFluidContained(stack); diff --git a/src/main/java/net/minecraftforge/client/ForgeClientHandler.java b/src/main/java/net/minecraftforge/client/ForgeClientHandler.java index e2a2c86a8..b347f036c 100644 --- a/src/main/java/net/minecraftforge/client/ForgeClientHandler.java +++ b/src/main/java/net/minecraftforge/client/ForgeClientHandler.java @@ -22,9 +22,10 @@ package net.minecraftforge.client; import net.minecraftforge.client.event.ColorHandlerEvent; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.ForgeModContainer; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fluids.FluidRegistry; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class ForgeClientHandler { @@ -34,7 +35,7 @@ public class ForgeClientHandler // register model for the universal bucket, if it exists if (FluidRegistry.isUniversalBucketEnabled()) { - ModelLoader.setBucketModelDefinition(ForgeModContainer.getInstance().universalBucket); + ModelLoader.setBucketModelDefinition(ForgeMod.getInstance().universalBucket); } } @@ -43,7 +44,7 @@ public class ForgeClientHandler { if (FluidRegistry.isUniversalBucketEnabled()) { - event.getItemColors().registerItemColorHandler(new FluidContainerColorer(), ForgeModContainer.getInstance().universalBucket); + event.getItemColors().registerItemColorHandler(new FluidContainerColorer(), ForgeMod.getInstance().universalBucket); } } } diff --git a/src/main/java/net/minecraftforge/client/model/Attributes.java b/src/main/java/net/minecraftforge/client/model/Attributes.java index c059d660f..2620ae3d0 100644 --- a/src/main/java/net/minecraftforge/client/model/Attributes.java +++ b/src/main/java/net/minecraftforge/client/model/Attributes.java @@ -45,8 +45,8 @@ public class Attributes */ public static boolean moreSpecific(VertexFormat first, VertexFormat second) { - int size = first.getNextOffset(); - if(size != second.getNextOffset()) return false; + int size = first.getSize(); + if(size != second.getSize()) return false; int padding = 0; int j = 0; diff --git a/src/main/java/net/minecraftforge/client/model/ForgeBlockStateV1.java b/src/main/java/net/minecraftforge/client/model/ForgeBlockStateV1.java index 06ca6bdf8..989dcede9 100644 --- a/src/main/java/net/minecraftforge/client/model/ForgeBlockStateV1.java +++ b/src/main/java/net/minecraftforge/client/model/ForgeBlockStateV1.java @@ -35,6 +35,9 @@ import javax.vecmath.Matrix4f; import javax.vecmath.Quat4f; import javax.vecmath.Vector3f; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.block.model.ModelRotation; import net.minecraft.util.JsonUtils; @@ -43,7 +46,6 @@ import net.minecraftforge.client.model.BlockStateLoader.Marker; import net.minecraftforge.client.model.BlockStateLoader.SubModel; import net.minecraftforge.common.model.IModelState; import net.minecraftforge.common.model.TRSRTransformation; -import net.minecraftforge.fml.common.FMLLog; import java.util.Objects; import java.util.Optional; @@ -62,6 +64,7 @@ import com.google.gson.JsonParseException; public class ForgeBlockStateV1 extends Marker { + private static final Logger LOGGER = LogManager.getLogger(); ForgeBlockStateV1.Variant defaults; Multimap variants = LinkedHashMultimap.create(); @@ -181,9 +184,9 @@ public class ForgeBlockStateV1 extends Marker String value = v.textures.get(tex.getValue().substring(1)); if (value == null) { - FMLLog.log.fatal("Could not resolve texture name \"{}\" for permutation \"{}\"", tex.getValue(), e.getKey()); + LOGGER.fatal("Could not resolve texture name \"{}\" for permutation \"{}\"", tex.getValue(), e.getKey()); for (Entry t: v.textures.entrySet()) - FMLLog.log.fatal("{}={}", t.getKey(), t.getValue()); + LOGGER.fatal("{}={}", t.getKey(), t.getValue()); throw new JsonParseException("Could not resolve texture name \"" + tex.getValue() + "\" for permutation \"" + e.getKey() + "\""); } v.textures.put(tex.getKey(), value); @@ -441,7 +444,7 @@ public class ForgeBlockStateV1 extends Marker protected ResourceLocation getBlockLocation(String location) { ResourceLocation tmp = new ResourceLocation(location); - return new ResourceLocation(tmp.getResourceDomain(), "block/" + tmp.getResourcePath()); + return new ResourceLocation(tmp.getNamespace(), "block/" + tmp.getPath()); } /** Throws an error if there are submodels in this submodel. */ diff --git a/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java b/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java index f7a9d4eda..2545cfab7 100644 --- a/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java +++ b/src/main/java/net/minecraftforge/client/model/ICustomModelLoader.java @@ -24,22 +24,20 @@ import java.util.function.Predicate; import net.minecraftforge.client.resource.IResourceType; import net.minecraftforge.client.resource.ISelectiveResourceReloadListener; import net.minecraftforge.client.resource.VanillaResourceType; - -import net.minecraft.client.resources.IResourceManager; -import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.ResourceLocation; public interface ICustomModelLoader extends ISelectiveResourceReloadListener { @Override - void onResourceManagerReload(IResourceManager resourceManager); + void func_195410_a(IResourceManager resourceManager); @Override default void onResourceManagerReload(IResourceManager resourceManager, Predicate resourcePredicate) { if (resourcePredicate.test(VanillaResourceType.MODELS)) { - onResourceManagerReload(resourceManager); + func_195410_a(resourceManager); } } diff --git a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java index c117056aa..acb22885a 100644 --- a/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java +++ b/src/main/java/net/minecraftforge/client/model/ItemLayerModel.java @@ -30,7 +30,7 @@ import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.block.model.ModelBlock; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.resources.IResourceManager; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; @@ -449,15 +449,15 @@ public final class ItemLayerModel implements IModel INSTANCE; @Override - public void onResourceManagerReload(IResourceManager resourceManager) {} + public void func_195410_a(IResourceManager resourceManager) {} @Override public boolean accepts(ResourceLocation modelLocation) { - return modelLocation.getResourceDomain().equals(ForgeVersion.MOD_ID) && ( - modelLocation.getResourcePath().equals("item-layer") || - modelLocation.getResourcePath().equals("models/block/item-layer") || - modelLocation.getResourcePath().equals("models/item/item-layer")); + return modelLocation.getNamespace().equals(ForgeVersion.MOD_ID) && ( + modelLocation.getPath().equals("item-layer") || + modelLocation.getPath().equals("models/block/item-layer") || + modelLocation.getPath().equals("models/item/item-layer")); } @Override diff --git a/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java b/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java index 0d248c2d8..95e489d9f 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java +++ b/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java @@ -36,10 +36,10 @@ import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.resources.IResource; -import net.minecraft.client.resources.IResourceManager; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; +import net.minecraft.resources.IResource; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; @@ -61,11 +61,13 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; -import net.minecraftforge.fml.common.FMLLog; import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; public final class ModelDynBucket implements IModel { + private static final Logger LOGGER = LogManager.getLogger(); public static final ModelResourceLocation LOCATION = new ModelResourceLocation(new ResourceLocation(ForgeVersion.MOD_ID, "dynbucket"), "inventory"); // minimal Z offset to prevent depth-fighting @@ -93,13 +95,6 @@ public final class ModelDynBucket implements IModel this(null, null, null, null, false, true); } - /** @deprecated use {@link #ModelDynBucket(ResourceLocation, ResourceLocation, ResourceLocation, Fluid, boolean, boolean)} */ - @Deprecated // TODO: remove - public ModelDynBucket(@Nullable ResourceLocation baseLocation, @Nullable ResourceLocation liquidLocation, @Nullable ResourceLocation coverLocation, @Nullable Fluid fluid, boolean flipGas) - { - this(baseLocation, liquidLocation, coverLocation, fluid, flipGas, true); - } - public ModelDynBucket(@Nullable ResourceLocation baseLocation, @Nullable ResourceLocation liquidLocation, @Nullable ResourceLocation coverLocation, @Nullable Fluid fluid, boolean flipGas, boolean tint) { this.baseLocation = baseLocation; @@ -255,7 +250,7 @@ public final class ModelDynBucket implements IModel @Override public boolean accepts(ResourceLocation modelLocation) { - return modelLocation.getResourceDomain().equals(ForgeVersion.MOD_ID) && modelLocation.getResourcePath().contains("forgebucket"); + return modelLocation.getNamespace().equals(ForgeVersion.MOD_ID) && modelLocation.getPath().contains("forgebucket"); } @Override @@ -265,7 +260,7 @@ public final class ModelDynBucket implements IModel } @Override - public void onResourceManagerReload(IResourceManager resourceManager) + public void func_195410_a(IResourceManager resourceManager) { // no need to clear cache since we create a new model instance } @@ -397,7 +392,7 @@ public final class ModelDynBucket implements IModel } catch (IOException e) { - FMLLog.log.error("Failed to close resource", e); + LOGGER.error("Failed to close resource", e); } this.clearFramesTextureData(); diff --git a/src/main/java/net/minecraftforge/client/model/ModelFluid.java b/src/main/java/net/minecraftforge/client/model/ModelFluid.java index bde861d53..0fb18a3eb 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelFluid.java +++ b/src/main/java/net/minecraftforge/client/model/ModelFluid.java @@ -36,7 +36,7 @@ import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformT import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.resources.IResourceManager; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; @@ -48,9 +48,10 @@ import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fluids.BlockFluidBase; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; -import net.minecraftforge.fml.common.FMLLog; import org.apache.commons.lang3.tuple.Pair; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -63,6 +64,7 @@ import com.google.gson.JsonParser; public final class ModelFluid implements IModel { + private static final Logger LOGGER = LogManager.getLogger(); public static final ModelFluid WATER = new ModelFluid(FluidRegistry.WATER); public static final ModelFluid LAVA = new ModelFluid(FluidRegistry.LAVA); @@ -102,15 +104,15 @@ public final class ModelFluid implements IModel INSTANCE; @Override - public void onResourceManagerReload(IResourceManager resourceManager) {} + public void func_195410_a(IResourceManager resourceManager) {} @Override public boolean accepts(ResourceLocation modelLocation) { - return modelLocation.getResourceDomain().equals(ForgeVersion.MOD_ID) && ( - modelLocation.getResourcePath().equals("fluid") || - modelLocation.getResourcePath().equals("models/block/fluid") || - modelLocation.getResourcePath().equals("models/item/fluid")); + return modelLocation.getNamespace().equals(ForgeVersion.MOD_ID) && ( + modelLocation.getPath().equals("fluid") || + modelLocation.getPath().equals("models/block/fluid") || + modelLocation.getPath().equals("models/item/fluid")); } @Override @@ -346,7 +348,7 @@ public final class ModelFluid implements IModel // sides for (int i = 0; i < 4; i++) { - EnumFacing side = EnumFacing.getHorizontal((5 - i) % 4); // [W, S, E, N] + EnumFacing side = EnumFacing.byHorizontalIndex((5 - i) % 4); // [W, S, E, N] boolean useOverlay = overlay.isPresent() && sideOverlays[side.getHorizontalIndex()]; int si = i; // local var for lambda capture @@ -502,7 +504,7 @@ public final class ModelFluid implements IModel String fluid = e.getAsString(); if(!FluidRegistry.isFluidRegistered(fluid)) { - FMLLog.log.fatal("fluid '{}' not found", fluid); + LOGGER.fatal("fluid '{}' not found", fluid); return WATER; } return new ModelFluid(FluidRegistry.getFluid(fluid)); diff --git a/src/main/java/net/minecraftforge/client/model/ModelLoader.java b/src/main/java/net/minecraftforge/client/model/ModelLoader.java index 449c9c731..c041cec67 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelLoader.java +++ b/src/main/java/net/minecraftforge/client/model/ModelLoader.java @@ -35,8 +35,8 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BlockModelShapes; -import net.minecraft.client.renderer.ItemMeshDefinition; import net.minecraft.client.renderer.ItemModelMesher; +import net.minecraft.client.renderer.Vector3f; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.BlockPart; import net.minecraft.client.renderer.block.model.BlockPartFace; @@ -50,7 +50,6 @@ import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelBlock; import net.minecraft.client.renderer.block.model.ModelBlockDefinition; -import net.minecraft.client.renderer.block.model.ModelBlockDefinition.MissingVariantException; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.block.model.MultipartBakedModel; import net.minecraft.client.renderer.block.model.SimpleBakedModel; @@ -59,14 +58,12 @@ import net.minecraft.client.renderer.block.model.VariantList; import net.minecraft.client.renderer.block.model.WeightedBakedModel; import net.minecraft.client.renderer.block.model.multipart.Multipart; import net.minecraft.client.renderer.block.model.multipart.Selector; -import net.minecraft.client.renderer.block.statemap.BlockStateMapper; -import net.minecraft.client.renderer.block.statemap.IStateMapper; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.resources.IResourceManager; import net.minecraft.item.Item; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.util.registry.IRegistry; @@ -81,7 +78,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.common.FMLLog; import net.minecraftforge.fml.common.ProgressManager; import net.minecraftforge.fml.common.ProgressManager.ProgressBar; import net.minecraftforge.logging.ModelLoaderErrorMessage; @@ -183,7 +179,7 @@ public final class ModelLoader extends ModelBakery } catch (Exception e) { - FMLLog.log.error("Exception baking model for location(s) {}:", modelLocations, e); + LOGGEr.error("Exception baking model for location(s) {}:", modelLocations, e); bakedModels.put(model, missingBaked); } } @@ -335,7 +331,7 @@ public final class ModelLoader extends ModelBakery @Override protected ResourceLocation getModelLocation(ResourceLocation model) { - return new ResourceLocation(model.getResourceDomain(), model.getResourcePath() + ".json"); + return new ResourceLocation(model.getNamespace(), model.getPath() + ".json"); } private final class VanillaModelWrapper implements IModel @@ -474,7 +470,7 @@ public final class ModelLoader extends ModelBakery { transformation = transformation.compose(newTransforms.get(i)); BlockPartRotation rot = part.partRotation; - if(rot == null) rot = new BlockPartRotation(new org.lwjgl.util.vector.Vector3f(), EnumFacing.Axis.Y, 0, false); + if(rot == null) rot = new BlockPartRotation(new Vector3f(), EnumFacing.Axis.Y, 0, false); part = new BlockPart(part.positionFrom, part.positionTo, part.mapFaces, rot, part.shade); } for(Map.Entry e : part.mapFaces.entrySet()) @@ -764,7 +760,7 @@ public final class ModelLoader extends ModelBakery { try { - missingModel = VanillaLoader.INSTANCE.loadModel(new ResourceLocation(MODEL_MISSING.getResourceDomain(), MODEL_MISSING.getResourcePath())); + missingModel = VanillaLoader.INSTANCE.loadModel(new ResourceLocation(MODEL_MISSING.getNamespace(), MODEL_MISSING.getPath())); } catch(Exception e) { @@ -838,7 +834,7 @@ public final class ModelLoader extends ModelBakery // NOOP, handled in loader @Override - public void onResourceManagerReload(IResourceManager resourceManager) {} + public void func_195410_a(IResourceManager resourceManager) {} @Override public boolean accepts(ResourceLocation modelLocation) @@ -853,12 +849,12 @@ public final class ModelLoader extends ModelBakery { return loader.getMissingModel(); } - String modelPath = modelLocation.getResourcePath(); - if(modelLocation.getResourcePath().startsWith("models/")) + String modelPath = modelLocation.getPath(); + if(modelLocation.getPath().startsWith("models/")) { modelPath = modelPath.substring("models/".length()); } - ResourceLocation armatureLocation = new ResourceLocation(modelLocation.getResourceDomain(), "armatures/" + modelPath + ".json"); + ResourceLocation armatureLocation = new ResourceLocation(modelLocation.getNamespace(), "armatures/" + modelPath + ".json"); ModelBlockAnimation animation = ModelBlockAnimation.loadVanillaAnimation(loader.resourceManager, armatureLocation); ModelBlock model = loader.loadModel(modelLocation); IModel iModel = loader.new VanillaModelWrapper(modelLocation, model, false, animation); @@ -917,6 +913,7 @@ public final class ModelLoader extends ModelBakery } } + @SuppressWarnings("serial") public static class ItemLoadingException extends ModelLoaderRegistry.LoaderException { private final Exception normalException; @@ -1065,7 +1062,7 @@ public final class ModelLoader extends ModelBakery // NOOP, handled in loader @Override - public void onResourceManagerReload(IResourceManager resourceManager) {} + public void func_195410_a(IResourceManager resourceManager) {} @Override public boolean accepts(ResourceLocation modelLocation) @@ -1091,7 +1088,7 @@ public final class ModelLoader extends ModelBakery IModel model = loader.multipartModels.get(definition); if (model == null) { - model = new MultipartModel(new ResourceLocation(variant.getResourceDomain(), variant.getResourcePath()), definition.getMultipartData()); + model = new MultipartModel(new ResourceLocation(variant.getNamespace(), variant.getPath()), definition.getMultipartData()); loader.multipartModels.put(definition, model); } return model; diff --git a/src/main/java/net/minecraftforge/client/model/MultiLayerModel.java b/src/main/java/net/minecraftforge/client/model/MultiLayerModel.java index 2479b77f4..909018022 100644 --- a/src/main/java/net/minecraftforge/client/model/MultiLayerModel.java +++ b/src/main/java/net/minecraftforge/client/model/MultiLayerModel.java @@ -33,7 +33,7 @@ import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.resources.IResourceManager; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; @@ -41,9 +41,10 @@ import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.ForgeVersion; import net.minecraftforge.common.model.IModelState; import net.minecraftforge.common.model.TRSRTransformation; -import net.minecraftforge.fml.common.FMLLog; import org.apache.commons.lang3.tuple.Pair; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.util.function.Function; import java.util.Optional; @@ -54,6 +55,7 @@ import com.google.gson.JsonParser; public final class MultiLayerModel implements IModel { + private static final Logger LOGGER = LogManager.getLogger(); public static final MultiLayerModel INSTANCE = new MultiLayerModel(ImmutableMap.of()); private final ImmutableMap, ModelResourceLocation> models; @@ -121,7 +123,7 @@ public final class MultiLayerModel implements IModel { return new ModelResourceLocation(e.getAsString()); } - FMLLog.log.fatal("Expect ModelResourceLocation, got: {}", json); + LOGGER.fatal("Expect ModelResourceLocation, got: {}", json); return new ModelResourceLocation("builtin/missing", "missing"); } @@ -205,15 +207,15 @@ public final class MultiLayerModel implements IModel INSTANCE; @Override - public void onResourceManagerReload(IResourceManager resourceManager) {} + public void func_195410_a(IResourceManager resourceManager) {} @Override public boolean accepts(ResourceLocation modelLocation) { - return modelLocation.getResourceDomain().equals(ForgeVersion.MOD_ID) && ( - modelLocation.getResourcePath().equals("multi-layer") || - modelLocation.getResourcePath().equals("models/block/multi-layer") || - modelLocation.getResourcePath().equals("models/item/multi-layer")); + return modelLocation.getNamespace().equals(ForgeVersion.MOD_ID) && ( + modelLocation.getPath().equals("multi-layer") || + modelLocation.getPath().equals("models/block/multi-layer") || + modelLocation.getPath().equals("models/item/multi-layer")); } @Override diff --git a/src/main/java/net/minecraftforge/client/model/SimpleModelFontRenderer.java b/src/main/java/net/minecraftforge/client/model/SimpleModelFontRenderer.java index f7d89ea59..d7730b653 100644 --- a/src/main/java/net/minecraftforge/client/model/SimpleModelFontRenderer.java +++ b/src/main/java/net/minecraftforge/client/model/SimpleModelFontRenderer.java @@ -28,14 +28,13 @@ import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; import com.google.common.collect.ImmutableList; +import net.minecraft.client.GameSettings; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.resources.IResourceManager; -import net.minecraft.client.settings.GameSettings; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java index 7867c9e60..582f86b38 100644 --- a/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java +++ b/src/main/java/net/minecraftforge/client/model/b3d/B3DLoader.java @@ -40,8 +40,8 @@ import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformT import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.resources.IResource; -import net.minecraft.client.resources.IResourceManager; +import net.minecraft.resources.IResource; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; @@ -68,7 +68,6 @@ import net.minecraftforge.common.model.animation.IJoint; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.common.property.IUnlistedProperty; import net.minecraftforge.common.property.Properties; -import net.minecraftforge.fml.common.FMLLog; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.tuple.Pair; @@ -108,7 +107,7 @@ public enum B3DLoader implements ICustomModelLoader } @Override - public void onResourceManagerReload(IResourceManager manager) + public void func_195410_a(IResourceManager manager) { this.manager = manager; cache.clear(); @@ -117,14 +116,14 @@ public enum B3DLoader implements ICustomModelLoader @Override public boolean accepts(ResourceLocation modelLocation) { - return enabledDomains.contains(modelLocation.getResourceDomain()) && modelLocation.getResourcePath().endsWith(".b3d"); + return enabledDomains.contains(modelLocation.getNamespace()) && modelLocation.getPath().endsWith(".b3d"); } @Override @SuppressWarnings("unchecked") public IModel loadModel(ResourceLocation modelLocation) throws Exception { - ResourceLocation file = new ResourceLocation(modelLocation.getResourceDomain(), modelLocation.getResourcePath()); + ResourceLocation file = new ResourceLocation(modelLocation.getNamespace(), modelLocation.getPath()); if(!cache.containsKey(file)) { IResource resource = null; @@ -136,10 +135,10 @@ public enum B3DLoader implements ICustomModelLoader } catch(FileNotFoundException e) { - if(modelLocation.getResourcePath().startsWith("models/block/")) - resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/item/" + file.getResourcePath().substring("models/block/".length()))); - else if(modelLocation.getResourcePath().startsWith("models/item/")) - resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/block/" + file.getResourcePath().substring("models/item/".length()))); + if(modelLocation.getPath().startsWith("models/block/")) + resource = manager.getResource(new ResourceLocation(file.getNamespace(), "models/item/" + file.getPath().substring("models/block/".length()))); + else if(modelLocation.getPath().startsWith("models/item/")) + resource = manager.getResource(new ResourceLocation(file.getNamespace(), "models/block/" + file.getPath().substring("models/item/".length()))); else throw e; } B3DModel.Parser parser = new B3DModel.Parser(resource.getInputStream()); @@ -452,7 +451,7 @@ public enum B3DLoader implements ICustomModelLoader @Override public Collection getTextures() { - return Collections2.filter(textures.values(), loc -> !loc.getResourcePath().startsWith("#")); + return Collections2.filter(textures.values(), loc -> !loc.getPath().startsWith("#")); } @Override @@ -462,9 +461,9 @@ public enum B3DLoader implements ICustomModelLoader TextureAtlasSprite missing = bakedTextureGetter.apply(new ResourceLocation("missingno")); for(Map.Entry e : textures.entrySet()) { - if(e.getValue().getResourcePath().startsWith("#")) + if(e.getValue().getPath().startsWith("#")) { - FMLLog.log.fatal("unresolved texture '{}' for b3d model '{}'", e.getValue().getResourcePath(), modelLocation); + FMLLog.log.fatal("unresolved texture '{}' for b3d model '{}'", e.getValue().getPath(), modelLocation); builder.put(e.getKey(), missing); } else diff --git a/src/main/java/net/minecraftforge/client/model/obj/OBJLoader.java b/src/main/java/net/minecraftforge/client/model/obj/OBJLoader.java index 4f7d9e4e6..0e1208aa7 100644 --- a/src/main/java/net/minecraftforge/client/model/obj/OBJLoader.java +++ b/src/main/java/net/minecraftforge/client/model/obj/OBJLoader.java @@ -25,16 +25,17 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import net.minecraft.client.resources.IResource; -import net.minecraft.client.resources.IResourceManager; +import net.minecraft.resources.IResource; +import net.minecraft.resources.IResourceManager; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ICustomModelLoader; import net.minecraftforge.client.model.IModel; import net.minecraftforge.client.model.ModelLoaderRegistry; -import net.minecraftforge.fml.common.FMLLog; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /* * Loader for OBJ models. @@ -44,6 +45,7 @@ import org.apache.logging.log4j.Level; public enum OBJLoader implements ICustomModelLoader { INSTANCE; + private static final Logger LOGGER = LogManager.getLogger(); private IResourceManager manager; private final Set enabledDomains = new HashSet<>(); private final Map cache = new HashMap<>(); @@ -52,11 +54,11 @@ public enum OBJLoader implements ICustomModelLoader { public void addDomain(String domain) { enabledDomains.add(domain.toLowerCase()); - FMLLog.log.info("OBJLoader: Domain {} has been added.", domain.toLowerCase()); + LOGGER.info("OBJLoader: Domain {} has been added.", domain.toLowerCase()); } @Override - public void onResourceManagerReload(IResourceManager resourceManager) + public void func_195410_a(IResourceManager resourceManager) { this.manager = resourceManager; cache.clear(); @@ -66,13 +68,13 @@ public enum OBJLoader implements ICustomModelLoader { @Override public boolean accepts(ResourceLocation modelLocation) { - return enabledDomains.contains(modelLocation.getResourceDomain()) && modelLocation.getResourcePath().endsWith(".obj"); + return enabledDomains.contains(modelLocation.getNamespace()) && modelLocation.getPath().endsWith(".obj"); } @Override public IModel loadModel(ResourceLocation modelLocation) throws Exception { - ResourceLocation file = new ResourceLocation(modelLocation.getResourceDomain(), modelLocation.getResourcePath()); + ResourceLocation file = new ResourceLocation(modelLocation.getNamespace(), modelLocation.getPath()); if (!cache.containsKey(file)) { IResource resource = null; @@ -84,10 +86,10 @@ public enum OBJLoader implements ICustomModelLoader { } catch (FileNotFoundException e) { - if (modelLocation.getResourcePath().startsWith("models/block/")) - resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/item/" + file.getResourcePath().substring("models/block/".length()))); - else if (modelLocation.getResourcePath().startsWith("models/item/")) - resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/block/" + file.getResourcePath().substring("models/item/".length()))); + if (modelLocation.getPath().startsWith("models/block/")) + resource = manager.getResource(new ResourceLocation(file.getNamespace(), "models/item/" + file.getPath().substring("models/block/".length()))); + else if (modelLocation.getPath().startsWith("models/item/")) + resource = manager.getResource(new ResourceLocation(file.getNamespace(), "models/block/" + file.getPath().substring("models/item/".length()))); else throw e; } OBJModel.Parser parser = new OBJModel.Parser(resource, manager); diff --git a/src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java b/src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java index cbc124617..dbfb83c90 100644 --- a/src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java +++ b/src/main/java/net/minecraftforge/client/resource/ISelectiveResourceReloadListener.java @@ -21,13 +21,13 @@ package net.minecraftforge.client.resource; import java.util.function.Predicate; -import net.minecraft.client.resources.IResourceManager; -import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.resources.IResourceManager; +import net.minecraft.resources.IResourceManagerReloadListener; public interface ISelectiveResourceReloadListener extends IResourceManagerReloadListener { @Override - default void onResourceManagerReload(IResourceManager resourceManager) + default void func_195410_a(IResourceManager resourceManager) { // For compatibility, call the selective version from the non-selective function onResourceManagerReload(resourceManager, SelectiveReloadStateHandler.INSTANCE.get()); diff --git a/src/main/java/net/minecraftforge/common/UsernameCache.java b/src/main/java/net/minecraftforge/common/UsernameCache.java index bc86da57d..b70fdb840 100644 --- a/src/main/java/net/minecraftforge/common/UsernameCache.java +++ b/src/main/java/net/minecraftforge/common/UsernameCache.java @@ -20,9 +20,9 @@ package net.minecraftforge.common; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.IOException; import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; @@ -33,7 +33,6 @@ import java.util.UUID; import javax.annotation.Nullable; import com.google.common.base.Charsets; -import net.minecraft.world.storage.ThreadedFileIOBase; import net.minecraftforge.fml.loading.FMLLoader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -162,6 +161,7 @@ public final class UsernameCache { try (final BufferedReader reader = Files.newBufferedReader(saveFile, Charsets.UTF_8)) { + @SuppressWarnings("serial") Type type = new TypeToken>(){}.getType(); map = gson.fromJson(reader, type); } @@ -209,13 +209,13 @@ public final class UsernameCache { // Make sure we don't save when another thread is still saving synchronized (saveFile) { - Files.write(data, saveFile, charset); + Files.write(saveFile, data.getBytes(StandardCharsets.UTF_8)); } } catch (IOException e) { - log.error("Failed to save username cache to file!", e); + LOGGER.error(USRCACHE, "Failed to save username cache to file!", e); } } } -} \ No newline at end of file +} diff --git a/src/main/java/net/minecraftforge/common/WorldSpecificSaveHandler.java b/src/main/java/net/minecraftforge/common/WorldSpecificSaveHandler.java index b990adf7c..52fa8fa21 100644 --- a/src/main/java/net/minecraftforge/common/WorldSpecificSaveHandler.java +++ b/src/main/java/net/minecraftforge/common/WorldSpecificSaveHandler.java @@ -22,20 +22,19 @@ package net.minecraftforge.common; import java.io.File; import java.io.IOException; -import net.minecraft.world.gen.structure.template.TemplateManager; import org.apache.logging.log4j.Level; import com.google.common.io.Files; +import com.mojang.datafixers.DataFixer; import net.minecraft.world.chunk.storage.IChunkLoader; +import net.minecraft.world.dimension.Dimension; +import net.minecraft.world.gen.feature.template.TemplateManager; import net.minecraft.world.storage.IPlayerFileData; import net.minecraft.world.storage.ISaveHandler; -import net.minecraft.world.MinecraftException; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.storage.WorldInfo; -import net.minecraft.world.WorldProvider; import net.minecraft.world.WorldServer; -import net.minecraftforge.fml.common.FMLLog; //Class used internally to provide the world specific data directories. @@ -53,12 +52,13 @@ public class WorldSpecificSaveHandler implements ISaveHandler @Override public WorldInfo loadWorldInfo() { return parent.loadWorldInfo(); } @Override public void checkSessionLock() throws MinecraftException { parent.checkSessionLock(); } - @Override public IChunkLoader getChunkLoader(WorldProvider var1) { return parent.getChunkLoader(var1); } + @Override public IChunkLoader getChunkLoader(Dimension var1) { return parent.getChunkLoader(var1); } @Override public void saveWorldInfoWithPlayer(WorldInfo var1, NBTTagCompound var2) { parent.saveWorldInfoWithPlayer(var1, var2); } @Override public void saveWorldInfo(WorldInfo var1){ parent.saveWorldInfo(var1); } @Override public IPlayerFileData getPlayerNBTManager() { return parent.getPlayerNBTManager(); } @Override public void flush() { parent.flush(); } @Override public File getWorldDirectory() { return parent.getWorldDirectory(); } + @Override public DataFixer func_197718_i() { return parent.func_197718_i(); } @Override public File getMapFileFromName(String name) @@ -105,5 +105,4 @@ public class WorldSpecificSaveHandler implements ISaveHandler { return parent.getStructureTemplateManager(); } - } diff --git a/src/main/java/net/minecraftforge/common/asm/CapabilityInjectDefinalize.java b/src/main/java/net/minecraftforge/common/asm/CapabilityInjectDefinalize.java new file mode 100644 index 000000000..08cfd373f --- /dev/null +++ b/src/main/java/net/minecraftforge/common/asm/CapabilityInjectDefinalize.java @@ -0,0 +1,72 @@ +/* + * 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.common.asm; + +import java.nio.file.Path; +import java.util.List; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AnnotationNode; +import org.objectweb.asm.tree.ClassNode; +import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; + +/** + * Removes the final modifier from fields with the @CapabilityInject annotation, prevents the JITer from in lining them so our runtime replacements can work. + */ +public class CapabilityInjectDefinalize implements ILaunchPluginService { + + private final String CAP = "Lnet/minecraftforge/common/capabilities/Capability;"; //Don't directly reference this to prevent class loading. + private final String CAP_INJECT = "Lnet/minecraftforge/common/capabilities/CapabilityInject;"; //Don't directly reference this to prevent class loading. + + @Override + public String name() { + return "capability_inject_definalize"; + } + + @Override public void addResource(Path resource, String name) { } + + @Override public T getExtension() { return null; } // ? + + @Override + public boolean handlesClass(Type classType, boolean isEmpty) + { + return !isEmpty; //Check for annotations? + } + + private boolean hasHolder(List lst) + { + return lst != null && lst.stream().anyMatch(n -> n.desc.equals(CAP_INJECT)); + } + + @Override + public ClassNode processClass(ClassNode classNode, Type classType) + { + final int flags = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; + + classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.equals(CAP) && hasHolder(f.visibleAnnotations)).forEach(f -> + { + f.access &= ~Opcodes.ACC_FINAL; //Strip final + f.access |= Opcodes.ACC_SYNTHETIC; //Add Synthetic so we can check in runtime. + }); + + return classNode; + } + +} diff --git a/src/main/java/net/minecraftforge/common/capabilities/CapabilityDispatcher.java b/src/main/java/net/minecraftforge/common/capabilities/CapabilityDispatcher.java index c597038d0..881ff6ed5 100644 --- a/src/main/java/net/minecraftforge/common/capabilities/CapabilityDispatcher.java +++ b/src/main/java/net/minecraftforge/common/capabilities/CapabilityDispatcher.java @@ -19,7 +19,6 @@ package net.minecraftforge.common.capabilities; -import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Map; @@ -86,32 +85,18 @@ public final class CapabilityDispatcher implements INBTSerializable capability, @Nullable EnumFacing facing) - { - for (ICapabilityProvider cap : caps) - { - if (cap.hasCapability(capability, facing)) - { - return true; - } - } - return false; - } @Override - @Nullable - public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) + public OptionalCapabilityInstance getCapability(Capability cap, EnumFacing side) { - for (ICapabilityProvider cap : caps) + for (ICapabilityProvider c : caps) { - T ret = cap.getCapability(capability, facing); - if (ret != null) - { + OptionalCapabilityInstance ret = c.getCapability(cap, side); + if (ret.isPresent()) { return ret; } } - return null; + return OptionalCapabilityInstance.empty(); } @Override diff --git a/src/main/java/net/minecraftforge/common/capabilities/CapabilityManager.java b/src/main/java/net/minecraftforge/common/capabilities/CapabilityManager.java index a9402f168..1b4ea93ed 100644 --- a/src/main/java/net/minecraftforge/common/capabilities/CapabilityManager.java +++ b/src/main/java/net/minecraftforge/common/capabilities/CapabilityManager.java @@ -38,8 +38,6 @@ import org.objectweb.asm.Type; import java.util.function.Function; import java.util.stream.Collectors; -import net.minecraftforge.common.util.EnumHelper; - import static net.minecraftforge.fml.Logging.CAPABILITIES; public enum CapabilityManager @@ -138,8 +136,8 @@ public enum CapabilityManager LOGGER.warn(CAPABILITIES,"Unable to inject capability {} at {}.{} (Non-Static)", capabilityName, targetClass, targetName); return null; } - // TODO Remove enumhelper here - EnumHelper.setFailsafeFieldValue(field, null, input); + field.setAccessible(true); + field.set(null, input); } catch (Exception e) { diff --git a/src/main/java/net/minecraftforge/common/capabilities/ICapabilityProvider.java b/src/main/java/net/minecraftforge/common/capabilities/ICapabilityProvider.java index 5bf8a3fa4..b95380fdc 100644 --- a/src/main/java/net/minecraftforge/common/capabilities/ICapabilityProvider.java +++ b/src/main/java/net/minecraftforge/common/capabilities/ICapabilityProvider.java @@ -19,8 +19,6 @@ package net.minecraftforge.common.capabilities; -import java.util.Map; - import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -29,41 +27,23 @@ import net.minecraft.util.EnumFacing; public interface ICapabilityProvider { /** - * Determines if this object has support for the capability in question on the specific side. - * The return value of this MIGHT change during runtime if this object gains or loses support - * for a capability. It is not required to call this function before calling - * {@link #getCapability(Capability, EnumFacing)}. - *

- * Basically, this method functions analogously to {@link Map#containsKey(Object)}. - *

- * Example: - * A Pipe getting a cover placed on one side causing it lose the Inventory attachment function for that side. - *

- * This is a light weight version of getCapability, intended for metadata uses. - *

- * @param capability The capability to check - * @param facing The Side to check from: - * CAN BE NULL. Null is defined to represent 'internal' or 'self' - * @return True if this object supports the capability. If true, then {@link #getCapability(Capability, EnumFacing)} - * must not return null. - */ - boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing); - - /** - * Retrieves the handler for the capability requested on the specific side. - *
    - *
  • The return value CAN be null if the object does not support the capability. - *
  • The return value CAN be the same for multiple faces.
  • - *
- *

- * Basically, this method functions analogously to {@link Map#get(Object)}. + * Retrieves the Optional handler for the capability requested on the specific side. + * The return value CAN be the same for multiple faces. + * Modders are encouraged to cache this value, using the listener capabilities of the Optional to + * be notified if the requested capability get lost. * * @param capability The capability to check - * @param facing The Side to check from, + * @param facing The Side to check from, * CAN BE NULL. Null is defined to represent 'internal' or 'self' - * @return The requested capability. Must NOT be null when {@link #hasCapability(Capability, EnumFacing)} - * would return true. + * @return The requested an optional holding the requested capability. */ - @Nullable - T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing); + @Nonnull OptionalCapabilityInstance getCapability(@Nonnull final Capability cap, final @Nullable EnumFacing side); + + /* + * Purely added as a bouncer to sided version, to make modders stop complaining about calling with a null value. + * This should never be OVERRIDDEN, modders should only ever implement the sided version. + */ + @Nonnull default OptionalCapabilityInstance getCapability(@Nonnull final Capability cap) { + return getCapability(cap, null); + } } diff --git a/src/main/java/net/minecraftforge/common/capabilities/NonNullSupplier.java b/src/main/java/net/minecraftforge/common/capabilities/NonNullSupplier.java new file mode 100644 index 000000000..f317cdac1 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/capabilities/NonNullSupplier.java @@ -0,0 +1,29 @@ +/* + * 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.common.capabilities; + +import javax.annotation.Nonnull; + +//Exactly like Supplier, except there IS a contract that each invocation should return a new unique instance and it must not be null. +@FunctionalInterface +public interface NonNullSupplier +{ + @Nonnull T get(); +} diff --git a/src/main/java/net/minecraftforge/common/capabilities/OptionalCapabilityInstance.java b/src/main/java/net/minecraftforge/common/capabilities/OptionalCapabilityInstance.java new file mode 100644 index 000000000..082d1933c --- /dev/null +++ b/src/main/java/net/minecraftforge/common/capabilities/OptionalCapabilityInstance.java @@ -0,0 +1,247 @@ +/* + * 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.common.capabilities; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public class OptionalCapabilityInstance +{ + private final NonNullSupplier supplier; + private AtomicReference resolved; + private Set>> listeners = new HashSet<>(); + private boolean isValid = true; + + private static final OptionalCapabilityInstance EMPTY = new OptionalCapabilityInstance<>(null); + + @SuppressWarnings("unchecked") + public static OptionalCapabilityInstance empty() + { + return (OptionalCapabilityInstance)EMPTY; + } + + @SuppressWarnings("unchecked") + public OptionalCapabilityInstance cast() + { + return (OptionalCapabilityInstance)this; + } + + private OptionalCapabilityInstance(NonNullSupplier instanceSupplier) + { + this.supplier = instanceSupplier; + } + + public static OptionalCapabilityInstance of(final NonNullSupplier instanceSupplier) + { + return new OptionalCapabilityInstance<>(instanceSupplier); + } + + private T getValue() + { + if (!isValid) + return null; + if (resolved != null) + return resolved.get(); + + if (supplier != null) + { + resolved = new AtomicReference<>(null); + try + { + T temp = supplier.get(); + if (temp == null) + throw new IllegalStateException("Supplier must not return null value"); + resolved.set(temp); + return resolved.get(); + } + catch (Throwable e) + { + return null; + } + } + return null; + } + + /** + * Return {@code true} if there is a mod object present, otherwise {@code false}. + * + * @return {@code true} if there is a mod object present, otherwise {@code false} + */ + public boolean isPresent() + { + return supplier != null && isValid; + } + + /** + * If a mod object is present, invoke the specified consumer with the object, + * otherwise do nothing. + * + * @param consumer block to be executed if a mod object is present + * @throws NullPointerException if mod object is present and {@code consumer} is + * null + */ + public void ifPresent(Consumer consumer) + { + if (isValid && getValue() != null) + consumer.accept(getValue()); + } + + /** + * If a mod object is present, and the mod object matches the given predicate, + * return an {@code OptionalMod} describing the value, otherwise return an + * empty {@code OptionalMod}. + * + * @param predicate a predicate to apply to the mod object, if present + * @return an {@code OptionalMod} describing the value of this {@code OptionalMod} + * if a mod object is present and the mod object matches the given predicate, + * otherwise an empty {@code OptionalMod} + * @throws NullPointerException if the predicate is null + */ + public OptionalCapabilityInstance filter(Predicate predicate) + { + Objects.requireNonNull(predicate); + final T value = getValue(); // To keep the non-null contract we have to evaluate right now. Should we allow this function at all? + return predicate.test(value) ? OptionalCapabilityInstance.of(()->value) : empty(); + } + + /** + * If a mod object is present, apply the provided mapping function to it, + * and if the result is non-null, return an {@code Optional} describing the + * result. Otherwise return an empty {@code Optional}. + * + * @apiNote This method supports post-processing on optional values, without + * the need to explicitly check for a return status. + * + * @param The type of the result of the mapping function + * @param mapper a mapping function to apply to the mod object, if present + * @return an {@code Optional} describing the result of applying a mapping + * function to the mod object of this {@code OptionalMod}, if a mod object is present, + * otherwise an empty {@code Optional} + * @throws NullPointerException if the mapping function is null + */ + public OptionalCapabilityInstance map(Function mapper) + { + Objects.requireNonNull(mapper); + return isPresent() ? OptionalCapabilityInstance.of(()->mapper.apply(getValue())) : empty(); + } + + /** + * If a value is present, apply the provided {@code Optional}-bearing + * mapping function to it, return that result, otherwise return an empty + * {@code Optional}. This method is similar to {@link #map(Function)}, + * but the provided mapper is one whose result is already an {@code Optional}, + * and if invoked, {@code flatMap} does not wrap it with an additional + * {@code Optional}. + * + * @param The type parameter to the {@code Optional} returned by + * @param mapper a mapping function to apply to the mod object, if present + * the mapping function + * @return the result of applying an {@code Optional}-bearing mapping + * function to the value of this {@code Optional}, if a value is present, + * otherwise an empty {@code Optional} + * @throws NullPointerException if the mapping function is null or returns + * a null result + */ + public OptionalCapabilityInstance flatMap(Function> mapper) + {//I am not sure this is valid, or how to handle this, it's just a copy pasta from Optional. I dont think its needed. Returning a null supplier is bad + Objects.requireNonNull(mapper); + final U value = map(mapper).orElse(Optional.empty()).orElse(null); // To keep the non-null contract we have to evaluate right now. Should we allow this function at all? + return value != null ? OptionalCapabilityInstance.of(() -> value) : OptionalCapabilityInstance.empty(); + } + + /** + * Return the mod object if present, otherwise return {@code other}. + * + * @param other the mod object to be returned if there is no mod object present, may + * be null + * @return the mod object, if present, otherwise {@code other} + */ + public T orElse(T other) + { + return getValue() != null ? getValue() : other; + } + + /** + * Return the mod object if present, otherwise invoke {@code other} and return + * the result of that invocation. + * + * @param other a {@code Supplier} whose result is returned if no mod object + * is present + * @return the mod object if present otherwise the result of {@code other.get()} + * @throws NullPointerException if mod object is not present and {@code other} is + * null + */ + public T orElseGet(Supplier other) + { + return getValue() != null ? getValue() : other.get(); + } + + /** + * Return the contained mod object, if present, otherwise throw an exception + * to be created by the provided supplier. + * + * @apiNote A method reference to the exception constructor with an empty + * argument list can be used as the supplier. For example, + * {@code IllegalStateException::new} + * + * @param Type of the exception to be thrown + * @param exceptionSupplier The supplier which will return the exception to + * be thrown + * @return the present mod object + * @throws X if there is no mod object present + * @throws NullPointerException if no mod object is present and + * {@code exceptionSupplier} is null + */ + public T orElseThrow(Supplier exceptionSupplier) throws X + { + if (getValue() != null) + return getValue(); + throw exceptionSupplier.get(); + } + + /** + * Registers a listener that will be called when this Optional becomes invalid. + */ + public void addListener(Consumer> listener) + { + if (!isPresent()) + listener.accept(this); // They are stupid so just directly call them. + else + this.listeners.add(listener); + } + + /* + * Should only be called by the 'Owner' of this capability, this is to notify any listerners that this has become invalid and they should update. + * For example, a TE would call this, if they are covered with a microblock panel, thus cutting off pipe connectivity to this side. + * Also should be called for all caps when a TE is invalidated, or a world/chunk unloads, or a entity dies, etc... + * This allows modders to keep a cache of Capabilities instead of re-checking them every tick. + */ + public void invalidate() + { + this.isValid = false; + this.listeners.forEach(e -> e.accept(this)); + } +} diff --git a/src/main/java/net/minecraftforge/fluids/UniversalBucket.java b/src/main/java/net/minecraftforge/fluids/UniversalBucket.java index 851aacd20..c5fc35a30 100644 --- a/src/main/java/net/minecraftforge/fluids/UniversalBucket.java +++ b/src/main/java/net/minecraftforge/fluids/UniversalBucket.java @@ -155,7 +155,7 @@ public class UniversalBucket extends Item // empty bucket shouldn't exist, do nothing since it should be handled by the bucket event if (fluidStack == null) { - return ActionResult.newResult(EnumActionResult.PASS, itemstack); + return new ActionResult(EnumActionResult.PASS, itemstack); } // clicked on a block? @@ -166,7 +166,7 @@ public class UniversalBucket extends Item if(mop == null || mop.typeOfHit != RayTraceResult.Type.BLOCK) { - return ActionResult.newResult(EnumActionResult.PASS, itemstack); + return new ActionResult(EnumActionResult.PASS, itemstack); } BlockPos clickPos = mop.getBlockPos(); @@ -184,7 +184,7 @@ public class UniversalBucket extends Item if (result.isSuccess() && !player.capabilities.isCreativeMode) { // success! - player.addStat(StatList.getObjectUseStats(this)); + player.addStat(StatList.OBJECT_USE_STATS.func_199076_b(this)); itemstack.shrink(1); ItemStack drained = result.getResult(); @@ -193,20 +193,20 @@ public class UniversalBucket extends Item // check whether we replace the item or add the empty one to the inventory if (itemstack.isEmpty()) { - return ActionResult.newResult(EnumActionResult.SUCCESS, emptyStack); + return new ActionResult(EnumActionResult.SUCCESS, emptyStack); } else { // add empty bucket to player inventory ItemHandlerHelper.giveItemToPlayer(player, emptyStack); - return ActionResult.newResult(EnumActionResult.SUCCESS, itemstack); + return new ActionResult(EnumActionResult.SUCCESS, itemstack); } } } } // couldn't place liquid there2 - return ActionResult.newResult(EnumActionResult.FAIL, itemstack); + return new ActionResult(EnumActionResult.FAIL, itemstack); } @SubscribeEvent(priority = EventPriority.LOW) // low priority so other mods can handle their stuff first diff --git a/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService b/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService index e8e16bd67..824a7b6c1 100644 --- a/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService +++ b/src/main/resources/META-INF/services/cpw.mods.modlauncher.serviceapi.ILaunchPluginService @@ -1,3 +1,4 @@ net.minecraftforge.fml.loading.RuntimeDistCleaner net.minecraftforge.common.asm.RuntimeEnumExtener net.minecraftforge.common.asm.ObjectHolderDefinalize +net.minecraftforge.common.asm.CapabilityInjectDefinalize