Compare commits

...

21 Commits

Author SHA1 Message Date
fscan fa2b4fabc7 Fix ConcurrentModificatonException in NetworkEventBus (#3660) 2018-08-01 00:35:44 +02:00
Saereth f8d5f4ddb1 Fixes #3478: Changes the way xp drops from Certus Ore blocks (#3482) 2018-06-26 23:36:21 +02:00
fscan f8dfa2619e Fixes #3535: Prevent crash when either quartz types are disabled (#3542)
* Fixes crash when either quartz types are disabled and prevent cascading worldgen.
* Also fixes  #3486
2018-06-26 15:31:03 +02:00
fscan c1d1dc947f Fixes #3548: AEBaseTile now respect overridden markDirty implementations. (#3550) 2018-06-26 10:33:56 +02:00
fscan 6bb465be0b Fixes #3449: Prevent CellInventory#getCell() from mutating the cell itemstack definition (#3552)
CellInventory#getCell() initalizes the ItemStack with an empty NBT and therefore was messing with the item definition.
2018-06-26 10:32:58 +02:00
fscan 8902af9766 Fixes #3459: Open the inventory if raytrace misses (#3549) 2018-06-26 10:31:17 +02:00
fscan 2b592dd40e Fixes DriveBakedModel to not crash when SLOT_STATE is null (#3545)
Uses a null object in case the TE is not available for whichever reason.
2018-06-18 19:03:28 +02:00
fscan 41e7558b24 Fixes interface shift-clicking to generate correct onChangeInventory events (#3544) 2018-06-18 19:01:17 +02:00
Kyle VanderBeek 3e09c49e03 Remove call to neighborChanged() (#3497)
Fixes #3462
2018-05-27 20:46:08 +02:00
yueh 9481c9a7d7 Fixes #3428: Invalidate container when the corresponding TE no longer exists. (#3433) 2018-03-22 13:52:07 +01:00
yueh ccefb47581 Added a config option to disable the CraftingManager fallback. (#3415) 2018-03-08 16:44:48 +01:00
yueh 59af05aeb1 Fixes #3417: Avoid creating ItemStacks when injecting them into a cell. (#3418) 2018-03-08 16:38:00 +01:00
yueh b32834e2b3 Fixes #3411: Limit patterns without substitute to precise operations. (#3413)
This will no longer ignore NBT data when searching for an itemstack,
thus less likely to trigger the CraftingManager fallback.
2018-03-08 16:35:13 +01:00
yueh 6c7cbb7ee1 Added a simple warning to patterns when using CraftingManager fallback. (#3412) 2018-03-08 16:34:48 +01:00
yueh 84c065ff28 Fixes #3394: Use cache to avoid using removed IItemHandler (#3395) 2018-03-04 14:33:45 +01:00
yueh c9b92a81a3 Fixes #3405: Use cached tooltip for search, then copy craftable as zero. (#3406) 2018-03-04 14:33:23 +01:00
yueh eed4776c6f Fixes #3389: Prevent inventory cache from becoming unmatched. (#3390)
Use slightly faster ArrayDeqeue instead of LinkedList.
Check boolean fields before more complex datatypes
2018-02-17 19:10:09 +01:00
yueh 22807bc619 Updated maven repos. (#3391) 2018-02-16 18:43:09 +01:00
Florian Scandella ae352c093e fix typo in AEItemStack#fuzzyComparison 2018-02-10 19:02:32 +01:00
yueh 36d6681eac Rework fuzzy comparison for 99 percent threshold (#3367)
* Rework fuzzy comparison for 99 percent threshold

The current implementation is quite convoluted and can handle 99%
incorrectly when items exceed a certain damage range.

* Use metadata explicitly for comparison

Some item could use metadata to pack damageable and undamageable items
into the same id. Thus could lead to get ItemStack#getItemDamage() to
return bogus values for undamageable items.
2018-02-05 15:20:02 +01:00
yueh 6cffe93970 Fixes #3370: Avoid caching the model for facades locally. (#3371) 2018-02-05 15:19:20 +01:00
25 changed files with 298 additions and 337 deletions
+8 -3
View File
@@ -31,7 +31,7 @@ repositories {
maven {
name = "Tesla repo"
url "http://maven.epoxide.xyz"
url "http://maven.mcmoddev.com"
}
maven {
@@ -48,7 +48,7 @@ repositories {
name 'tterrag maven'
url "http://maven.tterrag.com/"
}
maven { // McJtyLib
name 'mcjty'
url "http://maven.k-4u.nl/"
@@ -58,11 +58,16 @@ repositories {
name 'tehnut'
url "http://tehnut.info/maven"
}
maven { // CraftTweaker
name 'jared maven'
url "http://maven.blamejared.com/"
}
maven { // modmaven, maven proxy
name 'modmaven'
url "https://modmaven.k-4u.nl/"
}
}
configurations {
@@ -74,13 +74,8 @@ public class BlockDrive extends AEBaseTileBlock
public IBlockState getExtendedState( IBlockState state, IBlockAccess world, BlockPos pos )
{
TileDrive te = this.getTileEntity( world, pos );
if( te == null )
{
return super.getExtendedState( state, world, pos );
}
IExtendedBlockState extState = (IExtendedBlockState) super.getExtendedState( state, world, pos );
return extState.withProperty( SLOTS_STATE, DriveSlotsState.fromChestOrDrive( te ) );
return extState.withProperty( SLOTS_STATE, te == null ? DriveSlotsState.createEmpty( 10 ) : DriveSlotsState.fromChestOrDrive( te ) );
}
@Override
@@ -75,4 +75,14 @@ public class DriveSlotsState
}
return new DriveSlotsState( slots );
}
public static DriveSlotsState createEmpty( int slotCount )
{
DriveSlotState[] slots = new DriveSlotState[slotCount];
for( int i = 0; i < slotCount; i++ )
{
slots[i] = DriveSlotState.EMPTY;
}
return new DriveSlotsState( slots );
}
}
+20 -14
View File
@@ -21,6 +21,7 @@ package appeng.client.me;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
@@ -112,6 +113,8 @@ public class ItemRepo
final Enum viewMode = this.sortSrc.getSortDisplay();
final Enum searchMode = AEConfig.instance().getConfigManager().getSetting( Settings.SEARCH_MODE );
final boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE;
if( searchMode == SearchBoxMode.JEI_AUTOSEARCH || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH || searchMode == SearchBoxMode.JEI_AUTOSEARCH_KEEP || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH_KEEP )
{
this.updateJEI( this.searchString );
@@ -160,43 +163,46 @@ public class ItemRepo
continue;
}
if( viewMode == ViewItems.CRAFTABLE )
{
is = is.copy();
is.setStackSize( 0 );
}
if( viewMode == ViewItems.STORED && is.getStackSize() == 0 )
{
continue;
}
final String dspName = searchMod ? Platform.getModId( is ) : Platform.getItemDisplayName( is );
boolean foundMatchingItemStack = false;
notDone = true;
if( m.matcher( dspName.toLowerCase() ).find() )
{
this.view.add( is );
notDone = false;
foundMatchingItemStack = true;
}
if( terminalSearchToolTips && notDone && !searchMod )
{
for( final Object lp : Platform.getTooltip( is ) )
final List<String> tooltip = Platform.getTooltip( is );
for( final String line : tooltip )
{
if( lp instanceof String && m.matcher( (CharSequence) lp ).find() )
if( m.matcher( line ).find() )
{
this.view.add( is );
foundMatchingItemStack = true;
notDone = false;
break;
}
}
}
/*
* if ( terminalSearchMods && notDone ) { if ( m.matcher( Platform.getMod( is.getItemStack() ) ).find() ) {
* view.add( is ); notDone = false; } }
*/
if( foundMatchingItemStack )
{
if( needsZeroCopy )
{
is = is.copy();
is.setStackSize( 0 );
}
this.view.add( is );
}
}
final Enum SortBy = this.sortSrc.getSortBy();
@@ -43,22 +43,16 @@ public class FacadeItemModel implements IModel
// We use this to get the default item transforms and make our lives easier
private static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/facade_base" );
private IModel baseModel = null;
private IModel getBaseModel()
{
if( this.baseModel == null )
try
{
try
{
baseModel = ModelLoaderRegistry.getModel( MODEL_BASE );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
return ModelLoaderRegistry.getModel( MODEL_BASE );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
return this.baseModel;
}
@Override
@@ -84,6 +78,6 @@ public class FacadeItemModel implements IModel
@Override
public IModelState getDefaultState()
{
return getBaseModel().getDefaultState();
return this.getBaseModel().getDefaultState();
}
}
@@ -356,6 +356,11 @@ public abstract class AEBaseContainer extends Container
if( Platform.isServer() )
{
if( this.tileEntity != null && this.tileEntity.getWorld().getTileEntity( this.tileEntity.getPos() ) != this.tileEntity )
{
this.setValidContainer( false );
}
for( final IContainerListener listener : this.listeners )
{
for( final SyncData sd : this.syncData.values() )
@@ -431,6 +436,8 @@ public abstract class AEBaseContainer extends Container
}
else
{
tis = tis.copy();
// target slots in the container...
for( final Object inventorySlot : this.inventorySlots )
{
@@ -491,7 +498,7 @@ public abstract class AEBaseContainer extends Container
{
if( d.getHasStack() )
{
final ItemStack t = d.getStack();
final ItemStack t = d.getStack().copy();
if( Platform.itemComparisons().isSameItem( tis, t ) ) // t.isItemEqual(tis))
{
@@ -511,6 +518,8 @@ public abstract class AEBaseContainer extends Container
t.setCount( t.getCount() + placeAble );
tis.setCount( tis.getCount() - placeAble );
d.putStack( t );
if( tis.getCount() <= 0 )
{
clickSlot.putStack( ItemStack.EMPTY );
@@ -543,7 +552,7 @@ public abstract class AEBaseContainer extends Container
{
if( d.getHasStack() )
{
final ItemStack t = d.getStack();
final ItemStack t = d.getStack().copy();
if( Platform.itemComparisons().isSameItem( t, tis ) )
{
@@ -563,6 +572,8 @@ public abstract class AEBaseContainer extends Container
t.setCount( t.getCount() + placeAble );
tis.setCount( tis.getCount() - placeAble );
d.putStack( t );
if( tis.getCount() <= 0 )
{
clickSlot.putStack( ItemStack.EMPTY );
@@ -621,7 +632,7 @@ public abstract class AEBaseContainer extends Container
}
}
clickSlot.putStack( !tis.isEmpty() ? tis.copy() : ItemStack.EMPTY );
clickSlot.putStack( !tis.isEmpty() ? tis : ItemStack.EMPTY );
}
this.updateSlot( clickSlot );
@@ -148,11 +148,6 @@ public class ContainerCellWorkbench extends ContainerUpgradeable
final ItemStack is = this.workBench.getInventoryByName( "cell" ).getStackInSlot( 0 );
if( Platform.isServer() )
{
if( this.workBench.getWorld().getTileEntity( this.workBench.getPos() ) != this.workBench )
{
this.setValidContainer( false );
}
for( final IContainerListener listener : this.listeners )
{
if( this.prevStack != is )
+3 -1
View File
@@ -213,7 +213,9 @@ public final class AEConfig extends Configuration implements IConfigurableObject
{
if( feature.isVisible() )
{
if( this.get( "Features." + feature.category(), feature.key(), feature.isEnabled() ).getBoolean( feature.isEnabled() ) )
final Property option = this.get( "Features." + feature.category(), feature.key(), feature.isEnabled(), feature.comment() );
if( option.getBoolean( feature.isEnabled() ) )
{
this.featureFlags.add( feature );
}
@@ -155,6 +155,7 @@ public enum AEFeature
MOLECULAR_ASSEMBLER( "MolecularAssembler", Constants.CATEGORY_CRAFTING_FEATURES ),
PATTERNS( "Patterns", Constants.CATEGORY_CRAFTING_FEATURES ),
CRAFTING_CPU( "CraftingCPU", Constants.CATEGORY_CRAFTING_FEATURES ),
CRAFTING_MANAGER_FALLBACK( "CraftingManagerFallback", Constants.CATEGORY_CRAFTING_FEATURES, "Use CraftingManager to find an alternative recipe, after a pattern rejected an ingredient. Should be enabled to avoid issues, but can have a minor performance impact." ),
BASIC_CARDS( "BasicCards", Constants.CATEGORY_UPGRADES ),
ADVANCED_CARDS( "AdvancedCards", Constants.CATEGORY_UPGRADES ),
@@ -178,17 +179,29 @@ public enum AEFeature
private final String key;
private final String category;
private final boolean enabled;
private final String comment;
AEFeature( final String key, final String cat )
{
this( key, cat, true );
}
AEFeature( final String key, final String cat, final String comment )
{
this( key, cat, true, comment );
}
AEFeature( final String key, final String cat, final boolean enabled )
{
this( key, cat, enabled, null );
}
AEFeature( final String key, final String cat, final boolean enabled, final String comment )
{
this.key = key;
this.category = cat;
this.enabled = enabled;
this.comment = comment;
}
/**
@@ -216,6 +229,11 @@ public enum AEFeature
return this.enabled;
}
public String comment()
{
return this.comment;
}
private enum Constants
{
;
@@ -27,6 +27,7 @@ import net.minecraft.item.Item;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import appeng.api.AEApi;
@@ -76,16 +77,15 @@ public class BlockQuartzOre extends AEBaseBlock
}
@Override
public void dropBlockAsItemWithChance( final World w, final BlockPos pos, final IBlockState state, final float chance, final int fortune )
public int getExpDrop( IBlockState state, IBlockAccess world, BlockPos pos, int fortune )
{
super.dropBlockAsItemWithChance( w, pos, state, chance, fortune );
if( this.getItemDropped( state, w.rand, fortune ) != Item.getItemFromBlock( this ) )
{
final int xp = MathHelper.getInt( w.rand, 2, 5 );
this.dropXpOnBlockBreak( w, pos, xp );
Random rand = world instanceof World ? ( (World) world ).rand : new Random();
if ( this.getItemDropped( state, rand, fortune ) != Item.getItemFromBlock( this ) )
{
return MathHelper.getInt( rand, 2, 5 );
}
return super.getExpDrop( state, world, pos, fortune );
}
@Override
@@ -25,6 +25,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
@@ -40,6 +41,9 @@ import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.container.ContainerNull;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.core.features.AEFeature;
import appeng.util.ItemSorters;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
@@ -265,7 +269,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
return true;
}
}
else
else if( AEConfig.instance().isFeatureEnabled( AEFeature.CRAFTING_MANAGER_FALLBACK ) )
{
final ItemStack testOutput = CraftingManager.findMatchingResult( this.testFrame, w );
@@ -273,8 +277,16 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
{
this.testFrame.setInventorySlotContents( slotIndex, this.crafting.getStackInSlot( slotIndex ) );
this.markItemAs( slotIndex, i, TestStatus.ACCEPT );
if( AELog.isCraftingDebugLogEnabled() )
{
this.warnAboutCraftingManager( true );
}
return true;
}
this.warnAboutCraftingManager( false );
}
this.markItemAs( slotIndex, i, TestStatus.DECLINE );
@@ -395,6 +407,24 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
return this.pattern.hashCode();
}
private void warnAboutCraftingManager( boolean foundAlternative )
{
final String foundAlternativeRecipe = foundAlternative ? "Found alternative recipe." : "NOT FOUND, please report.";
final StringJoiner joinActualInputs = new StringJoiner( ", " );
for( int j = 0; j < this.testFrame.getSizeInventory(); j++ )
{
final ItemStack stack = this.testFrame.getStackInSlot( j );
if( !stack.isEmpty() )
{
joinActualInputs.add( stack.toString() );
}
}
AELog.warn( "Using CraftingManager fallback: Recipe <%s> for output <%s> rejected inputs [%s]. %s",
this.standardRecipe.getRegistryName(), this.standardRecipe.getRecipeOutput(), joinActualInputs, foundAlternativeRecipe );
}
@Override
public boolean equals( final Object obj )
{
@@ -83,16 +83,9 @@ public class ToolNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench,
{
final RayTraceResult mop = AppEng.proxy.getRTR();
if( mop == null )
if( mop == null || mop.typeOfHit == RayTraceResult.Type.MISS )
{
this.onItemUseFirst( p, w, new BlockPos( 0, 0, 0 ), null, 0, 0, 0, hand ); // eh?
}
else
{
if( w.getBlockState( mop.getBlockPos() ).getBlock().isAir( w.getBlockState( mop.getBlockPos() ), w, mop.getBlockPos() ) )
{
this.onItemUseFirst( p, w, new BlockPos( 0, 0, 0 ), null, 0, 0, 0, hand ); // eh?
}
NetworkHandler.instance().sendToServer( new PacketClick( BlockPos.ORIGIN, null, 0, 0, 0, hand ) );
}
}
@@ -67,7 +67,6 @@ public class ToolQuartzWrench extends AEBaseItem implements IAEWrench, IToolHamm
if( b.rotateBlock( world, pos, side ) )
{
b.neighborChanged( Platform.AIR_BLOCK.getDefaultState(), world, pos, Platform.AIR_BLOCK, pos );
player.swingArm( hand );
return !world.isRemote ? EnumActionResult.SUCCESS : EnumActionResult.FAIL;
}
+1 -1
View File
@@ -320,7 +320,7 @@ public class GridNode implements IGridNode, IPathItem
{
final IPathingGrid pg = g.getCache( IPathingGrid.class );
final IEnergyGrid eg = g.getCache( IEnergyGrid.class );
return this.meetsChannelRequirements() && eg.isNetworkPowered() && !pg.isNetworkBooting();
return eg.isNetworkPowered() && !pg.isNetworkBooting() && this.meetsChannelRequirements();
}
return false;
}
+13 -3
View File
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.Map.Entry;
import appeng.api.networking.IGridNode;
import appeng.api.networking.IMachineSet;
import appeng.api.networking.events.MENetworkEvent;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.core.AELog;
@@ -114,10 +115,19 @@ public class NetworkEventBus
target.invoke( cache.getCache(), e );
}
for( final IGridNode obj : g.getMachines( subscriber.getKey() ) )
// events may create or remove grid nodes in rare cases
final IMachineSet machines = g.getMachines( subscriber.getKey() );
final List<IGridNode> work = new ArrayList<>( machines.size() );
machines.forEach( work::add );
for( final IGridNode obj : work )
{
x++;
target.invoke( obj.getMachine(), e );
// stil part of grid?
if( machines.contains( obj ) )
{
x++;
target.invoke( obj.getMachine(), e );
}
}
}
}
+2 -2
View File
@@ -31,7 +31,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Queues;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
@@ -49,7 +49,7 @@ import appeng.me.storage.ItemWatcher;
public class NetworkMonitor<T extends IAEStack<T>> implements IMEMonitor<T>
{
@Nonnull
private static final Deque<NetworkMonitor<?>> GLOBAL_DEPTH = Lists.newLinkedList();
private static final Deque<NetworkMonitor<?>> GLOBAL_DEPTH = Queues.newArrayDeque();
@Nonnull
private final GridStorageCache myGridCache;
+1 -1
View File
@@ -402,7 +402,7 @@ public class PathGridCache implements IPathingGrid
@Override
public boolean isNetworkBooting()
{
return !this.active.isEmpty() && !this.booting;
return !this.booting && !this.active.isEmpty();
}
@Override
@@ -19,6 +19,7 @@
package appeng.me.cluster.implementations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -227,7 +228,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{
if( input instanceof IAEItemStack )
{
final IAEItemStack is = this.waitingFor.findPrecise( (IAEItemStack) input );
final IAEItemStack is = this.waitingFor.findPrecise( input );
if( is != null && is.getStackSize() > 0 )
{
return true;
@@ -243,7 +244,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
return input;
}
final IAEItemStack what = (IAEItemStack) input.copy();
final IAEItemStack what = input.copy();
final IAEItemStack is = this.waitingFor.findPrecise( what );
if( type == Actionable.SIMULATE )// causes crafting to lock up?
@@ -684,7 +685,25 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
if( details.isCraftable() )
{
for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( input[x], FuzzyMode.IGNORE_ALL ) )
final Collection<IAEItemStack> itemList;
if( details.canSubstitute() )
{
itemList = this.inventory.getItemList().findFuzzy( input[x], FuzzyMode.IGNORE_ALL );
}
else
{
itemList = new ArrayList<>( 1 );
final IAEItemStack item = this.inventory.getItemList().findPrecise( input[x] );
if( item != null )
{
itemList.add( item );
}
}
for( IAEItemStack fuzz : itemList )
{
fuzz = fuzz.copy();
fuzz.setStackSize( input[x].getStackSize() );
@@ -218,11 +218,12 @@ public class CellInventory implements ICellInventory
return input;
}
final ItemStack sharedItemStack = input.createItemStack();
if( CellInventory.isStorageCell( sharedItemStack ) )
// This is slightly hacky as it expects a read-only access, but fine for now.
// TODO: Guarantee a read-only access. E.g. provide an isEmpty() method and ensure CellInventory does not write
// any NBT data for empty cells instead of relying on an empty IItemContainer
if( CellInventory.isStorageCell( input.getDefinition() ) )
{
final IMEInventory meInventory = getCell( sharedItemStack, null );
final IMEInventory meInventory = getCell( input.createItemStack(), null );
if( meInventory != null && !this.isEmpty( meInventory ) )
{
return input;
@@ -232,20 +233,20 @@ public class CellInventory implements ICellInventory
final IAEItemStack l = this.getCellItems().findPrecise( input );
if( l != null )
{
final long remainingItemSlots = this.getRemainingItemCount();
if( remainingItemSlots < 0 )
final long remainingItemCount = this.getRemainingItemCount();
if( remainingItemCount < 0 )
{
return input;
}
if( input.getStackSize() > remainingItemSlots )
if( input.getStackSize() > remainingItemCount )
{
final IAEItemStack r = input.copy();
r.setStackSize( r.getStackSize() - remainingItemSlots );
r.setStackSize( r.getStackSize() - remainingItemCount );
if( mode == Actionable.MODULATE )
{
l.setStackSize( l.getStackSize() + remainingItemSlots );
this.updateItemCount( remainingItemSlots );
l.setStackSize( l.getStackSize() + remainingItemCount );
this.updateItemCount( remainingItemCount );
this.saveChanges();
}
return r;
@@ -269,19 +270,19 @@ public class CellInventory implements ICellInventory
{
if( input.getStackSize() > remainingItemCount )
{
final ItemStack toReturn = sharedItemStack.copy();
toReturn.setCount( sharedItemStack.getCount() - remainingItemCount );
final IAEItemStack toReturn = input.copy();
toReturn.setStackSize( input.getStackSize() - remainingItemCount );
if( mode == Actionable.MODULATE )
{
final ItemStack toWrite = sharedItemStack.copy();
toWrite.setCount( remainingItemCount );
final IAEItemStack toWrite = input.copy();
toWrite.setStackSize( remainingItemCount );
this.cellItems.add( AEItemStack.fromItemStack( toWrite ) );
this.updateItemCount( toWrite.getCount() );
this.cellItems.add( toWrite );
this.updateItemCount( toWrite.getStackSize() );
this.saveChanges();
}
return AEItemStack.fromItemStack( toReturn );
return toReturn;
}
if( mode == Actionable.MODULATE )
@@ -19,9 +19,10 @@
package appeng.me.storage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
@@ -144,7 +145,7 @@ public class MEMonitorIInventory implements IMEMonitor<IAEItemStack>, ITickingMo
public TickRateModulation onTick()
{
final LinkedList<IAEItemStack> changes = new LinkedList<>();
final List<IAEItemStack> changes = new ArrayList<>();
this.list.resetStatus();
int high = 0;
@@ -212,13 +212,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
@Override
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
for( int i = 0; i < this.itemHandler.getSlots(); i++ )
{
out.addStorage( AEItemStack.fromItemStack( this.itemHandler.getStackInSlot( i ) ) );
}
return out;
return this.cache.getAvailableItems( out );
}
@Override
@@ -259,7 +253,6 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
private static class InventoryCache
{
private ItemStack[] cachedStacks = new ItemStack[0];
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
private final IItemHandler itemHandler;
@@ -268,70 +261,76 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
this.itemHandler = itemHandler;
}
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{
Arrays.stream( this.cachedAeStacks ).forEach( out::add );
return out;
}
public List<IAEItemStack> update()
{
List<IAEItemStack> changes = new ArrayList<>();
int slots = this.itemHandler.getSlots();
final List<IAEItemStack> changes = new ArrayList<>();
final int slots = this.itemHandler.getSlots();
// Make room for new slots
if( slots > this.cachedStacks.length )
if( slots > this.cachedAeStacks.length )
{
this.cachedStacks = Arrays.copyOf( this.cachedStacks, slots );
this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots );
}
for( int slot = 0; slot < slots; slot++ )
{
// Save the old stuff
ItemStack oldIS = this.getItemStackInCachedSlot( slot );
IAEItemStack oldAeIS = this.cachedAeStacks[slot];
final IAEItemStack oldAeIS = this.cachedAeStacks[slot];
final ItemStack newIS = this.itemHandler.getStackInSlot( slot );
ItemStack newIS = this.itemHandler.getStackInSlot( slot );
if( isDifferent( newIS, oldIS ) )
{
this.addItemChange( slot, oldAeIS, newIS, changes );
}
else if( !newIS.isEmpty() && !oldIS.isEmpty() )
{
this.addPossibleStackSizeChange( slot, oldAeIS, newIS, changes );
}
this.handlePossibleSlotChanges( slot, oldAeIS, newIS, changes );
}
// Handle cases where the number of slots actually is lower now than before
if( slots < this.cachedStacks.length )
if( slots < this.cachedAeStacks.length )
{
for( int slot = slots; slot < this.cachedStacks.length; slot++ )
for( int slot = slots; slot < this.cachedAeStacks.length; slot++ )
{
IAEItemStack aeStack = this.cachedAeStacks[slot];
final IAEItemStack aeStack = this.cachedAeStacks[slot];
if( aeStack != null )
{
IAEItemStack a = aeStack.copy();
final IAEItemStack a = aeStack.copy();
a.setStackSize( -a.getStackSize() );
changes.add( a );
}
}
// Reduce the cache size
this.cachedStacks = Arrays.copyOf( this.cachedStacks, slots );
this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots );
}
return changes;
}
private void addPossibleStackSizeChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
private void handlePossibleSlotChanges( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
if( oldAeIS != null && oldAeIS.isSameType( newIS ) )
{
this.handleStackSizeChanged( slot, oldAeIS, newIS, changes );
}
else
{
this.handleItemChanged( slot, oldAeIS, newIS, changes );
}
}
private void handleStackSizeChanged( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
// Still the same item, but amount might have changed
long diff = newIS.getCount() - oldAeIS.getStackSize();
final long diff = newIS.getCount() - oldAeIS.getStackSize();
if( diff != 0 )
{
IAEItemStack stack = oldAeIS.copy();
final IAEItemStack stack = oldAeIS.copy();
stack.setStackSize( newIS.getCount() );
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = stack;
final IAEItemStack a = stack.copy();
@@ -340,28 +339,12 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
}
private ItemStack getItemStackInCachedSlot( int pos )
{
if( pos > this.cachedStacks.length )
{
return ItemStack.EMPTY;
}
if( this.cachedStacks[pos] == null )
{
return ItemStack.EMPTY;
}
return this.cachedStacks[pos];
}
private void addItemChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
private void handleItemChanged( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
// Completely different item
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = AEItemStack.fromItemStack( newIS );
// If we had a stack previously in this slot, notify the newtork about its disappearance
// If we had a stack previously in this slot, notify the network about its disappearance
if( oldAeIS != null )
{
oldAeIS.setStackSize( -oldAeIS.getStackSize() );
@@ -374,16 +357,6 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
changes.add( this.cachedAeStacks[slot] );
}
}
private static boolean isDifferent( final ItemStack a, final ItemStack b )
{
if( a == b && b.isEmpty() )
{
return false;
}
return a.isEmpty() || b.isEmpty() || !Platform.itemComparisons().isSameItem( a, b );
}
}
}
+1 -1
View File
@@ -488,7 +488,7 @@ public class AEBaseTile extends TileEntity implements IOrientable, ICommonTile,
public void saveChanges()
{
super.markDirty();
markDirty();
}
public boolean requiresTESR()
@@ -21,7 +21,6 @@ package appeng.util.helpers;
import javax.annotation.Nonnull;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
@@ -95,55 +94,23 @@ public class ItemComparisonHelper
return false;
}
/*
* if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! a.getHasSubtypes() && a.itemID ==
* b.itemID ) { return (a.getItemDamage() > 0) == (b.getItemDamage() > 0); }
*/
// test damageable items..
if( a.getItem() != Items.AIR && b.getItem() != Items.AIR && a.getItem().isDamageable() && a.getItem() == b.getItem() )
if( a.getItem() == b.getItem() && a.getItem().isDamageable() )
{
try
if( mode == FuzzyMode.IGNORE_ALL )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
final Item ai = a.getItem();
final Item bi = b.getItem();
return ( ai.getDurabilityForDisplay( a ) > 1 ) == ( bi.getDurabilityForDisplay( b ) > 1 );
}
else
{
final Item ai = a.getItem();
final Item bi = b.getItem();
final float percentDamagedOfA = 1.0f - (float) ai.getDurabilityForDisplay( a );
final float percentDamagedOfB = 1.0f - (float) bi.getDurabilityForDisplay( b );
return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint );
}
return true;
}
catch( final Throwable e )
else if( mode == FuzzyMode.PERCENT_99 )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
}
else
{
final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
}
else
{
final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint );
}
return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint );
}
}
@@ -155,17 +122,6 @@ public class ItemComparisonHelper
return true;
}
/*
* // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return OreID == getOreID( b );
* if ( Mode != FuzzyMode.IGNORE_ALL ) { if ( a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a =
* Platform.getSharedItemStack( AEItemStack.create( a ) ); }
* if ( b.hasTagCompound() && !isShared( b.getTagCompound() ) ) { b = Platform.getSharedItemStack(
* AEItemStack.create( b ) ); }
* // test regular items with damage values and what not... if ( isShared( a.getTagCompound() ) && isShared(
* b.getTagCompound() ) && a.itemID == b.itemID ) { return ((AppEngSharedNBTTagCompound)
* a.getTagCompound()).compareFuzzyWithRegistry( (AppEngSharedNBTTagCompound) b.getTagCompound() ); } }
*/
return a.isItemEqual( b );
}
+42 -109
View File
@@ -167,126 +167,30 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
{
if( st instanceof IAEItemStack )
{
final IAEItemStack o = (IAEItemStack) st;
final IAEItemStack other = (IAEItemStack) st;
if( this.sameOre( o ) )
if( OreHelper.INSTANCE.sameOre( this, other ) )
{
return true;
}
if( o.getItem() == this.getItem() )
{
if( this.getDefinition().getItem().isDamageable() )
{
final ItemStack a = this.getDefinition();
final ItemStack b = o.getDefinition();
final ItemStack itemStack = this.getDefinition();
final ItemStack otherStack = other.getDefinition();
try
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
final Item ai = a.getItem();
final Item bi = b.getItem();
return ( ai.getDurabilityForDisplay( a ) < 0.001f ) == ( bi.getDurabilityForDisplay( b ) < 0.001f );
}
else
{
final Item ai = a.getItem();
final Item bi = b.getItem();
final float percentDamageOfA = 1.0f - (float) ai.getDurabilityForDisplay( a );
final float percentDamageOfB = 1.0f - (float) bi.getDurabilityForDisplay( b );
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
catch( final Throwable e )
{
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 this.getItemDamage() == o.getItemDamage();
}
return this.fuzzyItemStackComparison( itemStack, otherStack, mode );
}
if( st instanceof ItemStack )
{
final ItemStack o = (ItemStack) st;
final ItemStack otherStack = (ItemStack) st;
OreHelper.INSTANCE.sameOre( this, o );
if( o.getItem() == this.getItem() )
if( OreHelper.INSTANCE.sameOre( this, otherStack ) )
{
if( this.getDefinition().getItem().isDamageable() )
{
final ItemStack a = this.getDefinition();
try
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
final Item ai = a.getItem();
final Item bi = o.getItem();
return ( ai.getDurabilityForDisplay( a ) < 0.001f ) == ( bi.getDurabilityForDisplay( o ) < 0.001f );
}
else
{
final Item ai = a.getItem();
final Item bi = o.getItem();
final float percentDamageOfA = 1.0f - (float) ai.getDurabilityForDisplay( a );
final float percentDamageOfB = 1.0f - (float) bi.getDurabilityForDisplay( o );
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
catch( final Throwable e )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
return ( a.getItemDamage() > 1 ) == ( o.getItemDamage() > 1 );
}
else
{
final float percentDamageOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamageOfB = (float) o.getItemDamage() / (float) o.getMaxDamage();
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
}
return this.getItemDamage() == o.getItemDamage();
return true;
}
final ItemStack itemStack = this.getDefinition();
return this.fuzzyItemStackComparison( itemStack, otherStack, mode );
}
return false;
@@ -390,7 +294,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
@Override
public String toString()
{
return this.getDefinition().toString();
return this.getStackSize() + "x" + this.getDefinition().getItem().getUnlocalizedName() + "@" + this.getDefinition().getItemDamage();
}
@SideOnly( Side.CLIENT )
@@ -443,7 +347,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
@Override
public ItemStack asItemStackRepresentation()
{
return getDefinition().copy();
return this.getDefinition().copy();
}
@Override
@@ -457,4 +361,33 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
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;
}
}
@@ -21,7 +21,6 @@ package appeng.worldgen;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
@@ -48,16 +47,22 @@ public final class QuartzWorldGen implements IWorldGenerator
final IBlockDefinition oreDefinition = blocks.quartzOre();
final IBlockDefinition chargedDefinition = blocks.quartzOreCharged();
final Block ore = oreDefinition.maybeBlock().orElse( null );
final Block charged = chargedDefinition.maybeBlock().orElse( null );
this.oreNormal = new WorldGenMinable( ore.getDefaultState(), AEConfig.instance().getQuartzOresPerCluster() );
this.oreCharged = new WorldGenMinable( charged.getDefaultState(), AEConfig.instance().getQuartzOresPerCluster() );
this.oreNormal = oreDefinition.maybeBlock()
.map( b -> new WorldGenMinable( b.getDefaultState(), AEConfig.instance().getQuartzOresPerCluster() ) )
.orElse( null );
this.oreCharged = chargedDefinition.maybeBlock()
.map( b -> new WorldGenMinable( b.getDefaultState(), AEConfig.instance().getQuartzOresPerCluster() ) )
.orElse( null );
}
@Override
public void generate( final Random r, final int chunkX, final int chunkZ, final World w, final IChunkGenerator chunkGenerator, final IChunkProvider chunkProvider )
{
if( this.oreNormal == null && this.oreCharged == null )
{
return;
}
int seaLevel = w.provider.getAverageGroundLevel() + 1;
if( seaLevel < 20 )
@@ -67,26 +72,31 @@ public final class QuartzWorldGen implements IWorldGenerator
seaLevel = w.getHeight( x, z );
}
if( this.oreNormal == null || this.oreCharged == null )
{
return;
}
final double oreDepthMultiplier = AEConfig.instance().getQuartzOresClusterAmount() * seaLevel / 64;
final int scale = (int) Math.round( r.nextGaussian() * Math.sqrt( oreDepthMultiplier ) + oreDepthMultiplier );
for( int x = 0; x < ( r.nextBoolean() ? scale * 2 : scale ) / 2; ++x )
for( int cnt = 0; cnt < ( r.nextBoolean() ? scale * 2 : scale ) / 2; ++cnt )
{
final boolean isCharged = r.nextFloat() > AEConfig.instance().getSpawnChargedChance();
final WorldGenMinable whichOre = isCharged ? this.oreCharged : this.oreNormal;
boolean isCharged = false;
if( WorldGenRegistry.INSTANCE.isWorldGenEnabled( isCharged ? WorldGenType.CHARGED_CERTUS_QUARTZ : WorldGenType.CERTUS_QUARTZ, w ) )
if( this.oreCharged != null )
{
final int cx = chunkX * 16 + r.nextInt( 22 );
isCharged = r.nextFloat() > AEConfig.instance().getSpawnChargedChance();
}
final WorldGenMinable whichOre = isCharged ? this.oreCharged : this.oreNormal;
if( whichOre != null && shouldGenerate( isCharged, w ) )
{
final int cx = chunkX * 16 + r.nextInt( 16 );
final int cy = r.nextInt( 40 * seaLevel / 64 ) + r.nextInt( 22 * seaLevel / 64 ) + 12 * seaLevel / 64;
final int cz = chunkZ * 16 + r.nextInt( 22 );
final int cz = chunkZ * 16 + r.nextInt( 16 );
whichOre.generate( w, r, new BlockPos( cx, cy, cz ) );
}
}
}
private static boolean shouldGenerate( final boolean isCharged, final World w )
{
return WorldGenRegistry.INSTANCE.isWorldGenEnabled( isCharged ? WorldGenType.CHARGED_CERTUS_QUARTZ : WorldGenType.CERTUS_QUARTZ, w );
}
}