backport 0bdc408e950fe787277d1e48be61ebf928127429

This commit is contained in:
Salomão
2021-03-31 20:53:26 -03:00
parent ca7ce33f34
commit 011b3a4b94
12 changed files with 524 additions and 600 deletions
@@ -56,9 +56,6 @@ public enum FuzzyMode {
*/ */
public final float percentage; public final float percentage;
public final float breakPoint;
public final float percentage;
FuzzyMode( final float p ) FuzzyMode( final float p )
{ {
this.percentage = p; this.percentage = p;
@@ -112,4 +112,13 @@ public interface IAEItemStack extends IAEStack<IAEItemStack>
* @return definition stack * @return definition stack
*/ */
ItemStack getDefinition(); ItemStack getDefinition();
/**
* Compare this AE item stack to another item stack, but ignores the amount. It checks the item type, NBT and damage
* values.
*
* @param is An item stack
*/
boolean equals(ItemStack is);
} }
@@ -23,27 +23,24 @@
package appeng.api.storage.data; package appeng.api.storage.data;
import java.io.IOException; import java.io.IOException;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.storage.IStorageChannel; import appeng.api.storage.IStorageChannel;
public interface IAEStack<T extends IAEStack<T>> {
public interface IAEStack<T extends IAEStack<T>>
{
/** /**
* add two stacks together * add two stacks together
* *
* @param is added item * @param is added item
*/ */
void add( T is ); void add(T is);
/** /**
* number of items in the stack. * number of items in the stack.
@@ -57,7 +54,7 @@ public interface IAEStack<T extends IAEStack<T>>
* *
* @param stackSize , ItemStack.stackSize = N * @param stackSize , ItemStack.stackSize = N
*/ */
T setStackSize( long stackSize ); T setStackSize(long stackSize);
/** /**
* Same as getStackSize, but for requestable items. ( LP ) * Same as getStackSize, but for requestable items. ( LP )
@@ -71,7 +68,7 @@ public interface IAEStack<T extends IAEStack<T>>
* *
* @return basically itemStack.stackSize = N but for setStackSize items. * @return basically itemStack.stackSize = N but for setStackSize items.
*/ */
T setCountRequestable( long countRequestable ); T setCountRequestable(long countRequestable);
/** /**
* true, if the item can be crafted. * true, if the item can be crafted.
@@ -85,7 +82,7 @@ public interface IAEStack<T extends IAEStack<T>>
* *
* @param isCraftable can item be crafted * @param isCraftable can item be crafted
*/ */
T setCraftable( boolean isCraftable ); T setCraftable(boolean isCraftable);
/** /**
* clears, requestable, craftable, and stack sizes. * clears, requestable, craftable, and stack sizes.
@@ -104,33 +101,33 @@ public interface IAEStack<T extends IAEStack<T>>
* *
* @param i additional stack size * @param i additional stack size
*/ */
void incStackSize( long i ); void incStackSize(long i);
/** /**
* removes some from the stack size. * removes some from the stack size.
*/ */
void decStackSize( long i ); void decStackSize(long i);
/** /**
* adds items to the requestable * adds items to the requestable
* *
* @param i increased amount of requested items * @param i increased amount of requested items
*/ */
void incCountRequestable( long i ); void incCountRequestable(long i);
/** /**
* removes items from the requestable * removes items from the requestable
* *
* @param i decreased amount of requested items * @param i decreased amount of requested items
*/ */
void decCountRequestable( long i ); void decCountRequestable(long i);
/** /**
* write to a NBTTagCompound. * write to a CompoundNBT.
* *
* @param i to be written data * @param i to be written data
*/ */
void writeToNBT( NBTTagCompound i ); void writeToNBT( NBTTagCompound i);
/** /**
* Compare stacks using precise logic. * Compare stacks using precise logic.
@@ -146,17 +143,18 @@ public interface IAEStack<T extends IAEStack<T>>
* @return true if they are the same. * @return true if they are the same.
*/ */
@Override @Override
boolean equals( Object obj ); boolean equals(Object obj);
/** /**
* Compare the same subtype of {@link IAEStack} with another using a fuzzy comparison. * Compare the same subtype of {@link IAEStack} with another using a fuzzy
* comparison.
* *
* @param other The stack to compare. * @param other The stack to compare.
* @param mode Which {@link FuzzyMode} should be used. * @param mode Which {@link FuzzyMode} should be used.
* *
* @return true if two stacks are equal based on AE Fuzzy Comparison. * @return true if two stacks are equal based on AE Fuzzy Comparison.
*/ */
boolean fuzzyComparison( T other, FuzzyMode mode ); boolean fuzzyComparison(T other, FuzzyMode mode);
/** /**
* Slower for disk saving, but smaller/more efficient for packets. * Slower for disk saving, but smaller/more efficient for packets.
@@ -165,7 +163,7 @@ public interface IAEStack<T extends IAEStack<T>>
* *
* @throws IOException * @throws IOException
*/ */
void writeToPacket( ByteBuf data ) throws IOException; void writeToPacket( ByteBuf data) throws IOException;
/** /**
* Clone the Item / Fluid Stack * Clone the Item / Fluid Stack
@@ -182,17 +180,7 @@ public interface IAEStack<T extends IAEStack<T>>
T empty(); T empty();
/** /**
* @return true if the stack is a {@link IAEItemStack} * @return The {@link IStorageChannel} backing this stack.
*/
boolean isItem();
/**
* @return true if the stack is a {@link IAEFluidStack}
*/
boolean isFluid();
/**
* @return ITEM or FLUID
*/ */
IStorageChannel<T> getChannel(); IStorageChannel<T> getChannel();
@@ -32,6 +32,7 @@ import io.netty.buffer.ByteBuf;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
@@ -216,18 +217,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
return dup; return dup;
} }
@Override
public boolean isItem()
{
return false;
}
@Override
public boolean isFluid()
{
return true;
}
@Override @Override
public IStorageChannel<IAEFluidStack> getChannel() public IStorageChannel<IAEFluidStack> getChannel()
{ {
@@ -318,17 +307,17 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
} }
@Override @Override
public void writeToPacket( final ByteBuf buffer ) throws IOException public void writeToPacket( final ByteBuf i ) throws IOException
{ {
final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this
.getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 ); .getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 );
buffer.writeByte( mask ); i.writeByte( mask );
this.writeToStream( buffer ); this.writeToStream( i );
this.putPacketValue( buffer, this.getStackSize() ); this.putPacketValue( i, this.getStackSize() );
this.putPacketValue( buffer, this.getCountRequestable() ); this.putPacketValue( i, this.getCountRequestable() );
} }
private void writeToStream( final ByteBuf buffer ) throws IOException private void writeToStream( final ByteBuf buffer ) throws IOException
@@ -0,0 +1,51 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 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, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 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 Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.util;
import java.util.regex.Pattern;
/**
* Regex wrapper for {@link java.util.UUID}s to not rely on try catch
*/
public final class UUIDMatcher
{
/**
* String which is the regular expression for {@link java.util.UUID}s
*/
private static final String UUID_REGEX = "[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}";
/**
* Pattern which pre-compiles the {@link appeng.util.UUIDMatcher#UUID_REGEX}
*/
private static final Pattern PATTERN = Pattern.compile( UUID_REGEX );
/**
* Checks if a potential {@link java.util.UUID} is an {@link java.util.UUID} by applying a regular expression on it.
*
* @param potential to be checked potential {@link java.util.UUID}
*
* @return true, if the potential {@link java.util.UUID} is indeed an {@link java.util.UUID}
*/
public boolean isUUID( final CharSequence potential )
{
return PATTERN.matcher( potential ).matches();
}
}
+222 -284
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Applied Energistics 2. * This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. * Copyright (c) 2013 - 2020, AlgorithmX2, All rights reserved.
* *
* Applied Energistics 2 is free software: you can redistribute it and/or modify * Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@@ -18,7 +18,6 @@
package appeng.util.item; package appeng.util.item;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
@@ -26,348 +25,287 @@ import java.util.Optional;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import appeng.api.AEApi;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import appeng.api.AEApi;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.storage.IStorageChannel; import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.util.Platform; import appeng.util.Platform;
public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemStack {
public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemStack private final AESharedItemStack sharedStack;
{ private Optional<OreReference> oreReference;
private AESharedItemStack sharedStack;
private Optional<OreReference> oreReference;
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
private String displayName; private String displayName;
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
private List<String> tooltip; private List<String> tooltip;
@SideOnly( Side.CLIENT )
private ResourceLocation uniqueID;
private AEItemStack( final AEItemStack is ) private AEItemStack(final AEItemStack is) {
{ this.setStackSize(is.getStackSize());
this.setStackSize( is.getStackSize() ); this.setCraftable(is.isCraftable());
this.setCraftable( is.isCraftable() ); this.setCountRequestable(is.getCountRequestable());
this.setCountRequestable( is.getCountRequestable() ); this.sharedStack = is.sharedStack;
this.sharedStack = is.sharedStack; this.oreReference = is.oreReference;
this.oreReference = is.oreReference; }
}
private AEItemStack( final AESharedItemStack is, long size ) private AEItemStack(final AESharedItemStack is, long size) {
{ this.sharedStack = is;
this.sharedStack = is; this.setStackSize(size);
this.setStackSize( size ); this.setCraftable(false);
this.setCraftable( false ); this.setCountRequestable(0);
this.setCountRequestable( 0 ); this.oreReference = OreHelper.INSTANCE.getOre( is.getDefinition() );
this.oreReference = OreHelper.INSTANCE.getOre( is.getDefinition() ); }
}
@Nullable @Nullable
public static AEItemStack fromItemStack( @Nonnull final ItemStack stack ) public static AEItemStack fromItemStack(@Nonnull final ItemStack stack) {
{ if (stack.isEmpty()) {
if( stack.isEmpty() ) return null;
{ }
return null;
}
return new AEItemStack( AEItemStackRegistry.getRegisteredStack( stack ), stack.getCount() ); return new AEItemStack(AEItemStackRegistry.getRegisteredStack(stack), stack.getCount());
} }
public static IAEItemStack fromNBT( final NBTTagCompound i ) public static IAEItemStack fromNBT( final NBTTagCompound i )
{ {
if( i == null ) if( i == null )
{ {
return null; return null;
} }
final ItemStack itemstack = new ItemStack( i ); final ItemStack itemstack = new ItemStack( i );
if( itemstack.isEmpty() ) if( itemstack.isEmpty() )
{ {
return null; return null;
} }
final AEItemStack item = AEItemStack.fromItemStack( itemstack ); final AEItemStack item = AEItemStack.fromItemStack( itemstack );
item.setStackSize( i.getLong( "Cnt" ) ); item.setStackSize( i.getLong( "Cnt" ) );
item.setCountRequestable( i.getLong( "Req" ) ); item.setCountRequestable( i.getLong( "Req" ) );
item.setCraftable( i.getBoolean( "Craft" ) ); item.setCraftable( i.getBoolean( "Craft" ) );
return item; return item;
} }
@Override @Override
public void writeToNBT( final NBTTagCompound i ) public void writeToNBT( final NBTTagCompound i )
{ {
this.getDefinition().writeToNBT( i ); this.getDefinition().writeToNBT( i );
i.setLong( "Cnt", this.getStackSize() ); i.setLong( "Cnt", this.getStackSize() );
i.setLong( "Req", this.getCountRequestable() ); i.setLong( "Req", this.getCountRequestable() );
i.setBoolean( "Craft", this.isCraftable() ); i.setBoolean( "Craft", this.isCraftable() );
} }
public static AEItemStack fromPacket( final ByteBuf data ) public static AEItemStack fromPacket( final ByteBuf data )
{ {
final byte mask = data.readByte(); final byte mask = data.readByte();
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 ); final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 ); final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0; final boolean isCraftable = ( mask & 0x40 ) > 0;
final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) ); final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) );
final long stackSize = getPacketValue( stackType, data ); final long stackSize = getPacketValue( stackType, data );
final long countRequestable = getPacketValue( countReqType, data ); final long countRequestable = getPacketValue( countReqType, data );
if( itemstack.isEmpty() ) if( itemstack.isEmpty() )
{ {
return null; return null;
} }
final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize ); final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize );
item.setCountRequestable( countRequestable ); item.setCountRequestable( countRequestable );
item.setCraftable( isCraftable ); item.setCraftable( isCraftable );
return item; return item;
} }
@Override @Override
public void writeToPacket( final ByteBuf i ) public void writeToPacket( final ByteBuf i )
{ {
final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this
.getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 ); .getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 );
i.writeByte( mask ); i.writeByte( mask );
ByteBufUtils.writeTag( i, this.getDefinition().serializeNBT() ); ByteBufUtils.writeTag( i, this.getDefinition().serializeNBT() );
this.putPacketValue( i, this.getStackSize() ); this.putPacketValue( i, this.getStackSize() );
this.putPacketValue( i, this.getCountRequestable() ); this.putPacketValue( i, this.getCountRequestable() );
} }
@Override /**
public void add( final IAEItemStack option ) * We're assuming that using capNBT here is safe, because {@link #getDefinition()} should have been created by
{ * {@link ItemStack#copy()}, and then never mutated. Copying an item stack will automatically serialize the
if( option == null ) * capabilities of the source stack and initialize the target stacks capNBT field using that tag, which we are then
{ * reusing here.
return; */
}
this.incStackSize( option.getStackSize() ); @Override
this.setCountRequestable( this.getCountRequestable() + option.getCountRequestable() ); public void add(final IAEItemStack option) {
this.setCraftable( this.isCraftable() || option.isCraftable() ); if (option == null) {
} return;
}
@Override this.incStackSize(option.getStackSize());
public boolean fuzzyComparison( final IAEItemStack other, final FuzzyMode mode ) this.setCountRequestable(this.getCountRequestable() + option.getCountRequestable());
{ this.setCraftable(this.isCraftable() || option.isCraftable());
if( mode == FuzzyMode.IGNORE_ALL && OreHelper.INSTANCE.sameOre( this, other ) ) }
{
return true;
}
final ItemStack itemStack = this.getDefinition(); @Override
final ItemStack otherStack = other.getDefinition(); public boolean fuzzyComparison(final IAEItemStack other, final FuzzyMode mode) {
final ItemStack itemStack = this.getDefinition();
final ItemStack otherStack = other.getDefinition();
return this.fuzzyItemStackComparison( itemStack, otherStack, mode ); return this.fuzzyItemStackComparison(itemStack, otherStack, mode);
} }
@Override @Override
public IAEItemStack copy() public IAEItemStack copy() {
{ return new AEItemStack(this);
return new AEItemStack( this ); }
}
@Override @Override
public boolean isItem() public IStorageChannel<IAEItemStack> getChannel() {
{ return AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class);
return true; }
}
@Override @Override
public boolean isFluid() public ItemStack createItemStack() {
{ return ItemHandlerHelper.copyStackWithSize(this.getDefinition(),
return false; (int) Math.min(Integer.MAX_VALUE, this.getStackSize()));
} }
@Override @Override
public IStorageChannel<IAEItemStack> getChannel() public Item getItem() {
{ return this.getDefinition().getItem();
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); }
}
@Override @Override
public ItemStack createItemStack() public int getItemDamage() {
{ return this.sharedStack.getItemDamage();
return ItemHandlerHelper.copyStackWithSize( this.getDefinition(), (int) Math.min( Integer.MAX_VALUE, this.getStackSize() ) ); }
}
@Override public Optional<OreReference> getOre()
public Item getItem() {
{ return this.oreReference;
return this.getDefinition().getItem(); }
}
@Override @Override
public int getItemDamage() public boolean sameOre( final IAEItemStack is )
{ {
return this.sharedStack.getItemDamage(); return OreHelper.INSTANCE.sameOre( this, is );
} }
@Override @Override
public boolean sameOre( final IAEItemStack is ) public boolean isSameType(final IAEItemStack otherStack) {
{ if (otherStack == null) {
return OreHelper.INSTANCE.sameOre( this, is ); return false;
} }
@Override return Objects.equals(this.sharedStack, ((AEItemStack) otherStack).sharedStack);
public boolean isSameType( final IAEItemStack otherStack ) }
{
if( otherStack == null )
{
return false;
}
return Objects.equals( this.sharedStack, ( (AEItemStack) otherStack ).sharedStack ); @Override
} public boolean isSameType(final ItemStack otherStack) {
if (otherStack.isEmpty()) {
return false;
}
int oldSize = otherStack.getCount();
@Override otherStack.setCount(1);
public boolean isSameType( final ItemStack otherStack ) boolean ret = ItemStack.areItemStacksEqual(this.getDefinition(), otherStack);
{ otherStack.setCount(oldSize);
if( otherStack.isEmpty() )
{
return false;
}
int oldSize = otherStack.getCount();
otherStack.setCount( 1 ); return ret;
boolean ret = ItemStack.areItemStacksEqual( this.getDefinition(), otherStack ); }
otherStack.setCount( oldSize );
return ret; @Override
} public int hashCode() {
return this.sharedStack.hashCode();
}
@Override @Override
public int hashCode() public boolean equals(final Object ia) {
{ if (ia instanceof AEItemStack) {
return this.sharedStack.hashCode(); return this.isSameType((AEItemStack) ia);
} } else if (ia instanceof ItemStack) {
// this actually breaks the equals contract (being equals to unrelated classes)
return equals((ItemStack) ia);
}
return false;
}
@Override @Override
public boolean equals( final Object ia ) public String toString() {
{ return this.getStackSize() + "x" + this.getDefinition().getItem().getRegistryName();
if( ia instanceof AEItemStack ) }
{
return this.isSameType( (AEItemStack) ia );
}
else if( ia instanceof ItemStack )
{
return this.isSameType( (ItemStack) ia );
}
return false;
}
@Override @SideOnly( Side.CLIENT )
public String toString() public List<String> getToolTip() {
{ if (this.tooltip == null) {
return this.getStackSize() + "x" + this.getDefinition().getItem().getUnlocalizedName() + "@" + this.getDefinition().getItemDamage(); this.tooltip = Platform.getTooltip(this.asItemStackRepresentation());
} }
return this.tooltip;
}
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
public List<String> getToolTip() public String getDisplayName() {
{ if (this.displayName == null) {
if( this.tooltip == null ) this.displayName = Platform.getItemDisplayName(this.asItemStackRepresentation());
{ }
this.tooltip = Platform.getTooltip( this.asItemStackRepresentation() ); return this.displayName;
} }
return this.tooltip;
}
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
public String getDisplayName() public String getModID() {
{ return this.getDefinition().getItem().getRegistryName().getResourceDomain();
if( this.displayName == null ) }
{
this.displayName = Platform.getItemDisplayName( this.asItemStackRepresentation() );
}
return this.displayName;
}
@SideOnly( Side.CLIENT ) @Override
public String getModID() public boolean hasTagCompound() {
{ return this.getDefinition().hasTagCompound();
if( this.uniqueID == null ) }
{
this.uniqueID = Item.REGISTRY.getNameForObject( this.getDefinition().getItem() );
}
if( this.uniqueID == null ) @Override
{ public ItemStack asItemStackRepresentation() {
return "** Null"; return this.getDefinition().copy();
} }
return this.uniqueID.getResourceDomain() == null ? "** Null" : this.uniqueID.getResourceDomain(); @Override
} public ItemStack getDefinition() {
return this.sharedStack.getDefinition();
}
public Optional<OreReference> getOre() public boolean equals(final ItemStack is) {
{ return this.isSameType(is);
return this.oreReference; }
}
@Override AESharedItemStack getSharedStack() {
public boolean hasTagCompound() return this.sharedStack;
{ }
return this.getDefinition().hasTagCompound();
}
@Override private boolean fuzzyItemStackComparison(ItemStack a, ItemStack b, FuzzyMode mode) {
public ItemStack asItemStackRepresentation() if (a.getItem() == b.getItem()) {
{ if (a.getItem().isDamageable()) {
return this.getDefinition().copy(); if (mode == FuzzyMode.IGNORE_ALL) {
} return true;
} else if (mode == FuzzyMode.PERCENT_99) {
return (a.getItemDamage() > 1) == (b.getItemDamage() > 1);
} else {
final float percentDamageOfA = (float) a.getItemDamage() / a.getMaxDamage();
final float percentDamageOfB = (float) b.getItemDamage() / b.getMaxDamage();
@Override return (percentDamageOfA > mode.breakPoint) == (percentDamageOfB > mode.breakPoint);
public ItemStack getDefinition() }
{ }
return this.sharedStack.getDefinition(); }
}
AESharedItemStack getSharedStack()
{
return this.sharedStack;
}
private boolean fuzzyItemStackComparison( ItemStack a, ItemStack b, FuzzyMode mode )
{
if( a.getItem() == b.getItem() )
{
if( a.getItem().isDamageable() )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
}
else
{
final float percentDamageOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamageOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
return a.getMetadata() == b.getMetadata();
}
return false;
}
return false;
}
} }
@@ -23,7 +23,6 @@
package appeng.util.item; package appeng.util.item;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@@ -31,56 +30,34 @@ import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import appeng.util.Platform; public final class AEItemStackRegistry {
private static final WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> REGISTRY = new WeakHashMap<>();
private AEItemStackRegistry() {
}
public final class AEItemStackRegistry static synchronized AESharedItemStack getRegisteredStack(final @Nonnull ItemStack itemStack) {
{ if (itemStack.isEmpty()) {
private static final WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> SERVER_REGISTRY = new WeakHashMap<>(); throw new IllegalArgumentException("stack cannot be empty");
private static final WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> CLIENT_REGISTRY = new WeakHashMap<>(); }
private AEItemStackRegistry() int oldStackSize = itemStack.getCount();
{ itemStack.setCount(1);
}
private static WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> registry() AESharedItemStack search = new AESharedItemStack(itemStack);
{ WeakReference<AESharedItemStack> weak = REGISTRY.get(search);
if( Platform.isClient() ) AESharedItemStack ret = null;
{
return CLIENT_REGISTRY;
}
else
{
return SERVER_REGISTRY;
}
}
static synchronized AESharedItemStack getRegisteredStack( final @Nonnull ItemStack itemStack ) if (weak != null) {
{ ret = weak.get();
if( itemStack.isEmpty() ) }
{
throw new IllegalArgumentException( "stack cannot be empty" );
}
int oldStackSize = itemStack.getCount(); if (ret == null) {
itemStack.setCount( 1 ); ret = new AESharedItemStack(itemStack.copy());
REGISTRY.put(ret, new WeakReference<>(ret));
}
itemStack.setCount(oldStackSize);
AESharedItemStack search = new AESharedItemStack( itemStack ); return ret;
WeakReference<AESharedItemStack> weak = registry().get( search ); }
AESharedItemStack ret = null;
if( weak != null )
{
ret = weak.get();
}
if( ret == null )
{
ret = new AESharedItemStack( itemStack.copy() );
registry().put( ret, new WeakReference<>( ret ) );
}
itemStack.setCount( oldStackSize );
return ret;
}
} }
@@ -18,7 +18,6 @@
package appeng.util.item; package appeng.util.item;
import java.util.Objects; import java.util.Objects;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
@@ -33,32 +32,32 @@ final class AESharedItemStack {
private final int itemDamage; private final int itemDamage;
private final int hashCode; private final int hashCode;
private final ItemStack itemStack; public AESharedItemStack(final ItemStack itemStack) {
private final int itemId; this(itemStack, itemStack.getItemDamage());
private final int itemDamage; }
private final int hashCode;
public AESharedItemStack( final ItemStack itemStack ) /**
{ * A constructor to explicitly set the damage value and not fetch it from the {@link ItemStack}
this.itemStack = itemStack; *
this.itemId = Item.getIdFromItem( itemStack.getItem() ); * @param itemStack The {@link ItemStack} to filter
this.itemDamage = itemStack.getItemDamage(); * @param damage The damage of the item
this.hashCode = this.makeHashCode(); */
} private AESharedItemStack(ItemStack itemStack, int damage) {
this.itemStack = itemStack;
this.itemId = Item.getIdFromItem(itemStack.getItem());
this.itemDamage = damage;
Bounds getBounds( final FuzzyMode fuzzy, final boolean ignoreMeta ) // Ensure this is always called last.
{ this.hashCode = this.makeHashCode();
return new Bounds( this.itemStack, fuzzy, ignoreMeta ); }
}
ItemStack getDefinition() { ItemStack getDefinition() {
return this.itemStack; return this.itemStack;
} }
int getItemID() int getItemDamage() {
{ return this.itemDamage;
return this.itemId; }
}
@Override @Override
public int hashCode() { public int hashCode() {
@@ -88,7 +87,7 @@ final class AESharedItemStack {
return Objects.hash( return Objects.hash(
this.itemId, this.itemId,
this.itemDamage, this.itemDamage,
this.itemStack.hasTag() ? this.itemStack.getTag() : 0); this.itemStack.hasTagCompound() ? this.itemStack.getTagCompound() : 0);
} }
} }
+126 -143
View File
@@ -18,169 +18,152 @@
package appeng.util.item; package appeng.util.item;
import appeng.api.storage.data.IAEStack;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import appeng.api.storage.data.IAEStack;
public abstract class AEStack<T extends IAEStack<T>> implements IAEStack<T> {
public abstract class AEStack<StackType extends IAEStack<StackType>> implements IAEStack<StackType> private boolean isCraftable;
{ private long stackSize;
private long countRequestable;
private boolean isCraftable; @Override
private long stackSize; public long getStackSize() {
private long countRequestable; return this.stackSize;
}
protected static long getPacketValue( final byte type, final ByteBuf tag ) @Override
{ public T setStackSize(final long ss) {
if( type == 0 ) this.stackSize = ss;
{ return (T) this;
long l = tag.readByte(); }
l -= Byte.MIN_VALUE;
return l;
}
else if( type == 1 )
{
long l = tag.readShort();
l -= Short.MIN_VALUE;
return l;
}
else if( type == 2 )
{
long l = tag.readInt();
l -= Integer.MIN_VALUE;
return l;
}
return tag.readLong(); @Override
} public long getCountRequestable() {
return this.countRequestable;
}
@Override @Override
public long getStackSize() public T setCountRequestable(final long countRequestable) {
{ this.countRequestable = countRequestable;
return this.stackSize; return (T) this;
} }
@Override @Override
public StackType setStackSize( final long ss ) public boolean isCraftable() {
{ return this.isCraftable;
this.stackSize = ss; }
return (StackType) this;
}
@Override @Override
public long getCountRequestable() public T setCraftable(final boolean isCraftable) {
{ this.isCraftable = isCraftable;
return this.countRequestable; return (T) this;
} }
@Override @Override
public StackType setCountRequestable( final long countRequestable ) public T reset() {
{ this.stackSize = 0;
this.countRequestable = countRequestable; this.setCountRequestable(0);
return (StackType) this; this.setCraftable(false);
} return (T) this;
}
@Override @Override
public boolean isCraftable() public T empty() {
{ final T dup = this.copy();
return this.isCraftable; dup.reset();
} return dup;
}
@Override @Override
public StackType setCraftable( final boolean isCraftable ) public boolean isMeaningful() {
{ return this.stackSize != 0 || this.countRequestable > 0 || this.isCraftable;
this.isCraftable = isCraftable; }
return (StackType) this;
}
@Override @Override
public StackType reset() public void incStackSize(final long i) {
{ this.stackSize += i;
this.stackSize = 0; }
// priority = Integer.MIN_VALUE;
this.setCountRequestable( 0 );
this.setCraftable( false );
return (StackType) this;
}
@Override @Override
public StackType empty() public void decStackSize(final long i) {
{ this.stackSize -= i;
final StackType dup = this.copy(); }
dup.reset();
return dup;
}
@Override @Override
public boolean isMeaningful() public void incCountRequestable(final long i) {
{ this.countRequestable += i;
return this.stackSize != 0 || this.countRequestable > 0 || this.isCraftable; }
}
@Override @Override
public void incStackSize( final long i ) public void decCountRequestable(final long i) {
{ this.countRequestable -= i;
this.stackSize += i; }
}
@Override protected abstract boolean hasTagCompound();
public void decStackSize( final long i )
{
this.stackSize -= i;
}
@Override protected static long getPacketValue( final byte type, final ByteBuf tag )
public void incCountRequestable( final long i ) {
{ if( type == 0 )
this.countRequestable += i; {
} long l = tag.readByte();
l -= Byte.MIN_VALUE;
return l;
}
else if( type == 1 )
{
long l = tag.readShort();
l -= Short.MIN_VALUE;
return l;
}
else if( type == 2 )
{
long l = tag.readInt();
l -= Integer.MIN_VALUE;
return l;
}
@Override return tag.readLong();
public void decCountRequestable( final long i ) }
{
this.countRequestable -= i;
}
protected byte getType( final long num ) protected void putPacketValue( final ByteBuf tag, final long num )
{ {
if( num <= 255 ) if( num <= 255 )
{ {
return 0; tag.writeByte( (byte) ( num + Byte.MIN_VALUE ) );
} }
else if( num <= 65535 ) else if( num <= 65535 )
{ {
return 1; tag.writeShort( (short) ( num + Short.MIN_VALUE ) );
} }
else if( num <= 4294967295L ) else if( num <= 4294967295L )
{ {
return 2; tag.writeInt( (int) ( num + Integer.MIN_VALUE ) );
} }
else else
{ {
return 3; tag.writeLong( num );
} }
} }
protected abstract boolean hasTagCompound(); protected byte getType( final long num )
{
protected void putPacketValue( final ByteBuf tag, final long num ) if( num <= 255 )
{ {
if( num <= 255 ) return 0;
{ }
tag.writeByte( (byte) ( num + Byte.MIN_VALUE ) ); else if( num <= 65535 )
} {
else if( num <= 65535 ) return 1;
{ }
tag.writeShort( (short) ( num + Short.MIN_VALUE ) ); else if( num <= 4294967295L )
} {
else if( num <= 4294967295L ) return 2;
{ }
tag.writeInt( (int) ( num + Integer.MIN_VALUE ) ); else
} {
else return 3;
{ }
tag.writeLong( num ); }
}
}
} }
@@ -145,14 +145,14 @@ class FuzzyItemVariantList extends ItemVariantList {
* higher number than the upper bound. * higher number than the upper bound.
*/ */
static ItemDamageBound makeLowerBound(final ItemStack stack, final FuzzyMode fuzzy) { static ItemDamageBound makeLowerBound(final ItemStack stack, final FuzzyMode fuzzy) {
Preconditions.checkState(stack.isDamageable(), "ItemStack#isDamageable() has to be true"); Preconditions.checkState(((stack.getMaxDamage() == 0 && stack.getItemDamage() > 0 ) || stack.isItemStackDamageable()), "ItemStack#isDamageable() has to be true");
int damage; int damage;
if (fuzzy == FuzzyMode.IGNORE_ALL) { if (fuzzy == FuzzyMode.IGNORE_ALL) {
damage = stack.getMaxDamage(); damage = stack.getMaxDamage();
} else { } else {
final int breakpoint = fuzzy.calculateBreakPoint(stack.getMaxDamage()); final int breakpoint = fuzzy.calculateBreakPoint(stack.getMaxDamage());
damage = stack.getDamage() <= breakpoint ? breakpoint : stack.getMaxDamage(); damage = stack.getItemDamage() <= breakpoint ? breakpoint : stack.getMaxDamage();
} }
return new ItemDamageBound(damage); return new ItemDamageBound(damage);
@@ -163,14 +163,14 @@ class FuzzyItemVariantList extends ItemVariantList {
* lower number than the lower bound. It also is exclusive. * lower number than the lower bound. It also is exclusive.
*/ */
static ItemDamageBound makeUpperBound(final ItemStack stack, final FuzzyMode fuzzy) { static ItemDamageBound makeUpperBound(final ItemStack stack, final FuzzyMode fuzzy) {
Preconditions.checkState(stack.isDamageable(), "ItemStack#isDamageable() has to be true"); Preconditions.checkState(((stack.getMaxDamage() == 0 && stack.getItemDamage() > 0 ) || stack.isItemStackDamageable()), "ItemStack#isDamageable() has to be true");
int damage; int damage;
if (fuzzy == FuzzyMode.IGNORE_ALL) { if (fuzzy == FuzzyMode.IGNORE_ALL) {
damage = MIN_DAMAGE_VALUE; damage = MIN_DAMAGE_VALUE;
} else { } else {
final int breakpoint = fuzzy.calculateBreakPoint(stack.getMaxDamage()); final int breakpoint = fuzzy.calculateBreakPoint(stack.getMaxDamage());
damage = stack.getDamage() <= breakpoint ? MIN_DAMAGE_VALUE : breakpoint; damage = stack.getItemDamage() <= breakpoint ? MIN_DAMAGE_VALUE : breakpoint;
} }
return new ItemDamageBound(damage); return new ItemDamageBound(damage);
+38 -43
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Applied Energistics 2. * This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved. * Copyright (c) 2013 - 2020, AlgorithmX2, All rights reserved.
* *
* Applied Energistics 2 is free software: you can redistribute it and/or modify * Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
@@ -18,8 +18,6 @@
package appeng.util.item; package appeng.util.item;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.ConcurrentModificationException; import java.util.ConcurrentModificationException;
@@ -27,13 +25,16 @@ import java.util.Iterator;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import net.minecraftforge.oredict.OreDictionary; import net.minecraft.item.Item;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.util.item.AESharedItemStack.Bounds;
public final class ItemList implements IItemList<IAEItemStack> {
private final Reference2ObjectMap<Item, ItemVariantList> records = new Reference2ObjectOpenHashMap<>(); private final Reference2ObjectMap<Item, ItemVariantList> records = new Reference2ObjectOpenHashMap<>();
/** /**
@@ -53,18 +54,20 @@ import appeng.util.item.AESharedItemStack.Bounds;
return record != null ? record.findPrecise(itemStack) : null; return record != null ? record.findPrecise(itemStack) : null;
} }
if( st != null ) @Override
{ public Collection<IAEItemStack> findFuzzy(final IAEItemStack filter, final FuzzyMode fuzzy) {
st.add( option ); if (filter == null) {
return; return Collections.emptyList();
} }
ItemVariantList record = this.records.get(filter.getItem()); ItemVariantList record = this.records.get(filter.getItem());
return record != null ? record.findFuzzy(filter, fuzzy) : Collections.emptyList(); return record != null ? record.findFuzzy(filter, fuzzy) : Collections.emptyList();
} }
this.putItemRecord( opt ); @Override
} public boolean isEmpty() {
return !this.iterator().hasNext();
}
@Override @Override
public void add(final IAEItemStack itemStack) { public void add(final IAEItemStack itemStack) {
@@ -74,8 +77,8 @@ import appeng.util.item.AESharedItemStack.Bounds;
return; return;
} }
return this.records.get( ( (AEItemStack) itemStack ).getSharedStack() ); this.getOrCreateRecord(itemStack.getItem()).add(itemStack);
} }
@Override @Override
public void addStorage(final IAEItemStack itemStack) { public void addStorage(final IAEItemStack itemStack) {
@@ -85,7 +88,8 @@ import appeng.util.item.AESharedItemStack.Bounds;
return; return;
} }
final AEItemStack ais = (AEItemStack) filter; this.getOrCreateRecord(itemStack.getItem()).addStorage(itemStack);
}
@Override @Override
public void addCrafting(final IAEItemStack itemStack) { public void addCrafting(final IAEItemStack itemStack) {
@@ -95,11 +99,8 @@ import appeng.util.item.AESharedItemStack.Bounds;
return; return;
} }
return this.findFuzzyDamage( is, fuzzy, is.getItemDamage() == OreDictionary.WILDCARD_VALUE ); this.getOrCreateRecord(itemStack.getItem()).addCrafting(itemStack);
} }
else
{
final Collection<IAEItemStack> output = new ArrayList<>();
@Override @Override
public void addRequestable(final IAEItemStack itemStack) { public void addRequestable(final IAEItemStack itemStack) {
@@ -109,24 +110,17 @@ import appeng.util.item.AESharedItemStack.Bounds;
return; return;
} }
return output; this.getOrCreateRecord(itemStack.getItem()).addRequestable(itemStack);
} }
} ).orElse( this.findFuzzyDamage( ais, fuzzy, false ) );
}
@Override @Override
public boolean isEmpty() public IAEItemStack getFirstItem() {
{ for (final IAEItemStack stackType : this) {
return !this.iterator().hasNext(); return stackType;
} }
@Override return null;
public void addStorage( final IAEItemStack option ) }
{
if( option == null )
{
return;
}
@Override @Override
public int size() { public int size() {
@@ -135,19 +129,20 @@ import appeng.util.item.AESharedItemStack.Bounds;
size += entry.size(); size += entry.size();
} }
if( st != null ) return size;
{ }
st.incStackSize( option.getStackSize() );
return;
}
@Override @Override
public Iterator<IAEItemStack> iterator() { public Iterator<IAEItemStack> iterator() {
return new ChainedIterator(this.records.values().iterator(), version); return new ChainedIterator(this.records.values().iterator(), version);
} }
this.putItemRecord( opt ); @Override
} public void resetStatus() {
for (final IAEItemStack i : this) {
i.reset();
}
}
private ItemVariantList getOrCreateRecord(Item item) { private ItemVariantList getOrCreateRecord(Item item) {
return this.records.computeIfAbsent(item, this::makeRecordMap); return this.records.computeIfAbsent(item, this::makeRecordMap);
@@ -43,13 +43,11 @@ public class MeaningfulItemIterator<T extends IAEItemStack> implements Iterator<
return this.next != null; return this.next != null;
} }
@Override @Override
public T next() public T next() {
{ if (this.next == null) {
if( this.next == null ) throw new NoSuchElementException();
{ }
throw new NoSuchElementException();
}
T result = this.next; T result = this.next;
this.next = this.seekNext(); this.next = this.seekNext();