Port capability patches to 1.13 and refactor to new system (#5134)
* resource package and misc leftover rendering stuff * Port Item and ItemStack patches * Extract most item patches to interface * Refactor Item#setNoRepair to be part of Item.Builder * Adapt AnimationItemOverrideList to new cap system * Improve null contract of OptionalCapabilityInstance * Remove Capability.cast * Update CapabilityAnimation to new cap system * Remove OptionalCapabilityInstance#flatMap and add NonNullConsumer * Add capability patch to Entity, not everything yet * Fix Entity patch and add missing methods to IForgeEntity * Fix null contract of CapabilityDispatcher * Add TileEntity caps * Adapt FluidUtil to new cap system * Add world caps * Add chunk caps * Clean up cap patches * Replace all tabs with spaces * Move builder methods on Item to Item.Builder Whitepsace fix * Sided stuff take 2 * Prevent OptionalCapabilityInstance creating additional empty instances * Cache getCapability result in AnimationTESR * Fix imports in TileEntity patch * Pull out cap code to base class, add village caps
This commit is contained in:
parent
f851b37aa0
commit
334d925972
45 changed files with 1967 additions and 266 deletions
|
@ -0,0 +1,10 @@
|
||||||
|
--- a/net/minecraft/client/multiplayer/WorldClient.java
|
||||||
|
+++ b/net/minecraft/client/multiplayer/WorldClient.java
|
||||||
|
@@ -81,6 +81,7 @@
|
||||||
|
this.mapStorage = new SaveDataMemoryStorage();
|
||||||
|
this.calculateInitialSkylight();
|
||||||
|
this.calculateInitialWeather();
|
||||||
|
+ this.initCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
|
@ -46,7 +46,7 @@
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+ public boolean isColorDisabled() {
|
+ public boolean isColorDisabled() {
|
||||||
+ return noColor;
|
+ return noColor;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ public void putBulkData(ByteBuffer buffer) {
|
+ public void putBulkData(ByteBuffer buffer) {
|
||||||
|
|
|
@ -17,6 +17,6 @@
|
||||||
+ * that should be applied to the GL state before rendering it (matrix may be null).
|
+ * that should be applied to the GL state before rendering it (matrix may be null).
|
||||||
+ */
|
+ */
|
||||||
+ default org.apache.commons.lang3.tuple.Pair<? extends IBakedModel, javax.vecmath.Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) {
|
+ default org.apache.commons.lang3.tuple.Pair<? extends IBakedModel, javax.vecmath.Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) {
|
||||||
+ return net.minecraftforge.client.ForgeHooksClient.handlePerspective(this, cameraTransformType);
|
+ return net.minecraftforge.client.ForgeHooksClient.handlePerspective(this, cameraTransformType);
|
||||||
}
|
}
|
||||||
+}
|
+}
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
|
|
||||||
private static BakedQuad func_209567_a(BlockPart p_209567_0_, BlockPartFace p_209567_1_, TextureAtlasSprite p_209567_2_, EnumFacing p_209567_3_, ModelRotation p_209567_4_, boolean p_209567_5_) {
|
private static BakedQuad func_209567_a(BlockPart p_209567_0_, BlockPartFace p_209567_1_, TextureAtlasSprite p_209567_2_, EnumFacing p_209567_3_, ModelRotation p_209567_4_, boolean p_209567_5_) {
|
||||||
- return field_209572_h.func_199332_a(p_209567_0_.positionFrom, p_209567_0_.positionTo, p_209567_1_, p_209567_2_, p_209567_3_, p_209567_4_, p_209567_0_.partRotation, p_209567_5_, p_209567_0_.shade);
|
- return field_209572_h.func_199332_a(p_209567_0_.positionFrom, p_209567_0_.positionTo, p_209567_1_, p_209567_2_, p_209567_3_, p_209567_4_, p_209567_0_.partRotation, p_209567_5_, p_209567_0_.shade);
|
||||||
+ return makeBakedQuad(p_209567_0_, p_209567_1_, p_209567_2_, p_209567_3_, (net.minecraftforge.common.model.IModelState) p_209567_4_, p_209567_5_);
|
+ return makeBakedQuad(p_209567_0_, p_209567_1_, p_209567_2_, p_209567_3_, (net.minecraftforge.common.model.IModelState) p_209567_4_, p_209567_5_);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ public static BakedQuad makeBakedQuad(BlockPart p_209567_0_, BlockPartFace p_209567_1_, TextureAtlasSprite p_209567_2_, EnumFacing p_209567_3_, net.minecraftforge.common.model.IModelState p_209567_4_, boolean p_209567_5_) {
|
+ public static BakedQuad makeBakedQuad(BlockPart p_209567_0_, BlockPartFace p_209567_1_, TextureAtlasSprite p_209567_2_, EnumFacing p_209567_3_, net.minecraftforge.common.model.IModelState p_209567_4_, boolean p_209567_5_) {
|
||||||
|
|
|
@ -8,6 +8,6 @@
|
||||||
+ // Forge Start
|
+ // Forge Start
|
||||||
+
|
+
|
||||||
+ public int getPixelRGBA(int frameIndex, int x, int y) {
|
+ public int getPixelRGBA(int frameIndex, int x, int y) {
|
||||||
+ return this.field_195670_c[frameIndex].func_195709_a(x + this.field_195671_d[frameIndex] * this.width, y + this.field_195672_e[frameIndex] * this.height);
|
+ return this.field_195670_c[frameIndex].func_195709_a(x + this.field_195671_d[frameIndex] * this.width, y + this.field_195672_e[frameIndex] * this.height);
|
||||||
}
|
}
|
||||||
+}
|
+}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
--- a/net/minecraft/client/renderer/vertex/VertexFormatElement.java
|
||||||
|
+++ b/net/minecraft/client/renderer/vertex/VertexFormatElement.java
|
||||||
|
@@ -124,10 +124,17 @@
|
||||||
|
NORMAL("Normal"),
|
||||||
|
COLOR("Vertex Color"),
|
||||||
|
UV("UV"),
|
||||||
|
+ // As of 1.8.8 - unused in vanilla; use GENERIC for now
|
||||||
|
+ @Deprecated
|
||||||
|
MATRIX("Bone Matrix"),
|
||||||
|
+ @Deprecated
|
||||||
|
BLEND_WEIGHT("Blend Weight"),
|
||||||
|
- PADDING("Padding");
|
||||||
|
+ PADDING("Padding"),
|
||||||
|
+ GENERIC("Generic");
|
||||||
|
|
||||||
|
+ public void preDraw(VertexFormat format, int element, int stride, java.nio.ByteBuffer buffer) { net.minecraftforge.client.ForgeHooksClient.preDraw(this, format, element, stride, buffer); }
|
||||||
|
+ public void postDraw(VertexFormat format, int element, int stride, java.nio.ByteBuffer buffer) { net.minecraftforge.client.ForgeHooksClient.postDraw(this, format, element, stride, buffer); }
|
||||||
|
+
|
||||||
|
private final String displayName;
|
||||||
|
|
||||||
|
private EnumUsage(String displayNameIn) {
|
|
@ -0,0 +1,25 @@
|
||||||
|
--- a/net/minecraft/client/resources/Language.java
|
||||||
|
+++ b/net/minecraft/client/resources/Language.java
|
||||||
|
@@ -15,7 +15,13 @@
|
||||||
|
this.region = regionIn;
|
||||||
|
this.name = nameIn;
|
||||||
|
this.bidirectional = bidirectionalIn;
|
||||||
|
+ String[] splitLangCode = name.split("_", 2);
|
||||||
|
+ if (splitLangCode.length == 1) { // Vanilla has some languages without underscores
|
||||||
|
+ this.javaLocale = new java.util.Locale(languageCode);
|
||||||
|
+ } else {
|
||||||
|
+ this.javaLocale = new java.util.Locale(splitLangCode[0], splitLangCode[1]);
|
||||||
|
}
|
||||||
|
+ }
|
||||||
|
|
||||||
|
public String getLanguageCode() {
|
||||||
|
return this.languageCode;
|
||||||
|
@@ -44,4 +50,8 @@
|
||||||
|
public int compareTo(Language p_compareTo_1_) {
|
||||||
|
return this.languageCode.compareTo(p_compareTo_1_.languageCode);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // Forge: add access to Locale so modders can create correct string and number formatters
|
||||||
|
+ private final java.util.Locale javaLocale;
|
||||||
|
+ public java.util.Locale getJavaLocale() { return javaLocale; }
|
||||||
|
}
|
28
patches/minecraft/net/minecraft/entity/Entity.java.patch
Normal file
28
patches/minecraft/net/minecraft/entity/Entity.java.patch
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
--- a/net/minecraft/entity/Entity.java
|
||||||
|
+++ b/net/minecraft/entity/Entity.java
|
||||||
|
@@ -12,6 +12,7 @@
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
+
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import net.minecraft.advancements.CriteriaTriggers;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
@@ -97,7 +98,7 @@
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
-public abstract class Entity implements INameable, ICommandSource {
|
||||||
|
+public abstract class Entity extends net.minecraftforge.common.capabilities.CapabilityProvider implements INameable, ICommandSource, net.minecraftforge.common.extensions.IForgeEntity {
|
||||||
|
protected static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
private static final List<ItemStack> EMPTY_EQUIPMENT = Collections.<ItemStack>emptyList();
|
||||||
|
private static final AxisAlignedBB ZERO_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
|
||||||
|
@@ -221,6 +222,8 @@
|
||||||
|
this.dataManager.register(SILENT, false);
|
||||||
|
this.dataManager.register(NO_GRAVITY, false);
|
||||||
|
this.entityInit();
|
||||||
|
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityEvent.EntityConstructing(this));
|
||||||
|
+ this.gatherCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityType<?> func_200600_R() {
|
|
@ -1,11 +1,163 @@
|
||||||
--- a/net/minecraft/item/Item.java
|
--- a/net/minecraft/item/Item.java
|
||||||
+++ b/net/minecraft/item/Item.java
|
+++ b/net/minecraft/item/Item.java
|
||||||
@@ -50,7 +50,7 @@
|
@@ -50,9 +50,9 @@
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
-public class Item implements IItemProvider {
|
-public class Item implements IItemProvider {
|
||||||
+public class Item extends net.minecraftforge.registries.ForgeRegistryEntry<Item> implements IItemProvider {
|
- public static final RegistryNamespaced<ResourceLocation, Item> REGISTRY = new RegistryNamespaced<ResourceLocation, Item>();
|
||||||
public static final RegistryNamespaced<ResourceLocation, Item> REGISTRY = new RegistryNamespaced<ResourceLocation, Item>();
|
- public static final Map<Block, Item> BLOCK_TO_ITEM = Maps.<Block, Item>newHashMap();
|
||||||
public static final Map<Block, Item> BLOCK_TO_ITEM = Maps.<Block, Item>newHashMap();
|
+public class Item extends net.minecraftforge.registries.ForgeRegistryEntry<Item> implements IItemProvider, net.minecraftforge.common.extensions.IForgeItem {
|
||||||
|
+ public static final RegistryNamespaced<ResourceLocation, Item> REGISTRY = net.minecraftforge.registries.GameData.getWrapper(Item.class);
|
||||||
|
+ public static final Map<Block, Item> BLOCK_TO_ITEM = net.minecraftforge.registries.GameData.getBlockItemMap();
|
||||||
private static final IItemPropertyGetter DAMAGED_GETTER = (p_210306_0_, p_210306_1_, p_210306_2_) -> {
|
private static final IItemPropertyGetter DAMAGED_GETTER = (p_210306_0_, p_210306_1_, p_210306_2_) -> {
|
||||||
|
return p_210306_0_.isItemDamaged() ? 1.0F : 0.0F;
|
||||||
|
};
|
||||||
|
@@ -126,6 +126,10 @@
|
||||||
|
this.containerItem = p_i48487_1_.field_200922_c;
|
||||||
|
this.maxDamage = p_i48487_1_.field_200921_b;
|
||||||
|
this.maxStackSize = p_i48487_1_.field_200920_a;
|
||||||
|
+ this.canRepair = p_i48487_1_.canRepair;
|
||||||
|
+ this.toolClasses.putAll(p_i48487_1_.toolClasses);
|
||||||
|
+ Object tmp = net.minecraftforge.fml.DistExecutor.callWhenOn(Dist.CLIENT, p_i48487_1_.teisr);
|
||||||
|
+ this.teisr = tmp == null ? null : () -> (net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer) tmp;
|
||||||
|
if (this.maxDamage > 0) {
|
||||||
|
this.addPropertyOverride(new ResourceLocation("damaged"), DAMAGED_GETTER);
|
||||||
|
this.addPropertyOverride(new ResourceLocation("damage"), DAMAGE_GETTER);
|
||||||
|
@@ -149,10 +153,12 @@
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @Deprecated // Use ItemStack sensitive version.
|
||||||
|
public final int getItemStackLimit() {
|
||||||
|
return this.maxStackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @Deprecated // Use ItemStack sensitive version.
|
||||||
|
public final int getMaxDamage() {
|
||||||
|
return this.maxDamage;
|
||||||
|
}
|
||||||
|
@@ -207,6 +213,7 @@
|
||||||
|
return this.containerItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @Deprecated // Use ItemStack sensitive version.
|
||||||
|
public boolean hasContainerItem() {
|
||||||
|
return this.containerItem != null;
|
||||||
|
}
|
||||||
|
@@ -263,7 +270,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnchantable(ItemStack stack) {
|
||||||
|
- return this.getItemStackLimit() == 1 && this.isDamageable();
|
||||||
|
+ return this.getItemStackLimit(stack) == 1 && this.isDamageable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@@ -280,8 +287,8 @@
|
||||||
|
float f5 = MathHelper.sin(-f * ((float)Math.PI / 180F));
|
||||||
|
float f6 = f3 * f4;
|
||||||
|
float f7 = f2 * f4;
|
||||||
|
- double d3 = 5.0D;
|
||||||
|
- Vec3d vec3d1 = vec3d.add((double)f6 * 5.0D, (double)f5 * 5.0D, (double)f7 * 5.0D);
|
||||||
|
+ double d3 = playerIn.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue();
|
||||||
|
+ Vec3d vec3d1 = vec3d.add((double)f6 * d3, (double)f5 * d3, (double)f7 * d3);
|
||||||
|
return worldIn.func_200259_a(vec3d, vec3d1, useLiquids ? RayTraceFluidMode.SOURCE_ONLY : RayTraceFluidMode.NEVER, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -297,6 +304,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isInCreativeTab(ItemGroup targetTab) {
|
||||||
|
+ if (getCreativeTabs().stream().anyMatch(tab -> tab == targetTab)) return true;
|
||||||
|
ItemGroup itemgroup = this.getCreativeTab();
|
||||||
|
return itemgroup != null && (targetTab == ItemGroup.SEARCH || targetTab == itemgroup);
|
||||||
|
}
|
||||||
|
@@ -310,10 +318,49 @@
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ @Deprecated // Use ItemStack sensitive version.
|
||||||
|
public Multimap<String, AttributeModifier> getItemAttributeModifiers(EntityEquipmentSlot equipmentSlot) {
|
||||||
|
return HashMultimap.<String, AttributeModifier>create();
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* ======================================== FORGE START =====================================*/
|
||||||
|
+
|
||||||
|
+ @Nullable
|
||||||
|
+ private final java.util.function.Supplier<net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer> teisr;
|
||||||
|
+
|
||||||
|
+ private final java.util.Map<String, Integer> toolClasses = new java.util.HashMap<String, Integer>();
|
||||||
|
+
|
||||||
|
+ protected final boolean canRepair;
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public boolean isRepairable()
|
||||||
|
+ {
|
||||||
|
+ return canRepair && isDamageable();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public java.util.Set<String> getToolClasses(ItemStack stack)
|
||||||
|
+ {
|
||||||
|
+ return toolClasses.keySet();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public int getHarvestLevel(ItemStack stack, String toolClass, @Nullable EntityPlayer player, @Nullable IBlockState blockState)
|
||||||
|
+ {
|
||||||
|
+ Integer ret = toolClasses.get(toolClass);
|
||||||
|
+ return ret == null ? -1 : ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @OnlyIn(Dist.CLIENT)
|
||||||
|
+ @Override
|
||||||
|
+ public final net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer getTileEntityItemStackRenderer()
|
||||||
|
+ {
|
||||||
|
+ net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer renderer = teisr != null ? teisr.get() : null;
|
||||||
|
+ return renderer != null ? renderer : net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer.instance;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* ======================================== FORGE END =====================================*/
|
||||||
|
+
|
||||||
|
public static void registerItems() {
|
||||||
|
registerItemBlock(Blocks.AIR, new ItemAir(Blocks.AIR, new Item.Builder()));
|
||||||
|
func_200879_a(Blocks.STONE, ItemGroup.BUILDING_BLOCKS);
|
||||||
|
@@ -1147,6 +1194,9 @@
|
||||||
|
private Item field_200922_c;
|
||||||
|
private ItemGroup field_200923_d;
|
||||||
|
private EnumRarity field_208104_e = EnumRarity.COMMON;
|
||||||
|
+ private boolean canRepair = true;
|
||||||
|
+ private java.util.Map<String, Integer> toolClasses = new java.util.HashMap<String, Integer>();
|
||||||
|
+ private java.util.function.Supplier<java.util.concurrent.Callable<net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer>> teisr;
|
||||||
|
|
||||||
|
public Item.Builder func_200917_a(int p_200917_1_) {
|
||||||
|
if (this.field_200921_b > 0) {
|
||||||
|
@@ -1181,5 +1231,27 @@
|
||||||
|
this.field_208104_e = p_208103_1_;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public Item.Builder setNoRepair() {
|
||||||
|
+ canRepair = false;
|
||||||
|
+ return this;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Sets or removes the harvest level for the specified tool class.
|
||||||
|
+ *
|
||||||
|
+ * @param toolClass Class
|
||||||
|
+ * @param level Harvest level: Wood: 0 Stone: 1 Iron: 2 Diamond: 3 Gold: 0
|
||||||
|
+ */
|
||||||
|
+ public void setHarvestLevel(String toolClass, int level) {
|
||||||
|
+ if (level < 0)
|
||||||
|
+ toolClasses.remove(toolClass);
|
||||||
|
+ else
|
||||||
|
+ toolClasses.put(toolClass, level);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public void setTileEntityItemStackRenderer(java.util.function.Supplier<java.util.concurrent.Callable<net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer>> teisrSupplier) {
|
||||||
|
+ this.teisr = teisrSupplier;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
|
302
patches/minecraft/net/minecraft/item/ItemStack.java.patch
Normal file
302
patches/minecraft/net/minecraft/item/ItemStack.java.patch
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
--- a/net/minecraft/item/ItemStack.java
|
||||||
|
+++ b/net/minecraft/item/ItemStack.java
|
||||||
|
@@ -63,7 +63,7 @@
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
-public final class ItemStack {
|
||||||
|
+public final class ItemStack extends net.minecraftforge.common.capabilities.CapabilityProvider implements net.minecraftforge.common.capabilities.ICapabilitySerializable<NBTTagCompound> {
|
||||||
|
private static final Logger field_199558_c = LogManager.getLogger();
|
||||||
|
public static final ItemStack EMPTY = new ItemStack((Item)null);
|
||||||
|
public static final DecimalFormat DECIMALFORMAT = func_208306_D();
|
||||||
|
@@ -79,6 +79,9 @@
|
||||||
|
private BlockWorldState canPlaceOnCacheBlock;
|
||||||
|
private boolean canPlaceOnCacheResult;
|
||||||
|
|
||||||
|
+ private net.minecraftforge.registries.IRegistryDelegate<Item> delegate;
|
||||||
|
+ private NBTTagCompound capNBT;
|
||||||
|
+
|
||||||
|
private static DecimalFormat func_208306_D() {
|
||||||
|
DecimalFormat decimalformat = new DecimalFormat("#.##");
|
||||||
|
decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT));
|
||||||
|
@@ -89,10 +92,13 @@
|
||||||
|
this(p_i48203_1_, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- public ItemStack(IItemProvider p_i48204_1_, int p_i48204_2_) {
|
||||||
|
+ public ItemStack(IItemProvider p_i48204_1_, int p_i48204_2_){ this(p_i48204_1_, p_i48204_2_, null); }
|
||||||
|
+ public ItemStack(IItemProvider p_i48204_1_, int p_i48204_2_, @Nullable NBTTagCompound capNBT) {
|
||||||
|
+ this.capNBT = capNBT;
|
||||||
|
this.item = p_i48204_1_ == null ? null : p_i48204_1_.func_199767_j();
|
||||||
|
this.stackSize = p_i48204_2_;
|
||||||
|
this.updateEmptyState();
|
||||||
|
+ this.forgeInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateEmptyState() {
|
||||||
|
@@ -101,6 +107,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack(NBTTagCompound compound) {
|
||||||
|
+ this.capNBT = compound.hasKey("ForgeCaps") ? compound.getCompoundTag("ForgeCaps") : null;
|
||||||
|
Item item = Item.REGISTRY.getObject(new ResourceLocation(compound.getString("id")));
|
||||||
|
this.item = item == null ? Items.AIR : item;
|
||||||
|
this.stackSize = compound.getByte("Count");
|
||||||
|
@@ -114,6 +121,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateEmptyState();
|
||||||
|
+ this.forgeInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemStack func_199557_a(NBTTagCompound p_199557_0_) {
|
||||||
|
@@ -128,7 +136,7 @@
|
||||||
|
public boolean isEmpty() {
|
||||||
|
if (this == EMPTY) {
|
||||||
|
return true;
|
||||||
|
- } else if (this.getItem() != null && this.getItem() != Items.AIR) {
|
||||||
|
+ } else if (this.getItemRaw() != null && this.getItemRaw() != Items.AIR) {
|
||||||
|
return this.stackSize <= 0;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
@@ -144,10 +152,11 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item getItem() {
|
||||||
|
- return this.isEmpty ? Items.AIR : this.item;
|
||||||
|
+ return this.isEmpty || this.delegate == null ? Items.AIR : this.delegate.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnumActionResult func_196084_a(ItemUseContext p_196084_1_) {
|
||||||
|
+ if (!p_196084_1_.field_196006_g.isRemote) return net.minecraftforge.common.ForgeHooks.onPlaceItemIntoWorld(p_196084_1_);
|
||||||
|
EntityPlayer entityplayer = p_196084_1_.func_195999_j();
|
||||||
|
BlockPos blockpos = p_196084_1_.func_195995_a();
|
||||||
|
BlockWorldState blockworldstate = new BlockWorldState(p_196084_1_.func_195991_k(), blockpos, false);
|
||||||
|
@@ -164,6 +173,23 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ public EnumActionResult onItemUseFirst(ItemUseContext p_196084_1_) {
|
||||||
|
+ EntityPlayer entityplayer = p_196084_1_.func_195999_j();
|
||||||
|
+ BlockPos blockpos = p_196084_1_.func_195995_a();
|
||||||
|
+ BlockWorldState blockworldstate = new BlockWorldState(p_196084_1_.func_195991_k(), blockpos, false);
|
||||||
|
+ if (entityplayer != null && !entityplayer.capabilities.allowEdit && !this.func_206847_b(p_196084_1_.func_195991_k().func_205772_D(), blockworldstate)) {
|
||||||
|
+ return EnumActionResult.PASS;
|
||||||
|
+ } else {
|
||||||
|
+ Item item = this.getItem();
|
||||||
|
+ EnumActionResult enumactionresult = item.onItemUseFirst(p_196084_1_);
|
||||||
|
+ if (entityplayer != null && enumactionresult == EnumActionResult.SUCCESS) {
|
||||||
|
+ entityplayer.addStat(StatList.OBJECT_USE_STATS.func_199076_b(item));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return enumactionresult;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
public float getDestroySpeed(IBlockState blockIn) {
|
||||||
|
return this.getItem().getDestroySpeed(this, blockIn);
|
||||||
|
}
|
||||||
|
@@ -183,12 +209,15 @@
|
||||||
|
if (this.stackTagCompound != null) {
|
||||||
|
nbt.setTag("tag", this.stackTagCompound);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ NBTTagCompound cnbt = this.serializeCaps();
|
||||||
|
+ if (cnbt != null && !cnbt.isEmpty()) {
|
||||||
|
+ nbt.setTag("ForgeCaps", cnbt);
|
||||||
|
+ }
|
||||||
|
return nbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxStackSize() {
|
||||||
|
- return this.getItem().getItemStackLimit();
|
||||||
|
+ return this.getItem().getItemStackLimit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStackable() {
|
||||||
|
@@ -196,7 +225,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isItemStackDamageable() {
|
||||||
|
- if (!this.isEmpty && this.getItem().getMaxDamage() > 0) {
|
||||||
|
+ if (!this.isEmpty && this.getItem().getMaxDamage(this) > 0) {
|
||||||
|
NBTTagCompound nbttagcompound = this.getTagCompound();
|
||||||
|
return nbttagcompound == null || !nbttagcompound.getBoolean("Unbreakable");
|
||||||
|
} else {
|
||||||
|
@@ -205,19 +234,19 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isItemDamaged() {
|
||||||
|
- return this.isItemStackDamageable() && this.getItemDamage() > 0;
|
||||||
|
+ return this.isItemStackDamageable() && getItem().isDamaged(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
- public int getItemDamage() {
|
||||||
|
- return this.stackTagCompound == null ? 0 : this.stackTagCompound.getInteger("Damage");
|
||||||
|
+ public int getItemDamage() { // TODO evaluate the necessity of this patch
|
||||||
|
+ return this.getItem().getDamage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void func_196085_b(int p_196085_1_) {
|
||||||
|
- this.func_196082_o().setInteger("Damage", Math.max(0, p_196085_1_));
|
||||||
|
+ getItem().setDamage(this, p_196085_1_);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxDamage() {
|
||||||
|
- return this.getItem().getMaxDamage();
|
||||||
|
+ return this.getItem().getMaxDamage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean attemptDamageItem(int amount, Random rand, @Nullable EntityPlayerMP damager) {
|
||||||
|
@@ -285,7 +314,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canHarvestBlock(IBlockState blockIn) {
|
||||||
|
- return this.getItem().canHarvestBlock(blockIn);
|
||||||
|
+ return this.getItem().canHarvestBlock(blockIn, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean interactWithEntity(EntityPlayer playerIn, EntityLivingBase entityIn, EnumHand hand) {
|
||||||
|
@@ -293,7 +322,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack copy() {
|
||||||
|
- ItemStack itemstack = new ItemStack(this.getItem(), this.stackSize);
|
||||||
|
+ ItemStack itemstack = new ItemStack(this.getItem(), this.stackSize, this.serializeCaps());
|
||||||
|
itemstack.setAnimationsToGo(this.getAnimationsToGo());
|
||||||
|
if (this.stackTagCompound != null) {
|
||||||
|
itemstack.stackTagCompound = this.stackTagCompound.copy();
|
||||||
|
@@ -309,7 +338,7 @@
|
||||||
|
if (stackA.stackTagCompound == null && stackB.stackTagCompound != null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
- return stackA.stackTagCompound == null || stackA.stackTagCompound.equals(stackB.stackTagCompound);
|
||||||
|
+ return stackA.stackTagCompound == null || stackA.stackTagCompound.equals(stackB.stackTagCompound) && stackA.areCapsCompatible(stackB);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
@@ -332,7 +361,7 @@
|
||||||
|
} else if (this.stackTagCompound == null && other.stackTagCompound != null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
- return this.stackTagCompound == null || this.stackTagCompound.equals(other.stackTagCompound);
|
||||||
|
+ return this.stackTagCompound == null || this.stackTagCompound.equals(other.stackTagCompound) && this.areCapsCompatible(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -633,6 +662,7 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ net.minecraftforge.event.ForgeEventFactory.onItemTooltip(this, playerIn, list, advanced);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -743,7 +773,7 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
- multimap = this.getItem().getItemAttributeModifiers(equipmentSlot);
|
||||||
|
+ multimap = this.getItem().getAttributeModifiers(equipmentSlot, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return multimap;
|
||||||
|
@@ -874,4 +904,98 @@
|
||||||
|
public void shrink(int quantity) {
|
||||||
|
this.grow(-quantity);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // FORGE START
|
||||||
|
+
|
||||||
|
+ public void deserializeNBT(NBTTagCompound nbt)
|
||||||
|
+ {
|
||||||
|
+ // TODO do this better while respecting new rules
|
||||||
|
+ final ItemStack itemStack = new ItemStack(nbt);
|
||||||
|
+ this.stackTagCompound = itemStack.stackTagCompound;
|
||||||
|
+ this.capNBT = itemStack.capNBT;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ public NBTTagCompound serializeNBT()
|
||||||
|
+ {
|
||||||
|
+ NBTTagCompound ret = new NBTTagCompound();
|
||||||
|
+ this.writeToNBT(ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Set up forge's ItemStack additions.
|
||||||
|
+ */
|
||||||
|
+ private void forgeInit()
|
||||||
|
+ {
|
||||||
|
+ Item item = getItemRaw();
|
||||||
|
+ if (item != null)
|
||||||
|
+ {
|
||||||
|
+ this.delegate = item.delegate;
|
||||||
|
+ net.minecraftforge.common.capabilities.ICapabilityProvider provider = item.initCapabilities(this, this.capNBT);
|
||||||
|
+ this.gatherCapabilities(provider);
|
||||||
|
+ if (this.capNBT != null) deserializeCaps(this.capNBT);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Internal call to get the actual item, not the delegate.
|
||||||
|
+ * In all other methods, FML replaces calls to this.item with the item delegate.
|
||||||
|
+ */
|
||||||
|
+ @Nullable
|
||||||
|
+ private Item getItemRaw()
|
||||||
|
+ {
|
||||||
|
+ return this.item;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Modeled after ItemStack.areItemStacksEqual
|
||||||
|
+ * Uses Item.getNBTShareTag for comparison instead of NBT and capabilities.
|
||||||
|
+ * Only used for comparing itemStacks that were transferred from server to client using Item.getNBTShareTag.
|
||||||
|
+ */
|
||||||
|
+ public static boolean areItemStacksEqualUsingNBTShareTag(ItemStack stackA, ItemStack stackB)
|
||||||
|
+ {
|
||||||
|
+ if (stackA.isEmpty())
|
||||||
|
+ return stackB.isEmpty();
|
||||||
|
+ else
|
||||||
|
+ return !stackB.isEmpty() && stackA.isItemStackEqualUsingNBTShareTag(stackB);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Modeled after ItemStack.isItemStackEqual
|
||||||
|
+ * Uses Item.getNBTShareTag for comparison instead of NBT and capabilities.
|
||||||
|
+ * Only used for comparing itemStacks that were transferred from server to client using Item.getNBTShareTag.
|
||||||
|
+ */
|
||||||
|
+ private boolean isItemStackEqualUsingNBTShareTag(ItemStack other)
|
||||||
|
+ {
|
||||||
|
+ return this.stackSize == other.stackSize && this.getItem() == other.getItem() && areItemStackShareTagsEqual(this, other);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Modeled after ItemStack.areItemStackTagsEqual
|
||||||
|
+ * Uses Item.getNBTShareTag for comparison instead of NBT and capabilities.
|
||||||
|
+ * Only used for comparing itemStacks that were transferred from server to client using Item.getNBTShareTag.
|
||||||
|
+ */
|
||||||
|
+ public static boolean areItemStackShareTagsEqual(ItemStack stackA, ItemStack stackB)
|
||||||
|
+ {
|
||||||
|
+ NBTTagCompound shareTagA = stackA.getItem().getNBTShareTag(stackA);
|
||||||
|
+ NBTTagCompound shareTagB = stackB.getItem().getNBTShareTag(stackB);
|
||||||
|
+ if (shareTagA == null)
|
||||||
|
+ return shareTagB == null;
|
||||||
|
+ else
|
||||||
|
+ return shareTagB != null && shareTagA.equals(shareTagB);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ *
|
||||||
|
+ * Should this item, when held, allow sneak-clicks to pass through to the underlying block?
|
||||||
|
+ *
|
||||||
|
+ * @param world The world
|
||||||
|
+ * @param pos Block position in world
|
||||||
|
+ * @param player The Player that is wielding the item
|
||||||
|
+ * @return
|
||||||
|
+ */
|
||||||
|
+ public boolean doesSneakBypassUse(net.minecraft.world.IWorldReader world, BlockPos pos, EntityPlayer player)
|
||||||
|
+ {
|
||||||
|
+ return this.isEmpty() || this.getItem().doesSneakBypassUse(this, world, pos, player);
|
||||||
|
+ }
|
||||||
|
+}
|
|
@ -0,0 +1,23 @@
|
||||||
|
--- a/net/minecraft/tileentity/TileEntity.java
|
||||||
|
+++ b/net/minecraft/tileentity/TileEntity.java
|
||||||
|
@@ -12,10 +12,11 @@
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
+
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
-public abstract class TileEntity {
|
||||||
|
+public abstract class TileEntity extends net.minecraftforge.common.capabilities.CapabilityProvider implements net.minecraftforge.common.extensions.IForgeTileEntity {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
private final TileEntityType<?> field_200663_e;
|
||||||
|
protected World world;
|
||||||
|
@@ -26,6 +27,7 @@
|
||||||
|
|
||||||
|
public TileEntity(TileEntityType<?> p_i48289_1_) {
|
||||||
|
this.field_200663_e = p_i48289_1_;
|
||||||
|
+ this.gatherCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
42
patches/minecraft/net/minecraft/village/Village.java.patch
Normal file
42
patches/minecraft/net/minecraft/village/Village.java.patch
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
--- a/net/minecraft/village/Village.java
|
||||||
|
+++ b/net/minecraft/village/Village.java
|
||||||
|
@@ -30,7 +30,7 @@
|
||||||
|
import net.minecraft.util.text.ITextComponent;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
-public class Village {
|
||||||
|
+public class Village extends net.minecraftforge.common.capabilities.CapabilityProvider implements net.minecraftforge.common.extensions.IForgeVillage {
|
||||||
|
private World world;
|
||||||
|
private final List<VillageDoorInfo> villageDoorInfoList = Lists.<VillageDoorInfo>newArrayList();
|
||||||
|
private BlockPos centerHelper = BlockPos.ORIGIN;
|
||||||
|
@@ -45,10 +45,12 @@
|
||||||
|
private int numIronGolems;
|
||||||
|
|
||||||
|
public Village() {
|
||||||
|
+ this.gatherCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Village(World worldIn) {
|
||||||
|
this.world = worldIn;
|
||||||
|
+ this.gatherCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorld(World worldIn) {
|
||||||
|
@@ -364,7 +366,7 @@
|
||||||
|
this.playerReputation.put(nbttagcompound1.getString("Name"), nbttagcompound1.getInteger("S"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ if (compound.hasKey("ForgeCaps")) this.deserializeCaps(compound.getCompoundTag("ForgeCaps"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeVillageDataToNBT(NBTTagCompound compound) {
|
||||||
|
@@ -413,6 +415,8 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
compound.setTag("Players", nbttaglist1);
|
||||||
|
+ NBTTagCompound capTag = this.serializeCaps();
|
||||||
|
+ if (capTag != null) compound.setTag("ForgeCaps", capTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endMatingSeason() {
|
55
patches/minecraft/net/minecraft/world/World.java.patch
Normal file
55
patches/minecraft/net/minecraft/world/World.java.patch
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
--- a/net/minecraft/world/World.java
|
||||||
|
+++ b/net/minecraft/world/World.java
|
||||||
|
@@ -68,10 +68,11 @@
|
||||||
|
import net.minecraft.world.storage.WorldSavedDataStorage;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
+
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
-public abstract class World implements IWorld, IWorldReader, AutoCloseable {
|
||||||
|
+public abstract class World extends net.minecraftforge.common.capabilities.CapabilityProvider implements IWorld, IWorldReader, AutoCloseable, net.minecraftforge.common.extensions.IForgeWorld {
|
||||||
|
protected static final Logger field_195596_d = LogManager.getLogger();
|
||||||
|
private static final EnumFacing[] field_200007_a = EnumFacing.values();
|
||||||
|
private int seaLevel = 63;
|
||||||
|
@@ -121,6 +122,7 @@
|
||||||
|
this.provider = providerIn;
|
||||||
|
this.isRemote = client;
|
||||||
|
this.worldBorder = providerIn.createWorldBorder();
|
||||||
|
+ perWorldStorage = new WorldSavedDataStorage((ISaveHandler)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWorld init() {
|
||||||
|
@@ -2397,4 +2399,31 @@
|
||||||
|
public abstract RecipeManager func_199532_z();
|
||||||
|
|
||||||
|
public abstract NetworkTagManager func_205772_D();
|
||||||
|
+
|
||||||
|
+ /* ======================================== FORGE START =====================================*/
|
||||||
|
+
|
||||||
|
+ private net.minecraftforge.common.util.WorldCapabilityData capabilityData;
|
||||||
|
+
|
||||||
|
+ protected void initCapabilities()
|
||||||
|
+ {
|
||||||
|
+ net.minecraftforge.common.capabilities.ICapabilityProvider parent = provider.initCapabilities();
|
||||||
|
+ this.gatherCapabilities(parent);
|
||||||
|
+ net.minecraftforge.common.util.WorldCapabilityData data = (net.minecraftforge.common.util.WorldCapabilityData)perWorldStorage.func_201067_a(net.minecraftforge.common.util.WorldCapabilityData::new, net.minecraftforge.common.util.WorldCapabilityData.ID);
|
||||||
|
+ if (data == null)
|
||||||
|
+ {
|
||||||
|
+ capabilityData = new net.minecraftforge.common.util.WorldCapabilityData(getCapabilities());
|
||||||
|
+ perWorldStorage.setData(capabilityData.func_195925_e(), capabilityData);
|
||||||
|
}
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ capabilityData = data;
|
||||||
|
+ capabilityData.setCapabilities(provider, getCapabilities());
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ protected WorldSavedDataStorage perWorldStorage; //Moved to a getter to simulate final without being final so we can load in subclasses.
|
||||||
|
+ public WorldSavedDataStorage getPerWorldStorage()
|
||||||
|
+ {
|
||||||
|
+ return perWorldStorage;
|
||||||
|
+ }
|
||||||
|
+}
|
10
patches/minecraft/net/minecraft/world/WorldServer.java.patch
Normal file
10
patches/minecraft/net/minecraft/world/WorldServer.java.patch
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--- a/net/minecraft/world/WorldServer.java
|
||||||
|
+++ b/net/minecraft/world/WorldServer.java
|
||||||
|
@@ -150,6 +150,7 @@
|
||||||
|
this.getWorldBorder().setTransition(this.worldInfo.getBorderSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
+ this.initCapabilities();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
--- a/net/minecraft/world/WorldServerMulti.java
|
||||||
|
+++ b/net/minecraft/world/WorldServerMulti.java
|
||||||
|
@@ -60,6 +60,7 @@
|
||||||
|
this.villageCollection.setWorldsForAll(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ this.initCapabilities();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
19
patches/minecraft/net/minecraft/world/chunk/Chunk.java.patch
Normal file
19
patches/minecraft/net/minecraft/world/chunk/Chunk.java.patch
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
--- a/net/minecraft/world/chunk/Chunk.java
|
||||||
|
+++ b/net/minecraft/world/chunk/Chunk.java
|
||||||
|
@@ -53,7 +53,7 @@
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
-public class Chunk implements IChunk {
|
||||||
|
+public class Chunk extends net.minecraftforge.common.capabilities.CapabilityProvider implements IChunk, net.minecraftforge.common.extensions.IForgeChunk {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
public static final ChunkSection NULL_BLOCK_STORAGE = null;
|
||||||
|
private final ChunkSection[] storageArrays;
|
||||||
|
@@ -125,6 +125,7 @@
|
||||||
|
this.field_201621_s = p_i49379_6_;
|
||||||
|
this.field_205325_u = p_i49379_7_;
|
||||||
|
this.inhabitedTime = p_i49379_8_;
|
||||||
|
+ this.gatherCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk(World p_i48703_1_, ChunkPrimer p_i48703_2_, int p_i48703_3_, int p_i48703_4_) {
|
|
@ -0,0 +1,33 @@
|
||||||
|
--- a/net/minecraft/world/chunk/storage/AnvilChunkLoader.java
|
||||||
|
+++ b/net/minecraft/world/chunk/storage/AnvilChunkLoader.java
|
||||||
|
@@ -445,7 +445,19 @@
|
||||||
|
|
||||||
|
compound.setTag("Heightmaps", nbttagcompound2);
|
||||||
|
compound.setTag("Structures", this.func_202160_a(chunkIn.x, chunkIn.z, chunkIn.func_201609_c(), chunkIn.func_201604_d()));
|
||||||
|
+
|
||||||
|
+ if (chunkIn.getCapabilities() != null)
|
||||||
|
+ {
|
||||||
|
+ try
|
||||||
|
+ {
|
||||||
|
+ compound.setTag("ForgeCaps", chunkIn.getCapabilities().serializeNBT());
|
||||||
|
}
|
||||||
|
+ catch (Exception exception)
|
||||||
|
+ {
|
||||||
|
+ org.apache.logging.log4j.LogManager.getLogger().error("A capability provider has thrown an exception trying to write state. It will not persist. Report this to the mod author", exception);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
private Chunk readChunkFromNBT(IWorld worldIn, NBTTagCompound compound) {
|
||||||
|
int i = compound.getInteger("xPos");
|
||||||
|
@@ -511,6 +523,10 @@
|
||||||
|
chunk.setModified(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (chunk.getCapabilities() != null && compound.hasKey("ForgeCaps")) {
|
||||||
|
+ chunk.getCapabilities().deserializeNBT(compound.getCompoundTag("ForgeCaps"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
--- a/net/minecraft/world/dimension/Dimension.java
|
||||||
|
+++ b/net/minecraft/world/dimension/Dimension.java
|
||||||
|
@@ -13,7 +13,7 @@
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
-public abstract class Dimension {
|
||||||
|
+public abstract class Dimension implements net.minecraftforge.common.extensions.IForgeDimension {
|
||||||
|
public static final float[] MOON_PHASE_FACTORS = new float[]{1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F};
|
||||||
|
protected World world;
|
||||||
|
protected boolean doesWaterVaporize;
|
|
@ -41,6 +41,7 @@ import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.resources.IReloadableResourceManager;
|
import net.minecraft.resources.IReloadableResourceManager;
|
||||||
|
import net.minecraft.resources.IResourceManager;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
|
@ -35,7 +35,8 @@ public class ForgeClientHandler
|
||||||
// register model for the universal bucket, if it exists
|
// register model for the universal bucket, if it exists
|
||||||
if (FluidRegistry.isUniversalBucketEnabled())
|
if (FluidRegistry.isUniversalBucketEnabled())
|
||||||
{
|
{
|
||||||
ModelLoader.setBucketModelDefinition(ForgeMod.getInstance().universalBucket);
|
// TODO no more mesh definitions, this should be implemented with overrides
|
||||||
|
// ModelLoader.setBucketModelDefinition(ForgeMod.getInstance().universalBucket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public class ForgeClientHandler
|
||||||
{
|
{
|
||||||
if (FluidRegistry.isUniversalBucketEnabled())
|
if (FluidRegistry.isUniversalBucketEnabled())
|
||||||
{
|
{
|
||||||
event.getItemColors().registerItemColorHandler(new FluidContainerColorer(), ForgeMod.getInstance().universalBucket);
|
event.getItemColors().func_199877_a(new FluidContainerColorer(), ForgeMod.getInstance().universalBucket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,22 +67,23 @@ public final class AnimationItemOverrideList extends ItemOverrideList
|
||||||
@Override
|
@Override
|
||||||
public IBakedModel func_209581_a(IBakedModel originalModel, ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity)
|
public IBakedModel func_209581_a(IBakedModel originalModel, ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity)
|
||||||
{
|
{
|
||||||
IAnimationStateMachine asm = stack.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null);
|
return stack.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null)
|
||||||
if (asm != null)
|
.map(asm ->
|
||||||
{
|
|
||||||
// TODO: caching?
|
|
||||||
if(world == null && entity != null)
|
|
||||||
{
|
{
|
||||||
world = entity.world;
|
World w = world;
|
||||||
}
|
// TODO caching?
|
||||||
if(world == null)
|
if(w == null && entity != null)
|
||||||
{
|
{
|
||||||
world = Minecraft.getMinecraft().world;
|
w = entity.world;
|
||||||
}
|
}
|
||||||
IModelState state = asm.apply(Animation.getWorldTime(world, Animation.getPartialTickTime())).getLeft();
|
if(world == null)
|
||||||
|
{
|
||||||
|
w = Minecraft.getMinecraft().world;
|
||||||
|
}
|
||||||
|
return asm.apply(Animation.getWorldTime(world, Animation.getPartialTickTime())).getLeft();
|
||||||
|
})
|
||||||
// TODO where should uvlock data come from?
|
// TODO where should uvlock data come from?
|
||||||
return model.bake(ModelLoader.defaultModelGetter(), bakedTextureGetter, new ModelStateComposition(state, this.state), false, format);
|
.map(state -> model.bake(ModelLoader.defaultModelGetter(), bakedTextureGetter, new ModelStateComposition(state, this.state), false, format))
|
||||||
}
|
.orElseGet(() -> super.func_209581_a(originalModel, stack, world, entity));
|
||||||
return super.func_209581_a(originalModel, stack, world, entity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,11 +42,8 @@ import net.minecraftforge.client.model.pipeline.VertexLighterFlat;
|
||||||
import net.minecraftforge.client.model.pipeline.VertexBufferConsumer;
|
import net.minecraftforge.client.model.pipeline.VertexBufferConsumer;
|
||||||
import net.minecraftforge.common.animation.Event;
|
import net.minecraftforge.common.animation.Event;
|
||||||
import net.minecraftforge.common.animation.IEventHandler;
|
import net.minecraftforge.common.animation.IEventHandler;
|
||||||
import net.minecraftforge.common.model.IModelState;
|
|
||||||
import net.minecraftforge.common.model.animation.CapabilityAnimation;
|
import net.minecraftforge.common.model.animation.CapabilityAnimation;
|
||||||
|
|
||||||
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,17 +66,18 @@ public class AnimationModelBase<T extends Entity> extends ModelBase implements I
|
||||||
@Override
|
@Override
|
||||||
public void render(Entity entity, float limbSwing, float limbSwingSpeed, float timeAlive, float yawHead, float rotationPitch, float scale)
|
public void render(Entity entity, float limbSwing, float limbSwingSpeed, float timeAlive, float yawHead, float rotationPitch, float scale)
|
||||||
{
|
{
|
||||||
IAnimationStateMachine capability = entity.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null);
|
entity.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null)
|
||||||
if (capability == null)
|
.map(cap -> cap.apply(timeAlive / 20))
|
||||||
{
|
.map(pair -> {
|
||||||
return;
|
handleEvents((T) entity, timeAlive / 20, pair.getRight());
|
||||||
}
|
IUnbakedModel unbaked = ModelLoaderRegistry.getModelOrMissing(modelLocation);
|
||||||
Pair<IModelState, Iterable<Event>> pair = capability.apply(timeAlive / 20);
|
// TODO where should uvlock data come from?
|
||||||
handleEvents((T)entity, timeAlive / 20, pair.getRight());
|
return unbaked.bake(ModelLoader.defaultModelGetter(), ModelLoader.defaultTextureGetter(), pair.getLeft(), false, DefaultVertexFormats.ITEM);
|
||||||
IUnbakedModel model = ModelLoaderRegistry.getModelOrMissing(modelLocation);
|
}).ifPresent(model -> drawModel(model, entity));
|
||||||
// TODO where should uvlock data come from?
|
}
|
||||||
IBakedModel bakedModel = model.bake(ModelLoader.defaultModelGetter(), ModelLoader.defaultTextureGetter(), pair.getLeft(), false, DefaultVertexFormats.ITEM);
|
|
||||||
|
|
||||||
|
private void drawModel(IBakedModel bakedModel, Entity entity)
|
||||||
|
{
|
||||||
BlockPos pos = new BlockPos(entity.posX, entity.posY + entity.height, entity.posZ);
|
BlockPos pos = new BlockPos(entity.posX, entity.posY + entity.height, entity.posZ);
|
||||||
|
|
||||||
RenderHelper.disableStandardItemLighting();
|
RenderHelper.disableStandardItemLighting();
|
||||||
|
@ -109,7 +107,7 @@ public class AnimationModelBase<T extends Entity> extends ModelBase implements I
|
||||||
}
|
}
|
||||||
for(EnumFacing side : EnumFacing.values())
|
for(EnumFacing side : EnumFacing.values())
|
||||||
{
|
{
|
||||||
random.setSeed(42);
|
random.setSeed(42);
|
||||||
quads = bakedModel.func_200117_a(null, side, random);
|
quads = bakedModel.func_200117_a(null, side, random);
|
||||||
if(!quads.isEmpty())
|
if(!quads.isEmpty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,6 +30,7 @@ import net.minecraft.world.IWorldReader;
|
||||||
import net.minecraftforge.client.MinecraftForgeClient;
|
import net.minecraftforge.client.MinecraftForgeClient;
|
||||||
import net.minecraftforge.common.animation.Event;
|
import net.minecraftforge.common.animation.Event;
|
||||||
import net.minecraftforge.common.animation.IEventHandler;
|
import net.minecraftforge.common.animation.IEventHandler;
|
||||||
|
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
|
||||||
import net.minecraftforge.common.model.IModelState;
|
import net.minecraftforge.common.model.IModelState;
|
||||||
import net.minecraftforge.common.model.animation.CapabilityAnimation;
|
import net.minecraftforge.common.model.animation.CapabilityAnimation;
|
||||||
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
|
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
|
||||||
|
@ -50,7 +51,8 @@ public class AnimationTESR<T extends TileEntity> extends FastTESR<T> implements
|
||||||
@Override
|
@Override
|
||||||
public void renderTileEntityFast(T te, double x, double y, double z, float partialTick, int breakStage, BufferBuilder renderer)
|
public void renderTileEntityFast(T te, double x, double y, double z, float partialTick, int breakStage, BufferBuilder renderer)
|
||||||
{
|
{
|
||||||
if(!te.hasCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null))
|
OptionalCapabilityInstance<IAnimationStateMachine> cap = te.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY);
|
||||||
|
if(!cap.isPresent())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +62,7 @@ public class AnimationTESR<T extends TileEntity> extends FastTESR<T> implements
|
||||||
IBlockState state = world.getBlockState(pos);
|
IBlockState state = world.getBlockState(pos);
|
||||||
if(state.getBlock().getBlockState().getProperties().contains(Properties.StaticProperty))
|
if(state.getBlock().getBlockState().getProperties().contains(Properties.StaticProperty))
|
||||||
{
|
{
|
||||||
state = state.withProperty(Properties.StaticProperty, false);
|
state = state.func_206870_a(Properties.StaticProperty, false);
|
||||||
}
|
}
|
||||||
if(state instanceof IExtendedBlockState)
|
if(state instanceof IExtendedBlockState)
|
||||||
{
|
{
|
||||||
|
@ -68,20 +70,19 @@ public class AnimationTESR<T extends TileEntity> extends FastTESR<T> implements
|
||||||
if(exState.getUnlistedNames().contains(Properties.AnimationProperty))
|
if(exState.getUnlistedNames().contains(Properties.AnimationProperty))
|
||||||
{
|
{
|
||||||
float time = Animation.getWorldTime(getWorld(), partialTick);
|
float time = Animation.getWorldTime(getWorld(), partialTick);
|
||||||
IAnimationStateMachine capability = te.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY, null);
|
cap
|
||||||
if (capability != null)
|
.map(asm -> asm.apply(time))
|
||||||
{
|
.ifPresent(pair -> {
|
||||||
Pair<IModelState, Iterable<Event>> pair = capability.apply(time);
|
handleEvents(te, time, pair.getRight());
|
||||||
handleEvents(te, time, pair.getRight());
|
|
||||||
|
|
||||||
// TODO: caching?
|
// TODO: caching?
|
||||||
IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(exState.getClean());
|
IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(exState.getClean());
|
||||||
exState = exState.withProperty(Properties.AnimationProperty, pair.getLeft());
|
IExtendedBlockState animState = exState.withProperty(Properties.AnimationProperty, pair.getLeft());
|
||||||
|
|
||||||
renderer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());
|
renderer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());
|
||||||
|
|
||||||
blockRenderer.getBlockModelRenderer().func_199324_a(world, model, exState, pos, renderer, false, new Random(), 42);
|
blockRenderer.getBlockModelRenderer().func_199324_a(world, model, animState, pos, renderer, false, new Random(), 42);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
|
|
||||||
package net.minecraftforge.client.resource;
|
package net.minecraftforge.client.resource;
|
||||||
|
|
||||||
import net.minecraftforge.fml.relauncher.Side;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a generic type of reloadable resource. Used for resource reload filtering.
|
* Represents a generic type of reloadable resource. Used for resource reload filtering.
|
||||||
*/
|
*/
|
||||||
@SideOnly(Side.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public interface IResourceType
|
public interface IResourceType
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,15 +22,15 @@ package net.minecraftforge.client.resource;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import net.minecraftforge.fml.relauncher.Side;
|
|
||||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds methods to create standard predicates to select {@link IResourceType}s that should be reloaded.
|
* Holds methods to create standard predicates to select {@link IResourceType}s that should be reloaded.
|
||||||
*/
|
*/
|
||||||
@SideOnly(Side.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public final class ReloadRequirements
|
public final class ReloadRequirements
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -79,6 +79,7 @@ import net.minecraft.item.ItemPotion;
|
||||||
import net.minecraft.item.ItemSpade;
|
import net.minecraft.item.ItemSpade;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.ItemTippedArrow;
|
import net.minecraft.item.ItemTippedArrow;
|
||||||
|
import net.minecraft.item.ItemUseContext;
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
|
@ -867,8 +868,11 @@ public class ForgeHooks
|
||||||
return event.isCanceled() ? -1 : event.getExpToDrop();
|
return event.isCanceled() ? -1 : event.getExpToDrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EnumActionResult onPlaceItemIntoWorld(@Nonnull ItemStack itemstack, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing side, float hitX, float hitY, float hitZ, @Nonnull EnumHand hand)
|
public static EnumActionResult onPlaceItemIntoWorld(@Nonnull ItemUseContext context)
|
||||||
{
|
{
|
||||||
|
ItemStack itemstack = context.func_195996_i();
|
||||||
|
World world = context.func_195991_k();
|
||||||
|
|
||||||
// handle all placement events here
|
// handle all placement events here
|
||||||
int meta = itemstack.getItemDamage();
|
int meta = itemstack.getItemDamage();
|
||||||
int size = itemstack.getCount();
|
int size = itemstack.getCount();
|
||||||
|
@ -883,7 +887,7 @@ public class ForgeHooks
|
||||||
world.captureBlockSnapshots = true;
|
world.captureBlockSnapshots = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EnumActionResult ret = itemstack.getItem().onItemUse(player, world, pos, hand, side, hitX, hitY, hitZ);
|
EnumActionResult ret = itemstack.getItem().func_195939_a(context);
|
||||||
world.captureBlockSnapshots = false;
|
world.captureBlockSnapshots = false;
|
||||||
|
|
||||||
if (ret == EnumActionResult.SUCCESS)
|
if (ret == EnumActionResult.SUCCESS)
|
||||||
|
@ -902,12 +906,16 @@ public class ForgeHooks
|
||||||
world.capturedBlockSnapshots.clear();
|
world.capturedBlockSnapshots.clear();
|
||||||
|
|
||||||
// make sure to set pre-placement item data for event
|
// make sure to set pre-placement item data for event
|
||||||
itemstack.setItemDamage(meta);
|
itemstack.func_196085_b(meta);
|
||||||
itemstack.setCount(size);
|
itemstack.setCount(size);
|
||||||
if (nbt != null)
|
if (nbt != null)
|
||||||
{
|
{
|
||||||
itemstack.setTagCompound(nbt);
|
itemstack.setTagCompound(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityPlayer player = context.func_195999_j();
|
||||||
|
EnumFacing side = context.func_196000_l();
|
||||||
|
|
||||||
if (blockSnapshots.size() > 1)
|
if (blockSnapshots.size() > 1)
|
||||||
{
|
{
|
||||||
placeEvent = ForgeEventFactory.onPlayerMultiBlockPlace(player, blockSnapshots, side, hand);
|
placeEvent = ForgeEventFactory.onPlayerMultiBlockPlace(player, blockSnapshots, side, hand);
|
||||||
|
@ -931,7 +939,7 @@ public class ForgeHooks
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Change the stack to its new content
|
// Change the stack to its new content
|
||||||
itemstack.setItemDamage(newMeta);
|
itemstack.func_196085_b(newMeta);
|
||||||
itemstack.setCount(newSize);
|
itemstack.setCount(newSize);
|
||||||
if (nbt != null)
|
if (nbt != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,17 +135,6 @@ public class Capability<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Use this inside ICapabilityProvider.getCapability to avoid unchecked cast warnings.
|
|
||||||
* Example: return SOME_CAPABILITY.cast(instance);
|
|
||||||
* Use with caution;
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <R> R cast(T instance)
|
|
||||||
{
|
|
||||||
return (R)instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTERNAL
|
// INTERNAL
|
||||||
private final String name;
|
private final String name;
|
||||||
private final IStorage<T> storage;
|
private final IStorage<T> storage;
|
||||||
|
|
|
@ -20,11 +20,14 @@
|
||||||
package net.minecraftforge.common.capabilities;
|
package net.minecraftforge.common.capabilities;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
import net.minecraft.nbt.INBTBase;
|
import net.minecraft.nbt.INBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
|
@ -41,6 +44,8 @@ import net.minecraftforge.common.util.INBTSerializable;
|
||||||
* Internally the handlers are baked into arrays for fast iteration.
|
* Internally the handlers are baked into arrays for fast iteration.
|
||||||
* The ResourceLocations will be used for the NBT Key when serializing.
|
* The ResourceLocations will be used for the NBT Key when serializing.
|
||||||
*/
|
*/
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompound>, ICapabilityProvider
|
public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompound>, ICapabilityProvider
|
||||||
{
|
{
|
||||||
private ICapabilityProvider[] caps;
|
private ICapabilityProvider[] caps;
|
||||||
|
@ -87,7 +92,7 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> OptionalCapabilityInstance<T> getCapability(Capability<T> cap, EnumFacing side)
|
public <T> OptionalCapabilityInstance<T> getCapability(Capability<T> cap, @Nullable EnumFacing side)
|
||||||
{
|
{
|
||||||
for (ICapabilityProvider c : caps)
|
for (ICapabilityProvider c : caps)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +127,7 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean areCompatible(CapabilityDispatcher other) //Called from ItemStack to compare equality.
|
public boolean areCompatible(@Nullable CapabilityDispatcher other) //Called from ItemStack to compare equality.
|
||||||
{ // Only compares serializeable caps.
|
{ // Only compares serializeable caps.
|
||||||
if (other == null) return this.writers.length == 0; // Done this way so we can do some pre-checks before doing the costly NBT serialization and compare
|
if (other == null) return this.writers.length == 0; // Done this way so we can do some pre-checks before doing the costly NBT serialization and compare
|
||||||
if (this.writers.length == 0) return other.writers.length == 0;
|
if (this.writers.length == 0) return other.writers.length == 0;
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.util.EnumFacing;
|
||||||
|
import net.minecraftforge.event.ForgeEventFactory;
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
public abstract class CapabilityProvider implements ICapabilityProvider
|
||||||
|
{
|
||||||
|
private @Nullable CapabilityDispatcher capabilities;
|
||||||
|
|
||||||
|
protected final void gatherCapabilities() { gatherCapabilities(null); }
|
||||||
|
|
||||||
|
protected final void gatherCapabilities(@Nullable ICapabilityProvider parent)
|
||||||
|
{
|
||||||
|
this.capabilities = ForgeEventFactory.gatherCapabilities(getClass(), this, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final @Nullable CapabilityDispatcher getCapabilities()
|
||||||
|
{
|
||||||
|
return this.capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean areCapsCompatible(CapabilityProvider other)
|
||||||
|
{
|
||||||
|
return areCapsCompatible(other.getCapabilities());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean areCapsCompatible(@Nullable CapabilityDispatcher other)
|
||||||
|
{
|
||||||
|
final CapabilityDispatcher disp = getCapabilities();
|
||||||
|
if (disp == null)
|
||||||
|
{
|
||||||
|
if (other == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return other.areCompatible(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return disp.areCompatible(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final @Nullable NBTTagCompound serializeCaps()
|
||||||
|
{
|
||||||
|
final CapabilityDispatcher disp = getCapabilities();
|
||||||
|
if (disp != null)
|
||||||
|
{
|
||||||
|
return disp.serializeNBT();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void deserializeCaps(NBTTagCompound tag)
|
||||||
|
{
|
||||||
|
final CapabilityDispatcher disp = getCapabilities();
|
||||||
|
if (disp != null)
|
||||||
|
{
|
||||||
|
disp.deserializeNBT(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nonnull
|
||||||
|
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side)
|
||||||
|
{
|
||||||
|
final CapabilityDispatcher disp = getCapabilities();
|
||||||
|
return disp == null ? OptionalCapabilityInstance.empty() : disp.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 Consumer, except there IS a contract that the parameter must not be null.
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface NonNullConsumer<T>
|
||||||
|
{
|
||||||
|
void accept(@Nonnull T t);
|
||||||
|
}
|
|
@ -28,6 +28,14 @@ import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
public class OptionalCapabilityInstance<T>
|
public class OptionalCapabilityInstance<T>
|
||||||
{
|
{
|
||||||
private final NonNullSupplier<T> supplier;
|
private final NonNullSupplier<T> supplier;
|
||||||
|
@ -35,7 +43,7 @@ public class OptionalCapabilityInstance<T>
|
||||||
private Set<Consumer<OptionalCapabilityInstance<T>>> listeners = new HashSet<>();
|
private Set<Consumer<OptionalCapabilityInstance<T>>> listeners = new HashSet<>();
|
||||||
private boolean isValid = true;
|
private boolean isValid = true;
|
||||||
|
|
||||||
private static final OptionalCapabilityInstance<Void> EMPTY = new OptionalCapabilityInstance<>(null);
|
private static final @Nonnull OptionalCapabilityInstance<Void> EMPTY = new OptionalCapabilityInstance<>(null);
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> OptionalCapabilityInstance<T> empty()
|
public static <T> OptionalCapabilityInstance<T> empty()
|
||||||
|
@ -49,17 +57,17 @@ public class OptionalCapabilityInstance<T>
|
||||||
return (OptionalCapabilityInstance<X>)this;
|
return (OptionalCapabilityInstance<X>)this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OptionalCapabilityInstance(NonNullSupplier<T> instanceSupplier)
|
private OptionalCapabilityInstance(@Nullable NonNullSupplier<T> instanceSupplier)
|
||||||
{
|
{
|
||||||
this.supplier = instanceSupplier;
|
this.supplier = instanceSupplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> OptionalCapabilityInstance<T> of(final NonNullSupplier<T> instanceSupplier)
|
public static <T> OptionalCapabilityInstance<T> of(final @Nullable NonNullSupplier<T> instanceSupplier)
|
||||||
{
|
{
|
||||||
return new OptionalCapabilityInstance<>(instanceSupplier);
|
return instanceSupplier == null ? EMPTY.cast() : new OptionalCapabilityInstance<>(instanceSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private T getValue()
|
private @Nullable T getValue()
|
||||||
{
|
{
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
return null;
|
return null;
|
||||||
|
@ -103,10 +111,11 @@ public class OptionalCapabilityInstance<T>
|
||||||
* @throws NullPointerException if mod object is present and {@code consumer} is
|
* @throws NullPointerException if mod object is present and {@code consumer} is
|
||||||
* null
|
* null
|
||||||
*/
|
*/
|
||||||
public void ifPresent(Consumer<? super T> consumer)
|
public void ifPresent(NonNullConsumer<? super T> consumer)
|
||||||
{
|
{
|
||||||
if (isValid && getValue() != null)
|
T val = getValue();
|
||||||
consumer.accept(getValue());
|
if (isValid && val != null)
|
||||||
|
consumer.accept(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,30 +157,6 @@ public class OptionalCapabilityInstance<T>
|
||||||
return isPresent() ? OptionalCapabilityInstance.of(()->mapper.apply(getValue())) : empty();
|
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 <U> 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<U> OptionalCapabilityInstance<U> flatMap(Function<? super T, Optional<U>> 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}.
|
* Return the mod object if present, otherwise return {@code other}.
|
||||||
*
|
*
|
||||||
|
@ -181,7 +166,8 @@ public class OptionalCapabilityInstance<T>
|
||||||
*/
|
*/
|
||||||
public T orElse(T other)
|
public T orElse(T other)
|
||||||
{
|
{
|
||||||
return getValue() != null ? getValue() : other;
|
T val = getValue();
|
||||||
|
return val != null ? val : other;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -194,9 +180,10 @@ public class OptionalCapabilityInstance<T>
|
||||||
* @throws NullPointerException if mod object is not present and {@code other} is
|
* @throws NullPointerException if mod object is not present and {@code other} is
|
||||||
* null
|
* null
|
||||||
*/
|
*/
|
||||||
public T orElseGet(Supplier<? extends T> other)
|
public T orElseGet(NonNullSupplier<? extends T> other)
|
||||||
{
|
{
|
||||||
return getValue() != null ? getValue() : other.get();
|
T val = getValue();
|
||||||
|
return val != null ? val : other.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,8 +204,9 @@ public class OptionalCapabilityInstance<T>
|
||||||
*/
|
*/
|
||||||
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
|
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
|
||||||
{
|
{
|
||||||
if (getValue() != null)
|
T val = getValue();
|
||||||
return getValue();
|
if (val != null)
|
||||||
|
return val;
|
||||||
throw exceptionSupplier.get();
|
throw exceptionSupplier.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||||
|
|
||||||
|
public interface IForgeChunk extends ICapabilityProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
|
public interface IForgeDimension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called from {@link World#initCapabilities()}, to gather capabilities for this
|
||||||
|
* world. It's safe to access world here since this is called after world is
|
||||||
|
* registered.
|
||||||
|
*
|
||||||
|
* On server, called directly after mapStorage and world data such as Scoreboard
|
||||||
|
* and VillageCollection are initialized. On client, called when world is
|
||||||
|
* constructed, just before world load event is called. Note that this method is
|
||||||
|
* always called before the world load event.
|
||||||
|
*
|
||||||
|
* @return initial holder for capabilities on the world
|
||||||
|
*/
|
||||||
|
default net.minecraftforge.common.capabilities.ICapabilityProvider initCapabilities()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||||
|
|
||||||
|
public interface IForgeEntity extends ICapabilitySerializable<NBTTagCompound>
|
||||||
|
{
|
||||||
|
default Entity getEntity() { return (Entity) this; }
|
||||||
|
|
||||||
|
default void deserializeNBT(NBTTagCompound nbt)
|
||||||
|
{
|
||||||
|
getEntity().readFromNBT(nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
default NBTTagCompound serializeNBT()
|
||||||
|
{
|
||||||
|
NBTTagCompound ret = new NBTTagCompound();
|
||||||
|
String id = getEntity().getEntityString();
|
||||||
|
if (id != null)
|
||||||
|
{
|
||||||
|
ret.setString("id", getEntity().getEntityString());
|
||||||
|
}
|
||||||
|
return getEntity().writeToNBT(ret);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,758 @@
|
||||||
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
|
import net.minecraft.block.state.IBlockState;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||||
|
import net.minecraft.entity.passive.EntityHorse;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
|
import net.minecraft.init.Items;
|
||||||
|
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||||
|
import net.minecraft.item.IItemPropertyGetter;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemAxe;
|
||||||
|
import net.minecraft.item.ItemGroup;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.ItemSword;
|
||||||
|
import net.minecraft.item.ItemUseContext;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.util.EnumActionResult;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
import net.minecraft.util.registry.RegistrySimple;
|
||||||
|
import net.minecraft.world.GameType;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
// TODO review most of the methods in this "patch"
|
||||||
|
public interface IForgeItem
|
||||||
|
{
|
||||||
|
// Helpers for accessing Item data
|
||||||
|
default Item getItem()
|
||||||
|
{
|
||||||
|
return (Item) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItemStack sensitive version of getItemAttributeModifiers
|
||||||
|
*/
|
||||||
|
default Multimap<String, AttributeModifier> getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack)
|
||||||
|
{
|
||||||
|
return getItem().getItemAttributeModifiers(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a player drops the item into the world, returning false from this
|
||||||
|
* will prevent the item from being removed from the players inventory and
|
||||||
|
* spawning in the world
|
||||||
|
*
|
||||||
|
* @param player The player that dropped the item
|
||||||
|
* @param item The item stack, before the item is removed.
|
||||||
|
*/
|
||||||
|
default boolean onDroppedByPlayer(ItemStack item, EntityPlayer player)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow the item one last chance to modify its name used for the tool highlight
|
||||||
|
* useful for adding something extra that can't be removed by a user in the
|
||||||
|
* displayed name, such as a mode of operation.
|
||||||
|
*
|
||||||
|
* @param item the ItemStack for the item.
|
||||||
|
* @param displayName the name that will be displayed unless it is changed in
|
||||||
|
* this method.
|
||||||
|
*/
|
||||||
|
default String getHighlightTip(ItemStack item, String displayName)
|
||||||
|
{
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is called when the item is used, before the block is activated.
|
||||||
|
*
|
||||||
|
* @return Return PASS to allow vanilla handling, any other to skip normal code.
|
||||||
|
*/
|
||||||
|
default EnumActionResult onItemUseFirst(ItemUseContext context)
|
||||||
|
{
|
||||||
|
return EnumActionResult.PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by CraftingManager to determine if an item is reparable.
|
||||||
|
*
|
||||||
|
* @return True if reparable
|
||||||
|
*/
|
||||||
|
boolean isRepairable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to change the NBT data being sent to the client. You
|
||||||
|
* should ONLY override this when you have no other choice, as this might change
|
||||||
|
* behavior client side!
|
||||||
|
*
|
||||||
|
* Note that this will sometimes be applied multiple times, the following MUST
|
||||||
|
* be supported: Item item = stack.getItem(); NBTTagCompound nbtShare1 =
|
||||||
|
* item.getNBTShareTag(stack); stack.setTagCompound(nbtShare1); NBTTagCompound
|
||||||
|
* nbtShare2 = item.getNBTShareTag(stack); assert nbtShare1.equals(nbtShare2);
|
||||||
|
*
|
||||||
|
* @param stack The stack to send the NBT tag for
|
||||||
|
* @return The NBT tag
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default NBTTagCompound getNBTShareTag(ItemStack stack)
|
||||||
|
{
|
||||||
|
return stack.getTagCompound();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to decide what to do with the NBT data received from
|
||||||
|
* getNBTShareTag().
|
||||||
|
*
|
||||||
|
* @param stack The stack that received NBT
|
||||||
|
* @param nbt Received NBT, can be null
|
||||||
|
*/
|
||||||
|
default void readNBTShareTag(ItemStack stack, @Nullable NBTTagCompound nbt)
|
||||||
|
{
|
||||||
|
stack.setTagCompound(nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before a block is broken. Return true to prevent default block
|
||||||
|
* harvesting.
|
||||||
|
*
|
||||||
|
* Note: In SMP, this is called on both client and server sides!
|
||||||
|
*
|
||||||
|
* @param itemstack The current ItemStack
|
||||||
|
* @param pos Block's position in world
|
||||||
|
* @param player The Player that is wielding the item
|
||||||
|
* @return True to prevent harvesting, false to continue as normal
|
||||||
|
*/
|
||||||
|
default boolean onBlockStartBreak(ItemStack itemstack, BlockPos pos, EntityPlayer player)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called each tick while using an item.
|
||||||
|
*
|
||||||
|
* @param stack The Item being used
|
||||||
|
* @param player The Player using the item
|
||||||
|
* @param count The amount of time in tick the item has been used for
|
||||||
|
* continuously
|
||||||
|
*/
|
||||||
|
default void onUsingTick(ItemStack stack, EntityLivingBase player, int count)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the player Left Clicks (attacks) an entity. Processed before
|
||||||
|
* damage is done, if return value is true further processing is canceled and
|
||||||
|
* the entity is not attacked.
|
||||||
|
*
|
||||||
|
* @param stack The Item being used
|
||||||
|
* @param player The player that is attacking
|
||||||
|
* @param entity The entity being attacked
|
||||||
|
* @return True to cancel the rest of the interaction.
|
||||||
|
*/
|
||||||
|
default boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItemStack sensitive version of getContainerItem. Returns a full ItemStack
|
||||||
|
* instance of the result.
|
||||||
|
*
|
||||||
|
* @param itemStack The current ItemStack
|
||||||
|
* @return The resulting ItemStack
|
||||||
|
*/
|
||||||
|
default ItemStack getContainerItem(ItemStack itemStack)
|
||||||
|
{
|
||||||
|
if (!hasContainerItem(itemStack))
|
||||||
|
{
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
return new ItemStack(getItem().getContainerItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItemStack sensitive version of hasContainerItem
|
||||||
|
*
|
||||||
|
* @param stack The current item stack
|
||||||
|
* @return True if this item has a 'container'
|
||||||
|
*/
|
||||||
|
default boolean hasContainerItem(ItemStack stack)
|
||||||
|
{
|
||||||
|
return getItem().hasContainerItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the normal 'lifespan' of this item when it is dropped on the ground
|
||||||
|
* as a EntityItem. This is in ticks, standard result is 6000, or 5 mins.
|
||||||
|
*
|
||||||
|
* @param itemStack The current ItemStack
|
||||||
|
* @param world The world the entity is in
|
||||||
|
* @return The normal lifespan in ticks.
|
||||||
|
*/
|
||||||
|
default int getEntityLifespan(ItemStack itemStack, World world)
|
||||||
|
{
|
||||||
|
return 6000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if this Item has a special entity for when they are in the world.
|
||||||
|
* Is called when a EntityItem is spawned in the world, if true and
|
||||||
|
* Item#createCustomEntity returns non null, the EntityItem will be destroyed
|
||||||
|
* and the new Entity will be added to the world.
|
||||||
|
*
|
||||||
|
* @param stack The current item stack
|
||||||
|
* @return True of the item has a custom entity, If true,
|
||||||
|
* Item#createCustomEntity will be called
|
||||||
|
*/
|
||||||
|
default boolean hasCustomEntity(ItemStack stack)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function should return a new entity to replace the dropped item.
|
||||||
|
* Returning null here will not kill the EntityItem and will leave it to
|
||||||
|
* function normally. Called when the item it placed in a world.
|
||||||
|
*
|
||||||
|
* @param world The world object
|
||||||
|
* @param location The EntityItem object, useful for getting the position of
|
||||||
|
* the entity
|
||||||
|
* @param itemstack The current item stack
|
||||||
|
* @return A new Entity object to spawn or null
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default Entity createEntity(World world, Entity location, ItemStack itemstack)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by the default implemetation of EntityItem's onUpdate method, allowing
|
||||||
|
* for cleaner control over the update of the item without having to write a
|
||||||
|
* subclass.
|
||||||
|
*
|
||||||
|
* @param entityItem The entity Item
|
||||||
|
* @return Return true to skip any further update code.
|
||||||
|
*/
|
||||||
|
default boolean onEntityItemUpdate(net.minecraft.entity.item.EntityItem entityItem)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of tabs that items belonging to this class can display on,
|
||||||
|
* combined properly with getSubItems allows for a single item to span many
|
||||||
|
* sub-items across many tabs.
|
||||||
|
*
|
||||||
|
* @return A list of all tabs that this item could possibly be one.
|
||||||
|
*/
|
||||||
|
default java.util.Collection<ItemGroup> getCreativeTabs()
|
||||||
|
{
|
||||||
|
return java.util.Collections.singletonList(getItem().getCreativeTab());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the base experience for a player when they remove this item from a
|
||||||
|
* furnace slot. This number must be between 0 and 1 for it to be valid. This
|
||||||
|
* number will be multiplied by the stack size to get the total experience.
|
||||||
|
*
|
||||||
|
* @param item The item stack the player is picking up.
|
||||||
|
* @return The amount to award for each item.
|
||||||
|
*/
|
||||||
|
default float getSmeltingExperience(ItemStack item)
|
||||||
|
{
|
||||||
|
return -1; // -1 will default to the old lookups.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Should this item, when held, allow sneak-clicks to pass through to the
|
||||||
|
* underlying block?
|
||||||
|
*
|
||||||
|
* @param world The world
|
||||||
|
* @param pos Block position in world
|
||||||
|
* @param player The Player that is wielding the item
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
default boolean doesSneakBypassUse(ItemStack stack, net.minecraft.world.IWorldReader world, BlockPos pos, EntityPlayer player)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to tick armor in the armor slot. Override to do something
|
||||||
|
*/
|
||||||
|
default void onArmorTick(World world, EntityPlayer player, ItemStack itemStack)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the specific ItemStack can be placed in the specified armor
|
||||||
|
* slot, for the entity.
|
||||||
|
*
|
||||||
|
* TODO: Change name to canEquip in 1.13?
|
||||||
|
*
|
||||||
|
* @param stack The ItemStack
|
||||||
|
* @param armorType Armor slot to be verified.
|
||||||
|
* @param entity The entity trying to equip the armor
|
||||||
|
* @return True if the given ItemStack can be inserted in the slot
|
||||||
|
*/
|
||||||
|
default boolean isValidArmor(ItemStack stack, EntityEquipmentSlot armorType, Entity entity)
|
||||||
|
{
|
||||||
|
return net.minecraft.entity.EntityLiving.getSlotForItemStack(stack) == armorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this to set a non-default armor slot for an ItemStack, but <em>do
|
||||||
|
* not use this to get the armor slot of said stack; for that, use
|
||||||
|
* {@link net.minecraft.entity.EntityLiving#getSlotForItemStack(ItemStack)}.</em>
|
||||||
|
*
|
||||||
|
* @param stack the ItemStack
|
||||||
|
* @return the armor slot of the ItemStack, or {@code null} to let the default
|
||||||
|
* vanilla logic as per {@code EntityLiving.getSlotForItemStack(stack)}
|
||||||
|
* decide
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default EntityEquipmentSlot getEquipmentSlot(ItemStack stack)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow or forbid the specific book/item combination as an anvil enchant
|
||||||
|
*
|
||||||
|
* @param stack The item
|
||||||
|
* @param book The book
|
||||||
|
* @return if the enchantment is allowed
|
||||||
|
*/
|
||||||
|
default boolean isBookEnchantable(ItemStack stack, ItemStack book)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by RenderBiped and RenderPlayer to determine the armor texture that
|
||||||
|
* should be use for the currently equipped item. This will only be called on
|
||||||
|
* instances of ItemArmor.
|
||||||
|
*
|
||||||
|
* Returning null from this function will use the default value.
|
||||||
|
*
|
||||||
|
* @param stack ItemStack for the equipped armor
|
||||||
|
* @param entity The entity wearing the armor
|
||||||
|
* @param slot The slot the armor is in
|
||||||
|
* @param type The subtype, can be null or "overlay"
|
||||||
|
* @return Path of texture to bind, or null to use default
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default String getArmorTexture(ItemStack stack, Entity entity, EntityEquipmentSlot slot, String type)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the font renderer used to render tooltips and overlays for this item.
|
||||||
|
* Returning null will use the standard font renderer.
|
||||||
|
*
|
||||||
|
* @param stack The current item stack
|
||||||
|
* @return A instance of FontRenderer or null to use default
|
||||||
|
*/
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@Nullable
|
||||||
|
default net.minecraft.client.gui.FontRenderer getFontRenderer(ItemStack stack)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override this method to have an item handle its own armor rendering.
|
||||||
|
*
|
||||||
|
* @param entityLiving The entity wearing the armor
|
||||||
|
* @param itemStack The itemStack to render the model of
|
||||||
|
* @param armorSlot The slot the armor is in
|
||||||
|
* @param _default Original armor model. Will have attributes set.
|
||||||
|
* @return A ModelBiped to render instead of the default
|
||||||
|
*/
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@Nullable
|
||||||
|
default net.minecraft.client.renderer.entity.model.ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack,
|
||||||
|
EntityEquipmentSlot armorSlot, net.minecraft.client.renderer.entity.model.ModelBiped _default)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a entity tries to play the 'swing' animation.
|
||||||
|
*
|
||||||
|
* @param entityLiving The entity swinging the item.
|
||||||
|
* @param stack The Item stack
|
||||||
|
* @return True to cancel any further processing by EntityLiving
|
||||||
|
*/
|
||||||
|
default boolean onEntitySwing(EntityLivingBase entityLiving, ItemStack stack)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the client starts rendering the HUD, for whatever item the player
|
||||||
|
* currently has as a helmet. This is where pumpkins would render there overlay.
|
||||||
|
*
|
||||||
|
* @param stack The ItemStack that is equipped
|
||||||
|
* @param player Reference to the current client entity
|
||||||
|
* @param resolution Resolution information about the current viewport and
|
||||||
|
* configured GUI Scale
|
||||||
|
* @param partialTicks Partial ticks for the renderer, useful for interpolation
|
||||||
|
*/
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
default void renderHelmetOverlay(ItemStack stack, EntityPlayer player, int width, int height, float partialTicks)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the itemDamage represented by this ItemStack. Defaults to the Damage
|
||||||
|
* entry in the stack NBT, but can be overridden here for other sources.
|
||||||
|
*
|
||||||
|
* @param stack The itemstack that is damaged
|
||||||
|
* @return the damage value
|
||||||
|
*/
|
||||||
|
default int getDamage(ItemStack stack)
|
||||||
|
{
|
||||||
|
return !stack.hasTagCompound() ? 0 : stack.getTagCompound().getInteger("Damage");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the durability bar should be rendered for this item. Defaults
|
||||||
|
* to vanilla stack.isDamaged behavior. But modders can use this for any data
|
||||||
|
* they wish.
|
||||||
|
*
|
||||||
|
* @param stack The current Item Stack
|
||||||
|
* @return True if it should render the 'durability' bar.
|
||||||
|
*/
|
||||||
|
default boolean showDurabilityBar(ItemStack stack)
|
||||||
|
{
|
||||||
|
return stack.isItemDamaged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the percentage of the 'Durability' bar that should be drawn.
|
||||||
|
*
|
||||||
|
* @param stack The current ItemStack
|
||||||
|
* @return 0.0 for 100% (no damage / full bar), 1.0 for 0% (fully damaged /
|
||||||
|
* empty bar)
|
||||||
|
*/
|
||||||
|
default double getDurabilityForDisplay(ItemStack stack)
|
||||||
|
{
|
||||||
|
return (double) stack.getItemDamage() / (double) stack.getMaxDamage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the packed int RGB value used to render the durability bar in the
|
||||||
|
* GUI. Defaults to a value based on the hue scaled based on
|
||||||
|
* {@link #getDurabilityForDisplay}, but can be overriden.
|
||||||
|
*
|
||||||
|
* @param stack Stack to get durability from
|
||||||
|
* @return A packed RGB value for the durability colour (0x00RRGGBB)
|
||||||
|
*/
|
||||||
|
default int getRGBDurabilityForDisplay(ItemStack stack)
|
||||||
|
{
|
||||||
|
return MathHelper.hsvToRGB(Math.max(0.0F, (float) (1.0F - getDurabilityForDisplay(stack))) / 3.0F, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the maxDamage for this ItemStack. Defaults to the maxDamage field in
|
||||||
|
* this item, but can be overridden here for other sources such as NBT.
|
||||||
|
*
|
||||||
|
* @param stack The itemstack that is damaged
|
||||||
|
* @return the damage value
|
||||||
|
*/
|
||||||
|
default int getMaxDamage(ItemStack stack)
|
||||||
|
{
|
||||||
|
return getItem().getMaxDamage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if this itemstack is damaged. Note only called if
|
||||||
|
* {@link #isDamageable()} is true.
|
||||||
|
*
|
||||||
|
* @param stack the stack
|
||||||
|
* @return if the stack is damaged
|
||||||
|
*/
|
||||||
|
default boolean isDamaged(ItemStack stack)
|
||||||
|
{
|
||||||
|
return stack.getItemDamage() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the damage for this itemstack. Note, this method is responsible for zero
|
||||||
|
* checking.
|
||||||
|
*
|
||||||
|
* @param stack the stack
|
||||||
|
* @param damage the new damage value
|
||||||
|
*/
|
||||||
|
default void setDamage(ItemStack stack, int damage)
|
||||||
|
{
|
||||||
|
stack.func_196082_o().setInteger("Damage", Math.max(0, damage));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checked from
|
||||||
|
* {@link net.minecraft.client.multiplayer.PlayerControllerMP#onPlayerDestroyBlock(BlockPos pos)
|
||||||
|
* PlayerControllerMP.onPlayerDestroyBlock()} when a creative player left-clicks
|
||||||
|
* a block with this item. Also checked from
|
||||||
|
* {@link net.minecraftforge.common.ForgeHooks#onBlockBreakEvent(World, GameType, EntityPlayerMP, BlockPos)
|
||||||
|
* ForgeHooks.onBlockBreakEvent()} to prevent sending an event.
|
||||||
|
*
|
||||||
|
* @return true if the given player can destroy specified block in creative mode
|
||||||
|
* with this item
|
||||||
|
*/
|
||||||
|
default boolean canDestroyBlockInCreative(World world, BlockPos pos, ItemStack stack, EntityPlayer player)
|
||||||
|
{
|
||||||
|
return !(this instanceof ItemSword);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItemStack sensitive version of {@link #canHarvestBlock(IBlockState)}
|
||||||
|
*
|
||||||
|
* @param state The block trying to harvest
|
||||||
|
* @param stack The itemstack used to harvest the block
|
||||||
|
* @return true if can harvest the block
|
||||||
|
*/
|
||||||
|
default boolean canHarvestBlock(IBlockState state, ItemStack stack)
|
||||||
|
{
|
||||||
|
return getItem().canHarvestBlock(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the maximum number of items that this stack should be able to hold. This
|
||||||
|
* is a ItemStack (and thus NBT) sensitive version of Item.getItemStackLimit()
|
||||||
|
*
|
||||||
|
* @param stack The ItemStack
|
||||||
|
* @return The maximum number this item can be stacked to
|
||||||
|
*/
|
||||||
|
default int getItemStackLimit(ItemStack stack)
|
||||||
|
{
|
||||||
|
return getItem().getItemStackLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
java.util.Set<String> getToolClasses(ItemStack stack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the harvest level of this item stack for the specified tool class,
|
||||||
|
* Returns -1 if this tool is not of the specified type
|
||||||
|
*
|
||||||
|
* @param stack This item stack instance
|
||||||
|
* @param toolClass Tool Class
|
||||||
|
* @param player The player trying to harvest the given blockstate
|
||||||
|
* @param blockState The block to harvest
|
||||||
|
* @return Harvest level, or -1 if not the specified tool type.
|
||||||
|
*/
|
||||||
|
int getHarvestLevel(ItemStack stack, String toolClass, @Nullable EntityPlayer player, @Nullable IBlockState blockState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItemStack sensitive version of getItemEnchantability
|
||||||
|
*
|
||||||
|
* @param stack The ItemStack
|
||||||
|
* @return the item echantability value
|
||||||
|
*/
|
||||||
|
default int getItemEnchantability(ItemStack stack)
|
||||||
|
{
|
||||||
|
return getItem().getItemEnchantability();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether an item can be enchanted with a certain enchantment. This
|
||||||
|
* applies specifically to enchanting an item in the enchanting table and is
|
||||||
|
* called when retrieving the list of possible enchantments for an item.
|
||||||
|
* Enchantments may additionally (or exclusively) be doing their own checks in
|
||||||
|
* {@link net.minecraft.enchantment.Enchantment#canApplyAtEnchantingTable(ItemStack)};
|
||||||
|
* check the individual implementation for reference. By default this will check
|
||||||
|
* if the enchantment type is valid for this item type.
|
||||||
|
*
|
||||||
|
* @param stack the item stack to be enchanted
|
||||||
|
* @param enchantment the enchantment to be applied
|
||||||
|
* @return true if the enchantment can be applied to this item
|
||||||
|
*/
|
||||||
|
default boolean canApplyAtEnchantingTable(ItemStack stack, net.minecraft.enchantment.Enchantment enchantment)
|
||||||
|
{
|
||||||
|
return enchantment.type.canEnchantItem(stack.getItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this Item can be used as a payment to activate the vanilla beacon.
|
||||||
|
*
|
||||||
|
* @param stack the ItemStack
|
||||||
|
* @return true if this Item can be used
|
||||||
|
*/
|
||||||
|
default boolean isBeaconPayment(ItemStack stack)
|
||||||
|
{
|
||||||
|
return this == Items.EMERALD || this == Items.DIAMOND || this == Items.GOLD_INGOT || this == Items.IRON_INGOT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the player switching between these two item stacks
|
||||||
|
*
|
||||||
|
* @param oldStack The old stack that was equipped
|
||||||
|
* @param newStack The new stack
|
||||||
|
* @param slotChanged If the current equipped slot was changed, Vanilla does not
|
||||||
|
* play the animation if you switch between two slots that
|
||||||
|
* hold the exact same item.
|
||||||
|
* @return True to play the item change animation
|
||||||
|
*/
|
||||||
|
default boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged)
|
||||||
|
{
|
||||||
|
return !oldStack.equals(newStack); // !ItemStack.areItemStacksEqual(oldStack, newStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the player is mining a block and the item in his hand changes.
|
||||||
|
* Allows to not reset blockbreaking if only NBT or similar changes.
|
||||||
|
*
|
||||||
|
* @param oldStack The old stack that was used for mining. Item in players main
|
||||||
|
* hand
|
||||||
|
* @param newStack The new stack
|
||||||
|
* @return True to reset block break progress
|
||||||
|
*/
|
||||||
|
default boolean shouldCauseBlockBreakReset(ItemStack oldStack, ItemStack newStack)
|
||||||
|
{
|
||||||
|
return !(newStack.getItem() == oldStack.getItem() && ItemStack.areItemStackTagsEqual(newStack, oldStack)
|
||||||
|
&& (newStack.isItemStackDamageable() || newStack.getItemDamage() == oldStack.getItemDamage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to get the Mod ID of the mod that *created* the ItemStack, instead of
|
||||||
|
* the real Mod ID that *registered* it.
|
||||||
|
*
|
||||||
|
* For example the Forge Universal Bucket creates a subitem for each modded
|
||||||
|
* fluid, and it returns the modded fluid's Mod ID here.
|
||||||
|
*
|
||||||
|
* Mods that register subitems for other mods can override this. Informational
|
||||||
|
* mods can call it to show the mod that created the item.
|
||||||
|
*
|
||||||
|
* @param itemStack the ItemStack to check
|
||||||
|
* @return the Mod ID for the ItemStack, or null when there is no specially
|
||||||
|
* associated mod and {@link #getRegistryName()} would return null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default String getCreatorModId(ItemStack itemStack)
|
||||||
|
{
|
||||||
|
return net.minecraftforge.common.ForgeHooks.getDefaultCreatorModId(itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from ItemStack.setItem, will hold extra data for the life of this
|
||||||
|
* ItemStack. Can be retrieved from stack.getCapabilities() The NBT can be null
|
||||||
|
* if this is not called from readNBT or if the item the stack is changing FROM
|
||||||
|
* is different then this item, or the previous item had no capabilities.
|
||||||
|
*
|
||||||
|
* This is called BEFORE the stacks item is set so you can use stack.getItem()
|
||||||
|
* to see the OLD item. Remember that getItem CAN return null.
|
||||||
|
*
|
||||||
|
* @param stack The ItemStack
|
||||||
|
* @param nbt NBT of this item serialized, or null.
|
||||||
|
* @return A holder instance associated with this ItemStack where you can hold
|
||||||
|
* capabilities for the life of this item.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default net.minecraftforge.common.capabilities.ICapabilityProvider initCapabilities(ItemStack stack, @Nullable NBTTagCompound nbt)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default com.google.common.collect.ImmutableMap<String, net.minecraftforge.common.animation.ITimeValue> getAnimationParameters(final ItemStack stack,
|
||||||
|
final World world, final EntityLivingBase entity)
|
||||||
|
{
|
||||||
|
com.google.common.collect.ImmutableMap.Builder<String, net.minecraftforge.common.animation.ITimeValue> builder = com.google.common.collect.ImmutableMap
|
||||||
|
.builder();
|
||||||
|
for (ResourceLocation location : ((RegistrySimple<ResourceLocation, IItemPropertyGetter>) getItem().properties).getKeys())
|
||||||
|
{
|
||||||
|
final IItemPropertyGetter parameter = getItem().properties.getObject(location);
|
||||||
|
builder.put(location.toString(), input -> parameter.call(stack, world, entity));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can this Item disable a shield
|
||||||
|
*
|
||||||
|
* @param stack The ItemStack
|
||||||
|
* @param shield The shield in question
|
||||||
|
* @param entity The EntityLivingBase holding the shield
|
||||||
|
* @param attacker The EntityLivingBase holding the ItemStack
|
||||||
|
* @retrun True if this ItemStack can disable the shield in question.
|
||||||
|
*/
|
||||||
|
default boolean canDisableShield(ItemStack stack, ItemStack shield, EntityLivingBase entity, EntityLivingBase attacker)
|
||||||
|
{
|
||||||
|
return this instanceof ItemAxe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this Item a shield
|
||||||
|
*
|
||||||
|
* @param stack The ItemStack
|
||||||
|
* @param entity The Entity holding the ItemStack
|
||||||
|
* @return True if the ItemStack is considered a shield
|
||||||
|
*/
|
||||||
|
default boolean isShield(ItemStack stack, @Nullable EntityLivingBase entity)
|
||||||
|
{
|
||||||
|
return stack.getItem() == Items.SHIELD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the fuel burn time for this itemStack in a furnace. Return 0 to make
|
||||||
|
* it not act as a fuel. Return -1 to let the default vanilla logic
|
||||||
|
* decide.
|
||||||
|
*/
|
||||||
|
default int getItemBurnTime(ItemStack itemStack)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an enum constant of type {@code HorseArmorType}. The returned enum
|
||||||
|
* constant will be used to determine the armor value and texture of this item
|
||||||
|
* when equipped.
|
||||||
|
*
|
||||||
|
* @param stack the armor stack
|
||||||
|
* @return an enum constant of type {@code HorseArmorType}. Return
|
||||||
|
* HorseArmorType.NONE if this is not horse armor
|
||||||
|
*/
|
||||||
|
default net.minecraft.entity.passive.HorseArmorType getHorseArmorType(ItemStack stack)
|
||||||
|
{
|
||||||
|
return net.minecraft.entity.passive.HorseArmorType.getByItem(stack.getItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
default String getHorseArmorTexture(net.minecraft.entity.EntityLiving wearer, ItemStack stack)
|
||||||
|
{
|
||||||
|
return getHorseArmorType(stack).getTextureName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called every tick from {@link EntityHorse#onUpdate()} on the item in the
|
||||||
|
* armor slot.
|
||||||
|
*
|
||||||
|
* @param world the world the horse is in
|
||||||
|
* @param horse the horse wearing this armor
|
||||||
|
* @param armor the armor itemstack
|
||||||
|
*/
|
||||||
|
default void onHorseArmorTick(World world, net.minecraft.entity.EntityLiving horse, ItemStack armor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return This Item's renderer, or the default instance if it does not have
|
||||||
|
* one.
|
||||||
|
*/
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer getTileEntityItemStackRenderer();
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||||
|
|
||||||
|
public interface IForgeTileEntity extends ICapabilitySerializable<NBTTagCompound>
|
||||||
|
{
|
||||||
|
default TileEntity getTileEntity() { return (TileEntity) this; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void deserializeNBT(NBTTagCompound nbt)
|
||||||
|
{
|
||||||
|
getTileEntity().readFromNBT(nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default NBTTagCompound serializeNBT()
|
||||||
|
{
|
||||||
|
NBTTagCompound ret = new NBTTagCompound();
|
||||||
|
getTileEntity().writeToNBT(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.village.Village;
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
|
||||||
|
|
||||||
|
public interface IForgeVillage extends ICapabilitySerializable<NBTTagCompound>
|
||||||
|
{
|
||||||
|
default Village getVillage()
|
||||||
|
{
|
||||||
|
return (Village) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default void deserializeNBT(NBTTagCompound nbt)
|
||||||
|
{
|
||||||
|
getVillage().readVillageDataFromNBT(nbt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default NBTTagCompound serializeNBT()
|
||||||
|
{
|
||||||
|
NBTTagCompound ret = new NBTTagCompound();
|
||||||
|
getVillage().writeVillageDataToNBT(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||||
|
|
||||||
|
public interface IForgeWorld extends ICapabilityProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -60,14 +60,14 @@ public class CapabilityAnimation
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nonnull
|
||||||
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
|
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
|
||||||
{
|
{
|
||||||
if(capability == ANIMATION_CAPABILITY)
|
if(capability == ANIMATION_CAPABILITY)
|
||||||
{
|
{
|
||||||
return ANIMATION_CAPABILITY.cast(asm);
|
return OptionalCapabilityInstance.of(() -> asm).cast();
|
||||||
}
|
}
|
||||||
return null;
|
return OptionalCapabilityInstance.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
package net.minecraftforge.common.property;
|
package net.minecraftforge.common.property;
|
||||||
|
|
||||||
import net.minecraft.block.properties.IProperty;
|
import net.minecraft.state.BooleanProperty;
|
||||||
import net.minecraft.block.properties.PropertyBool;
|
import net.minecraft.state.IProperty;
|
||||||
import net.minecraftforge.common.model.IModelState;
|
import net.minecraftforge.common.model.IModelState;
|
||||||
|
|
||||||
public class Properties
|
public class Properties
|
||||||
|
@ -28,7 +28,7 @@ public class Properties
|
||||||
/**
|
/**
|
||||||
* Property indicating if the model should be rendered in the static renderer or in the TESR. AnimationTESR sets it to false.
|
* Property indicating if the model should be rendered in the static renderer or in the TESR. AnimationTESR sets it to false.
|
||||||
*/
|
*/
|
||||||
public static final PropertyBool StaticProperty = PropertyBool.create("static");
|
public static final BooleanProperty StaticProperty = BooleanProperty.create("static");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property holding the IModelState used for animating the model in the TESR.
|
* Property holding the IModelState used for animating the model in the TESR.
|
||||||
|
|
|
@ -19,8 +19,10 @@
|
||||||
|
|
||||||
package net.minecraftforge.common.util;
|
package net.minecraftforge.common.util;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.world.WorldProvider;
|
import net.minecraft.world.dimension.Dimension;
|
||||||
import net.minecraft.world.storage.WorldSavedData;
|
import net.minecraft.world.storage.WorldSavedData;
|
||||||
|
|
||||||
public class WorldCapabilityData extends WorldSavedData
|
public class WorldCapabilityData extends WorldSavedData
|
||||||
|
@ -35,7 +37,7 @@ public class WorldCapabilityData extends WorldSavedData
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorldCapabilityData(INBTSerializable<NBTTagCompound> serializable)
|
public WorldCapabilityData(@Nullable INBTSerializable<NBTTagCompound> serializable)
|
||||||
{
|
{
|
||||||
super(ID);
|
super(ID);
|
||||||
this.serializable = serializable;
|
this.serializable = serializable;
|
||||||
|
@ -66,7 +68,7 @@ public class WorldCapabilityData extends WorldSavedData
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCapabilities(WorldProvider provider, INBTSerializable<NBTTagCompound> capabilities)
|
public void setCapabilities(Dimension provider, INBTSerializable<NBTTagCompound> capabilities)
|
||||||
{
|
{
|
||||||
this.serializable = capabilities;
|
this.serializable = capabilities;
|
||||||
if (this.capNBT != null && serializable != null)
|
if (this.capNBT != null && serializable != null)
|
||||||
|
|
|
@ -328,9 +328,9 @@ public class ForgeEventFactory
|
||||||
return event.getNewState();
|
return event.getNewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemTooltipEvent onItemTooltip(ItemStack itemStack, @Nullable EntityPlayer entityPlayer, List<String> toolTip, ITooltipFlag flags)
|
public static ItemTooltipEvent onItemTooltip(ItemStack itemStack, @Nullable EntityPlayer entityPlayer, List<ITextComponent> list, ITooltipFlag flags)
|
||||||
{
|
{
|
||||||
ItemTooltipEvent event = new ItemTooltipEvent(itemStack, entityPlayer, toolTip, flags);
|
ItemTooltipEvent event = new ItemTooltipEvent(itemStack, entityPlayer, list, flags);
|
||||||
MinecraftForge.EVENT_BUS.post(event);
|
MinecraftForge.EVENT_BUS.post(event);
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
@ -624,41 +624,18 @@ public class ForgeEventFactory
|
||||||
{
|
{
|
||||||
return MinecraftForge.EVENT_BUS.post(new RenderBlockOverlayEvent(player, renderPartialTicks, type, block, pos));
|
return MinecraftForge.EVENT_BUS.post(new RenderBlockOverlayEvent(player, renderPartialTicks, type, block, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static CapabilityDispatcher gatherCapabilities(TileEntity tileEntity)
|
public static <T extends ICapabilityProvider> CapabilityDispatcher gatherCapabilities(Class<? extends T> type, T provider)
|
||||||
{
|
{
|
||||||
return gatherCapabilities(new AttachCapabilitiesEvent<TileEntity>(TileEntity.class, tileEntity), null);
|
return gatherCapabilities(type, provider, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Nullable
|
@Nullable
|
||||||
public static CapabilityDispatcher gatherCapabilities(Entity entity)
|
public static <T extends ICapabilityProvider> CapabilityDispatcher gatherCapabilities(Class<? extends T> type, T provider, @Nullable ICapabilityProvider parent)
|
||||||
{
|
{
|
||||||
return gatherCapabilities(new AttachCapabilitiesEvent<Entity>(Entity.class, entity), null);
|
return gatherCapabilities(new AttachCapabilitiesEvent<T>((Class<T>) type, provider), parent);
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static CapabilityDispatcher gatherCapabilities(Village village)
|
|
||||||
{
|
|
||||||
return gatherCapabilities(new AttachCapabilitiesEvent<Village>(Village.class, village), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static CapabilityDispatcher gatherCapabilities(ItemStack stack, ICapabilityProvider parent)
|
|
||||||
{
|
|
||||||
return gatherCapabilities(new AttachCapabilitiesEvent<ItemStack>(ItemStack.class, stack), parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static CapabilityDispatcher gatherCapabilities(World world, ICapabilityProvider parent)
|
|
||||||
{
|
|
||||||
return gatherCapabilities(new AttachCapabilitiesEvent<World>(World.class, world), parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static CapabilityDispatcher gatherCapabilities(Chunk chunk)
|
|
||||||
{
|
|
||||||
return gatherCapabilities(new AttachCapabilitiesEvent<Chunk>(Chunk.class, chunk), null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -25,6 +25,7 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.util.ITooltipFlag;
|
import net.minecraft.client.util.ITooltipFlag;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.text.ITextComponent;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -34,17 +35,17 @@ public class ItemTooltipEvent extends PlayerEvent
|
||||||
private final ITooltipFlag flags;
|
private final ITooltipFlag flags;
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final ItemStack itemStack;
|
private final ItemStack itemStack;
|
||||||
private final List<String> toolTip;
|
private final List<ITextComponent> toolTip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This event is fired in {@link ItemStack#getTooltip(EntityPlayer, ITooltipFlag)}, which in turn is called from it's respective GUIContainer.
|
* This event is fired in {@link ItemStack#getTooltip(EntityPlayer, ITooltipFlag)}, which in turn is called from it's respective GUIContainer.
|
||||||
* Tooltips are also gathered with a null entityPlayer during startup by {@link Minecraft#populateSearchTreeManager()}.
|
* Tooltips are also gathered with a null entityPlayer during startup by {@link Minecraft#populateSearchTreeManager()}.
|
||||||
*/
|
*/
|
||||||
public ItemTooltipEvent(@Nonnull ItemStack itemStack, @Nullable EntityPlayer entityPlayer, List<String> toolTip, ITooltipFlag flags)
|
public ItemTooltipEvent(@Nonnull ItemStack itemStack, @Nullable EntityPlayer entityPlayer, List<ITextComponent> list, ITooltipFlag flags)
|
||||||
{
|
{
|
||||||
super(entityPlayer);
|
super(entityPlayer);
|
||||||
this.itemStack = itemStack;
|
this.itemStack = itemStack;
|
||||||
this.toolTip = toolTip;
|
this.toolTip = list;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ public class ItemTooltipEvent extends PlayerEvent
|
||||||
/**
|
/**
|
||||||
* The {@link ItemStack} tooltip.
|
* The {@link ItemStack} tooltip.
|
||||||
*/
|
*/
|
||||||
public List<String> getToolTip()
|
public List<ITextComponent> getToolTip()
|
||||||
{
|
{
|
||||||
return toolTip;
|
return toolTip;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockLiquid;
|
|
||||||
import net.minecraft.block.material.Material;
|
import net.minecraft.block.material.Material;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
@ -40,6 +39,7 @@ import net.minecraft.util.SoundEvent;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.ForgeMod;
|
import net.minecraftforge.common.ForgeMod;
|
||||||
|
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
|
||||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||||
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
|
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
|
||||||
|
@ -74,8 +74,7 @@ public class FluidUtil
|
||||||
Preconditions.checkNotNull(world);
|
Preconditions.checkNotNull(world);
|
||||||
Preconditions.checkNotNull(pos);
|
Preconditions.checkNotNull(pos);
|
||||||
|
|
||||||
IFluidHandler blockFluidHandler = getFluidHandler(world, pos, side);
|
return getFluidHandler(world, pos, side).map(handler -> interactWithFluidHandler(player, hand, handler)).orElse(false);
|
||||||
return blockFluidHandler != null && interactWithFluidHandler(player, hand, blockFluidHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -98,21 +97,23 @@ public class FluidUtil
|
||||||
ItemStack heldItem = player.getHeldItem(hand);
|
ItemStack heldItem = player.getHeldItem(hand);
|
||||||
if (!heldItem.isEmpty())
|
if (!heldItem.isEmpty())
|
||||||
{
|
{
|
||||||
IItemHandler playerInventory = player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
|
return player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
|
||||||
if (playerInventory != null)
|
.map(playerInventory -> {
|
||||||
{
|
|
||||||
FluidActionResult fluidActionResult = tryFillContainerAndStow(heldItem, handler, playerInventory, Integer.MAX_VALUE, player, true);
|
FluidActionResult fluidActionResult = tryFillContainerAndStow(heldItem, handler, playerInventory, Integer.MAX_VALUE, player, true);
|
||||||
if (!fluidActionResult.isSuccess())
|
if (!fluidActionResult.isSuccess())
|
||||||
{
|
{
|
||||||
fluidActionResult = tryEmptyContainerAndStow(heldItem, handler, playerInventory, Integer.MAX_VALUE, player, true);
|
fluidActionResult = tryEmptyContainerAndStow(heldItem, handler, playerInventory, Integer.MAX_VALUE, player, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fluidActionResult.isSuccess())
|
if (fluidActionResult.isSuccess())
|
||||||
{
|
{
|
||||||
player.setHeldItem(hand, fluidActionResult.getResult());
|
player.setHeldItem(hand, fluidActionResult.getResult());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
|
})
|
||||||
|
.orElse(false);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -133,31 +134,31 @@ public class FluidUtil
|
||||||
public static FluidActionResult tryFillContainer(@Nonnull ItemStack container, IFluidHandler fluidSource, int maxAmount, @Nullable EntityPlayer player, boolean doFill)
|
public static FluidActionResult tryFillContainer(@Nonnull ItemStack container, IFluidHandler fluidSource, int maxAmount, @Nullable EntityPlayer player, boolean doFill)
|
||||||
{
|
{
|
||||||
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
||||||
IFluidHandlerItem containerFluidHandler = getFluidHandler(containerCopy);
|
return getFluidHandler(containerCopy)
|
||||||
if (containerFluidHandler != null)
|
.map(containerFluidHandler -> {
|
||||||
{
|
FluidStack simulatedTransfer = tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, false);
|
||||||
FluidStack simulatedTransfer = tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, false);
|
if (simulatedTransfer != null)
|
||||||
if (simulatedTransfer != null)
|
|
||||||
{
|
|
||||||
if (doFill)
|
|
||||||
{
|
|
||||||
tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, true);
|
|
||||||
if (player != null)
|
|
||||||
{
|
{
|
||||||
SoundEvent soundevent = simulatedTransfer.getFluid().getFillSound(simulatedTransfer);
|
if (doFill)
|
||||||
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
{
|
||||||
|
tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, true);
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
SoundEvent soundevent = simulatedTransfer.getFluid().getFillSound(simulatedTransfer);
|
||||||
|
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
containerFluidHandler.fill(simulatedTransfer, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack resultContainer = containerFluidHandler.getContainer();
|
||||||
|
return new FluidActionResult(resultContainer);
|
||||||
}
|
}
|
||||||
}
|
return FluidActionResult.FAILURE;
|
||||||
else
|
})
|
||||||
{
|
.orElse(FluidActionResult.FAILURE);
|
||||||
containerFluidHandler.fill(simulatedTransfer, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemStack resultContainer = containerFluidHandler.getContainer();
|
|
||||||
return new FluidActionResult(resultContainer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return FluidActionResult.FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,35 +178,35 @@ public class FluidUtil
|
||||||
public static FluidActionResult tryEmptyContainer(@Nonnull ItemStack container, IFluidHandler fluidDestination, int maxAmount, @Nullable EntityPlayer player, boolean doDrain)
|
public static FluidActionResult tryEmptyContainer(@Nonnull ItemStack container, IFluidHandler fluidDestination, int maxAmount, @Nullable EntityPlayer player, boolean doDrain)
|
||||||
{
|
{
|
||||||
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
||||||
IFluidHandlerItem containerFluidHandler = getFluidHandler(containerCopy);
|
return getFluidHandler(containerCopy)
|
||||||
if (containerFluidHandler != null)
|
.map(containerFluidHandler -> {
|
||||||
{
|
if (doDrain)
|
||||||
if (doDrain)
|
|
||||||
{
|
|
||||||
FluidStack transfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, true);
|
|
||||||
if (transfer != null)
|
|
||||||
{
|
|
||||||
if (player != null)
|
|
||||||
{
|
{
|
||||||
SoundEvent soundevent = transfer.getFluid().getEmptySound(transfer);
|
FluidStack transfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, true);
|
||||||
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
if (transfer != null)
|
||||||
|
{
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
SoundEvent soundevent = transfer.getFluid().getEmptySound(transfer);
|
||||||
|
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
ItemStack resultContainer = containerFluidHandler.getContainer();
|
||||||
|
return new FluidActionResult(resultContainer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ItemStack resultContainer = containerFluidHandler.getContainer();
|
else
|
||||||
return new FluidActionResult(resultContainer);
|
{
|
||||||
}
|
FluidStack simulatedTransfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, false);
|
||||||
}
|
if (simulatedTransfer != null)
|
||||||
else
|
{
|
||||||
{
|
containerFluidHandler.drain(simulatedTransfer, true);
|
||||||
FluidStack simulatedTransfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, false);
|
ItemStack resultContainer = containerFluidHandler.getContainer();
|
||||||
if (simulatedTransfer != null)
|
return new FluidActionResult(resultContainer);
|
||||||
{
|
}
|
||||||
containerFluidHandler.drain(simulatedTransfer, true);
|
}
|
||||||
ItemStack resultContainer = containerFluidHandler.getContainer();
|
return FluidActionResult.FAILURE;
|
||||||
return new FluidActionResult(resultContainer);
|
})
|
||||||
}
|
.orElse(FluidActionResult.FAILURE);
|
||||||
}
|
|
||||||
}
|
|
||||||
return FluidActionResult.FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -478,47 +479,30 @@ public class FluidUtil
|
||||||
* You can't fill or drain multiple items at once, if you do then liquid is multiplied or destroyed.
|
* You can't fill or drain multiple items at once, if you do then liquid is multiplied or destroyed.
|
||||||
*
|
*
|
||||||
* Vanilla buckets will be converted to universal buckets if they are enabled.
|
* Vanilla buckets will be converted to universal buckets if they are enabled.
|
||||||
*
|
|
||||||
* Returns null if the itemStack passed in does not have a fluid handler.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
public static OptionalCapabilityInstance<IFluidHandlerItem> getFluidHandler(@Nonnull ItemStack itemStack)
|
||||||
public static IFluidHandlerItem getFluidHandler(@Nonnull ItemStack itemStack)
|
|
||||||
{
|
{
|
||||||
if (itemStack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null))
|
return itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
|
||||||
{
|
|
||||||
return itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to get the fluid contained in an itemStack
|
* Helper method to get the fluid contained in an itemStack
|
||||||
*/
|
*/
|
||||||
@Nullable
|
public static OptionalCapabilityInstance<FluidStack> getFluidContained(@Nonnull ItemStack container)
|
||||||
public static FluidStack getFluidContained(@Nonnull ItemStack container)
|
|
||||||
{
|
{
|
||||||
if (!container.isEmpty())
|
if (!container.isEmpty())
|
||||||
{
|
{
|
||||||
container = ItemHandlerHelper.copyStackWithSize(container, 1);
|
container = ItemHandlerHelper.copyStackWithSize(container, 1);
|
||||||
IFluidHandlerItem fluidHandler = getFluidHandler(container);
|
return getFluidHandler(container)
|
||||||
if (fluidHandler != null)
|
.map(handler -> handler.drain(Integer.MAX_VALUE, false));
|
||||||
{
|
|
||||||
return fluidHandler.drain(Integer.MAX_VALUE, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return OptionalCapabilityInstance.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to get an IFluidHandler for at a block position.
|
* Helper method to get an IFluidHandler for at a block position.
|
||||||
*
|
|
||||||
* Returns null if there is no valid fluid handler.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
public static OptionalCapabilityInstance<IFluidHandler> getFluidHandler(World world, BlockPos blockPos, @Nullable EnumFacing side)
|
||||||
public static IFluidHandler getFluidHandler(World world, BlockPos blockPos, @Nullable EnumFacing side)
|
|
||||||
{
|
{
|
||||||
IBlockState state = world.getBlockState(blockPos);
|
IBlockState state = world.getBlockState(blockPos);
|
||||||
Block block = state.getBlock();
|
Block block = state.getBlock();
|
||||||
|
@ -526,21 +510,21 @@ public class FluidUtil
|
||||||
if (block.hasTileEntity(state))
|
if (block.hasTileEntity(state))
|
||||||
{
|
{
|
||||||
TileEntity tileEntity = world.getTileEntity(blockPos);
|
TileEntity tileEntity = world.getTileEntity(blockPos);
|
||||||
if (tileEntity != null && tileEntity.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side))
|
if (tileEntity != null)
|
||||||
{
|
{
|
||||||
return tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side);
|
return tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side);
|
||||||
}
|
}
|
||||||
}
|
}/* TODO fluids blocks?
|
||||||
if (block instanceof IFluidBlock)
|
if (block instanceof IFluidBlock)
|
||||||
{
|
{
|
||||||
return new FluidBlockWrapper((IFluidBlock) block, world, blockPos);
|
return OptionalCapabilityInstance.of(() -> new FluidBlockWrapper((IFluidBlock) block, world, blockPos));
|
||||||
}
|
}
|
||||||
else if (block instanceof BlockLiquid)
|
else if (block instanceof BlockLiquid)
|
||||||
{
|
{
|
||||||
return new BlockLiquidWrapper((BlockLiquid) block, world, blockPos);
|
return OptionalCapabilityInstance.of(() -> new BlockLiquidWrapper((BlockLiquid) block, world, blockPos));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return null;
|
return OptionalCapabilityInstance.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -565,6 +549,7 @@ public class FluidUtil
|
||||||
IBlockState state = worldIn.getBlockState(pos);
|
IBlockState state = worldIn.getBlockState(pos);
|
||||||
Block block = state.getBlock();
|
Block block = state.getBlock();
|
||||||
|
|
||||||
|
/* TODO fluid blocks?
|
||||||
if (block instanceof IFluidBlock || block instanceof BlockLiquid)
|
if (block instanceof IFluidBlock || block instanceof BlockLiquid)
|
||||||
{
|
{
|
||||||
IFluidHandler targetFluidHandler = getFluidHandler(worldIn, pos, side);
|
IFluidHandler targetFluidHandler = getFluidHandler(worldIn, pos, side);
|
||||||
|
@ -572,7 +557,7 @@ public class FluidUtil
|
||||||
{
|
{
|
||||||
return tryFillContainer(emptyContainer, targetFluidHandler, Integer.MAX_VALUE, playerIn, true);
|
return tryFillContainer(emptyContainer, targetFluidHandler, Integer.MAX_VALUE, playerIn, true);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
return FluidActionResult.FAILURE;
|
return FluidActionResult.FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,12 +576,11 @@ public class FluidUtil
|
||||||
public static FluidActionResult tryPlaceFluid(@Nullable EntityPlayer player, World world, BlockPos pos, @Nonnull ItemStack container, FluidStack resource)
|
public static FluidActionResult tryPlaceFluid(@Nullable EntityPlayer player, World world, BlockPos pos, @Nonnull ItemStack container, FluidStack resource)
|
||||||
{
|
{
|
||||||
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
ItemStack containerCopy = ItemHandlerHelper.copyStackWithSize(container, 1); // do not modify the input
|
||||||
IFluidHandlerItem containerFluidHandler = getFluidHandler(containerCopy);
|
return getFluidHandler(containerCopy)
|
||||||
if (containerFluidHandler != null && tryPlaceFluid(player, world, pos, containerFluidHandler, resource))
|
.filter(handler -> tryPlaceFluid(player, world, pos, handler, resource))
|
||||||
{
|
.map(IFluidHandlerItem::getContainer)
|
||||||
return new FluidActionResult(containerFluidHandler.getContainer());
|
.map(FluidActionResult::new)
|
||||||
}
|
.orElse(FluidActionResult.FAILURE);
|
||||||
return FluidActionResult.FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -674,7 +658,7 @@ public class FluidUtil
|
||||||
*/
|
*/
|
||||||
private static IFluidHandler getFluidBlockHandler(Fluid fluid, World world, BlockPos pos)
|
private static IFluidHandler getFluidBlockHandler(Fluid fluid, World world, BlockPos pos)
|
||||||
{
|
{
|
||||||
Block block = fluid.getBlock();
|
Block block = fluid.getBlock();/* TODO fluid blocks?
|
||||||
if (block instanceof IFluidBlock)
|
if (block instanceof IFluidBlock)
|
||||||
{
|
{
|
||||||
return new FluidBlockWrapper((IFluidBlock) block, world, pos);
|
return new FluidBlockWrapper((IFluidBlock) block, world, pos);
|
||||||
|
@ -683,7 +667,7 @@ public class FluidUtil
|
||||||
{
|
{
|
||||||
return new BlockLiquidWrapper((BlockLiquid) block, world, pos);
|
return new BlockLiquidWrapper((BlockLiquid) block, world, pos);
|
||||||
}
|
}
|
||||||
else
|
else*/
|
||||||
{
|
{
|
||||||
return new BlockWrapper(block, world, pos);
|
return new BlockWrapper(block, world, pos);
|
||||||
}
|
}
|
||||||
|
@ -724,7 +708,7 @@ public class FluidUtil
|
||||||
{
|
{
|
||||||
Fluid fluid = fluidStack.getFluid();
|
Fluid fluid = fluidStack.getFluid();
|
||||||
|
|
||||||
if (fluidStack.tag == null || fluidStack.tag.hasNoTags())
|
if (fluidStack.tag == null || fluidStack.tag.isEmpty())
|
||||||
{
|
{
|
||||||
if (fluid == FluidRegistry.WATER)
|
if (fluid == FluidRegistry.WATER)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,9 @@ public net.minecraft.block.BlockFire func_176534_d(Lnet/minecraft/block/Block;)I
|
||||||
# Item
|
# Item
|
||||||
public net.minecraft.item.Item func_77656_e(I)Lnet.minecraft.item.Item; #setMaxDamage
|
public net.minecraft.item.Item func_77656_e(I)Lnet.minecraft.item.Item; #setMaxDamage
|
||||||
public net.minecraft.item.Item func_77627_a(Z)Lnet.minecraft.item.Item; #setHasSubtypes
|
public net.minecraft.item.Item func_77627_a(Z)Lnet.minecraft.item.Item; #setHasSubtypes
|
||||||
|
public net.minecraft.item.Item field_185051_m # properties
|
||||||
|
# Entity
|
||||||
|
public net.minecraft.entity.Entity func_70022_Q()Ljava/lang/String; # getEntityString
|
||||||
# EntityPlayer
|
# EntityPlayer
|
||||||
public net.minecraft.entity.player.EntityPlayer func_71053_j()V #closeScreen
|
public net.minecraft.entity.player.EntityPlayer func_71053_j()V #closeScreen
|
||||||
# EntityTrackerEntry
|
# EntityTrackerEntry
|
||||||
|
|
Loading…
Reference in a new issue