Compare commits

..

29 Commits

Author SHA1 Message Date
yueh c1197c0084 Updated to latest Forge RB. (#3250)
While this is not ideal for a stable release, switching to the latest RB
of Forge avoids the broken recipes in previous versions.
2017-11-26 15:46:38 +01:00
fscan f0d807f0a2 Rework ContainerInscriber validation (#3238)
* Correctly handle metadata wildcard for inscriber inputs
2017-11-26 15:46:02 +01:00
fscan 5fa2c0ab27 Deprecate AE2 recipe system. (#3247)
* Deprecate aerecipes to indicate that they are going away soon.
2017-11-26 15:45:34 +01:00
fscan 3063bd887c Revert DamageableRecipe changes (#3246)
Forge fixed this after all. This is no longer needed.
2017-11-26 15:44:56 +01:00
Florian Scandella fac4a8f9dc Fix typo 2017-11-26 14:38:09 +01:00
fscan 9d8226da19 Remove swingArm in IToolHammer implementation. (#3249)
Fixes #3248
2017-11-25 13:38:22 +01:00
yueh 33754d289d Fixes #932: Fire ExplosionEvent.Detonate when tiny TNT explodes. (#3229)
This still bypasses the start event to prevent it from ever being
cancelled.
2017-11-23 11:06:46 +01:00
fscan 959672dae3 Add CraftTweaker support (#3231) 2017-11-22 21:09:26 +01:00
fscan 90c17c09a8 Add custom recipe for damageable Ingredients (#3230) 2017-11-17 16:20:53 +01:00
yueh e0bf7223e0 Refactors grid connections (#3219)
Extracted all checks and subsequent updates to a factory method from the constructor.
Reordered checks to check for nulls before anything else.
Also existing connections before security breaks.
Fixes TileController#checkController() using the wrong position.
Added debug logging for failed connections.
Improved logging.
Inversed boolean so false no longer means security check passed.
Only issue a security break on SecurityConnectionException.
2017-11-12 18:13:59 +01:00
fscan ba9af94228 Fix StorageBus not updating item count correctly (#3218)
* Queue tick instead of ticking immediatley
2017-11-12 18:12:56 +01:00
yueh 122b6163dc Fixes #3209: Reset stack to prevent leaking meaningful ones (#3210) 2017-11-12 12:53:40 +01:00
yueh fab42ccc75 Use craftinggrid to check existing patterns for JEI recipe transfer. (#3202) 2017-11-12 12:48:18 +01:00
yueh f5dd2c8b0a Fixes tooltips for ME Slots (#3205)
No longer strips colors from names, lore, etc.
Now uses the translation again for "Items Stored:" instead of a hardcoded string.
Removed obsolete methods.
2017-11-12 12:35:05 +01:00
fscan a126112a2d Rework ImportBus (#3206)
Fixes #3201
2017-11-11 19:59:11 +01:00
fscan 99cda5f5a3 Cleanup recipe factories (#3207)
Fixes #3200
2017-11-11 17:51:20 +01:00
Florian Scandella 56a5363528 Fix NetworkToolViewer stack overflow, saveguard against markDirty recursion.
fixes #3199
2017-11-08 13:17:34 +01:00
fscan be65edbd5b Set base biome to "void" to shut up warning. (#3194)
Fixes #3118
2017-11-05 03:12:20 +01:00
fscan fe5d9251eb Spatial IO fixes (#3195)
* fix warning when transfering entities
* clean removed TileEntities from the ITickable list.
2017-11-04 23:12:17 +01:00
yueh 3cf48b2291 Remove channels per side from non smart cable states. (#3192)
These are unnecessary for these cable types and their rendering, but are
actually causing the cache to add duplicate models.
2017-11-04 13:24:57 +01:00
yueh cc4599b5fc Add a basic cache for cable models to avoid constant regeneration. (#3185)
* Add a basic cache for cable models to avoid constant regeneration.
* Improved equals/hashCode to ignore cable unrelated parts or facades.
2017-10-31 21:02:03 +01:00
yueh c1fa77df51 Fixes #3189: Formation plane unable to place special items. (#3190) 2017-10-31 16:12:08 +01:00
yueh 725fa491e6 Fixes #2611: Limit the adaptor to the main player inv. (#3188)
This prevents the result from various inventory actions to be placed into
the offhand or armor slots.
2017-10-31 14:05:05 +01:00
fscan e2a6cd1d57 Fix SkyChest bounding box (#3187)
fixes #3149
2017-10-31 01:40:17 +01:00
fscan 6ddf60fab8 Improve Facade rendering (#3182)
UV fix based on #2941 by @MoreThanHidden
fixes #2679, fixes #2625
2017-10-29 16:47:26 +01:00
fscan 2c07acfe81 Allow extraction for Condenser (#3179)
fixes #2960, fixes #2017, fixes #2602
2017-10-27 15:49:40 +02:00
fscan 3749742231 Fix handling of ItemStacks using getShareTag or Capabilites (#3171)
Temporary fix, ideally we would have a way to reference the original ItemStack so we don't need to send the full NBT data to the client.
2017-10-26 17:59:55 +02:00
yueh 74b9610b45 JSON resource cleanup (#3178)
Unified formatting
Added missing new lines at end of file
Removed superfluous spaces
Removed channel texture from dense covered cables.
2017-10-26 12:47:08 +02:00
yueh a725779ff6 Fixes #3175: Return the correct used amount. (#3176) 2017-10-26 12:46:49 +02:00
682 changed files with 18669 additions and 10492 deletions
+52
View File
@@ -14,6 +14,7 @@
* [Building](#building)
* [Contribution](#contribution)
* [API](#applied-energistics-2-api)
* [CraftTweaker](#applied-energistics-2-crafttweaker)
* [Localization](#applied-energistics-2-localization)
* [Credits](#credits)
@@ -154,6 +155,57 @@ Where the __ are filled in with the correct version criteria; AE2 is available f
An example string would be `appeng:appliedenergistics2:rv2-alpha-30:dev`
## Applied Energistics 2 CraftTweaker
### Inscriber
Add a recipe. When `inscribe` is true the bottom and top inputs are not consumed.
mods.appliedenergistics2.Inscriber.addRecipe(ItemStack output, ItemStack input, boolean inscribe,
@Optional ItemStack topInput, @Optional ItemStack bottomInput );
Remove all recipes for this output stack.
mods.appliedenergistics2.Inscriber.removeRecipe(ItemStack output);
### Grindstone
Add a recipe.
mods.appliedenergistics2.Grinder.addRecipe( ItemStack output, ItemStack input, int turns,
@Optional ItemStack secondary1Output, @Optional float secondary1Chance,
@Optional ItemStack secondary2Output, @Optional float secondary2Chance);
Remove recipes for this input.
mods.appliedenergistics2.Grinder.removeRecipe(ItemStack input);
### Spatial
Whitelist a TileEntity class for Spatial IO.
mods.appliedenergistics2.Spatial.whitelistEntity( String fullEntityClassName );
### Attunement
Attune a ItemStack or ModID to a specific P2P-Tunnel type. ModID's are used as fallback when no ItemStack was found.
mods.appliedenergistics2.Attunement.attuneME( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneME( String modID );
mods.appliedenergistics2.Attunement.attuneItem( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneItem( String modID );
mods.appliedenergistics2.Attunement.attuneFluid( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneFluid( String modID );
mods.appliedenergistics2.Attunement.attuneRedstone( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneRedstone( String modID );
mods.appliedenergistics2.Attunement.attuneRF( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneRF( String modID );
mods.appliedenergistics2.Attunement.attuneIC2( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneIC2( String modID );
mods.appliedenergistics2.Attunement.attuneLight( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneLight( String modID );
### Cannon
Add ammo types for the matter cannon.
mods.appliedenergistics2.Cannon.registerAmmo( ItemStack itemStack, double weight );
## Applied Energistics 2 Localization
### English Text
+1 -1
View File
@@ -9,7 +9,7 @@ aebasename=appliedenergistics2
#########################################################
minecraft_version=1.12.2
mcp_mappings=snapshot_20171003
forge_version=14.23.0.2491
forge_version=14.23.1.2554
#########################################################
# Installable #
+6
View File
@@ -58,6 +58,11 @@ repositories {
name 'tehnut'
url "http://tehnut.info/maven"
}
maven { // CraftTweaker
name 'jared maven'
url "http://maven.blamejared.com/"
}
}
configurations {
@@ -77,6 +82,7 @@ dependencies {
compileOnly "net.industrial-craft:industrialcraft-2:${ic2_version}:api"
compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api"
compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf"
compileOnly "CraftTweaker2:CraftTweaker2-API:4.+"
// at runtime, use the full JEI jar
runtime "mezz.jei:jei_${minecraft_version}:${jei_version}"
@@ -48,6 +48,7 @@ public interface IRecipeHandlerRegistry
* @param name name of crafthandler
* @param handler class of crafthandler
*/
@Deprecated
void addNewCraftHandler( String name, Class<? extends ICraftHandler> handler );
/**
@@ -65,11 +66,13 @@ public interface IRecipeHandlerRegistry
* @return A recipe handler by name, returns null on failure.
*/
@Nullable
@Deprecated
ICraftHandler getCraftHandlerFor( String name );
/**
* @return a new recipe handler, which can be used to parse, and read recipe files.
*/
@Deprecated
IRecipeHandler createNewRecipehandler();
/**
@@ -30,7 +30,7 @@ import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface ICraftHandler
{
@@ -29,7 +29,7 @@ import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface IIngredient
{
@@ -27,6 +27,7 @@ package appeng.api.recipes;
/**
* Represents the AE2 Recipe Loading/Reading Class
*/
@Deprecated
public interface IRecipeHandler
{
@@ -28,7 +28,7 @@ import java.io.BufferedReader;
import javax.annotation.Nonnull;
@Deprecated
public interface IRecipeLoader
{
/**
@@ -101,7 +101,6 @@ public class BlockCableBus extends AEBaseTileBlock
// this will actually be overwritten later through setupTile and the
// combined layers
this.setTileEntity( TileCableBus.class );
this.useNeighborBrightness = true;
}
@Override
@@ -47,9 +47,9 @@ import appeng.util.Platform;
public class BlockSkyChest extends AEBaseTileBlock implements ICustomCollision
{
private static final double AABB_OFFSET_BOTTOM = .0625d;
private static final double AABB_OFFSET_SIDES = 0;
private static final double AABB_OFFSET_TOP = .125d;
private static final double AABB_OFFSET_BOTTOM = 0.00;
private static final double AABB_OFFSET_SIDES = 0.06;
private static final double AABB_OFFSET_TOP = 0.125;
public enum SkyChestType
{
@@ -111,18 +111,18 @@ public class BlockSkyChest extends AEBaseTileBlock implements ICustomCollision
o = sk.getUp();
}
final double offsetX = o.getFrontOffsetX() == 0 ? AABB_OFFSET_BOTTOM : AABB_OFFSET_SIDES;
final double offsetY = o.getFrontOffsetY() == 0 ? AABB_OFFSET_BOTTOM : AABB_OFFSET_SIDES;
final double offsetZ = o.getFrontOffsetZ() == 0 ? AABB_OFFSET_BOTTOM : AABB_OFFSET_SIDES;
final double offsetX = o.getFrontOffsetX() == 0 ? AABB_OFFSET_SIDES : 0.0;
final double offsetY = o.getFrontOffsetY() == 0 ? AABB_OFFSET_SIDES : 0.0;
final double offsetZ = o.getFrontOffsetZ() == 0 ? AABB_OFFSET_SIDES : 0.0;
// x/z needs to be multiplied by -1, thus we simply add not substract.
final double minX = Math.max( 0.0, offsetX + o.getFrontOffsetX() * AABB_OFFSET_TOP );
final double minY = Math.max( 0.0, offsetY - o.getFrontOffsetY() * AABB_OFFSET_TOP );
final double minZ = Math.max( 0.0, offsetZ + o.getFrontOffsetZ() * AABB_OFFSET_TOP );
// for x/z top and bottom is swapped
final double minX = Math.max( 0.0, offsetX + ( o.getFrontOffsetX() < 0 ? AABB_OFFSET_BOTTOM : ( o.getFrontOffsetX() * AABB_OFFSET_TOP ) ) );
final double minY = Math.max( 0.0, offsetY + ( o.getFrontOffsetY() < 0 ? AABB_OFFSET_TOP : ( o.getFrontOffsetY() * AABB_OFFSET_BOTTOM ) ) );
final double minZ = Math.max( 0.0, offsetZ + ( o.getFrontOffsetZ() < 0 ? AABB_OFFSET_BOTTOM : ( o.getFrontOffsetZ() * AABB_OFFSET_TOP ) ) );
final double maxX = Math.min( 1.0, ( 1.0 - offsetX ) + o.getFrontOffsetX() * AABB_OFFSET_TOP );
final double maxY = Math.min( 1.0, ( 1.0 - offsetY ) - o.getFrontOffsetY() * AABB_OFFSET_TOP );
final double maxZ = Math.min( 1.0, ( 1.0 - offsetZ ) + o.getFrontOffsetZ() * AABB_OFFSET_TOP );
final double maxX = Math.min( 1.0, 1.0 - offsetX - ( o.getFrontOffsetX() < 0 ? AABB_OFFSET_TOP : ( o.getFrontOffsetX() * AABB_OFFSET_BOTTOM ) ) );
final double maxY = Math.min( 1.0, 1.0 - offsetY - ( o.getFrontOffsetY() < 0 ? AABB_OFFSET_BOTTOM : ( o.getFrontOffsetY() * AABB_OFFSET_TOP ) ) );
final double maxZ = Math.min( 1.0, 1.0 - offsetZ - ( o.getFrontOffsetZ() < 0 ? AABB_OFFSET_TOP : ( o.getFrontOffsetZ() * AABB_OFFSET_BOTTOM ) ) );
return new AxisAlignedBB( minX, minY, minZ, maxX, maxY, maxZ );
}
@@ -23,7 +23,6 @@ import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
@@ -43,70 +42,17 @@ public abstract class AEBaseMEGui extends AEBaseGui
super( container );
}
public List<String> handleItemTooltip( final ItemStack stack, final int mouseX, final int mouseY, final List<String> currentToolTip )
{
if( !stack.isEmpty() )
{
final Slot s = this.getSlot( mouseX, mouseY );
if( s instanceof SlotME )
{
final int BigNumber = AEConfig.instance().useTerminalUseLargeFont() ? 999 : 9999;
IAEItemStack myStack = null;
try
{
final SlotME theSlotField = (SlotME) s;
myStack = theSlotField.getAEStack();
}
catch( final Throwable ignore )
{
}
if( myStack != null )
{
if( myStack.getStackSize() > BigNumber || ( myStack.getStackSize() > 1 && stack.isItemDamaged() ) )
{
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
if( myStack.getCountRequestable() > 0 )
{
final String local = ButtonToolTips.ItemsRequestable.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
}
else if( stack.getCount() > BigNumber || ( stack.getCount() > 1 && stack.isItemDamaged() ) )
{
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
}
}
return currentToolTip;
}
// Vanilla version...
// protected void drawItemStackTooltip(ItemStack stack, int x, int y)
@Override
protected void renderToolTip( final ItemStack stack, final int x, final int y )
{
final Slot s = this.getSlot( x, y );
if( s instanceof SlotME && !stack.isEmpty() )
{
final int BigNumber = AEConfig.instance().useTerminalUseLargeFont() ? 999 : 9999;
final int bigNumber = AEConfig.instance().useTerminalUseLargeFont() ? 999 : 9999;
IAEItemStack myStack = null;
final List<String> currentToolTip = this.getItemToolTip( stack );
try
{
@@ -117,33 +63,44 @@ public abstract class AEBaseMEGui extends AEBaseGui
{
}
ITooltipFlag.TooltipFlags tooltipFlag = this.mc.gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL;
if( myStack != null )
{
final List<String> currentToolTip = stack.getTooltip( this.mc.player, tooltipFlag );
if( myStack.getStackSize() > BigNumber || ( myStack.getStackSize() > 1 && stack.isItemDamaged() ) )
if( myStack.getStackSize() > bigNumber || ( myStack.getStackSize() > 1 && stack.isItemDamaged() ) )
{
currentToolTip.add( "Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() ) );
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
if( myStack.getCountRequestable() > 0 )
{
currentToolTip.add( "Items Requestable: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() ) );
final String local = ButtonToolTips.ItemsRequestable.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( format );
}
this.drawTooltip( x, y, currentToolTip );
this.drawHoveringText( currentToolTip, x, y, this.fontRenderer );
return;
}
else if( stack.getCount() > BigNumber )
else if( stack.getCount() > bigNumber )
{
List<String> var4 = stack.getTooltip( this.mc.player, tooltipFlag );
var4.add( "Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() ) );
this.drawTooltip( x, y, var4 );
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
this.drawHoveringText( currentToolTip, x, y, this.fontRenderer );
return;
}
}
super.renderToolTip( stack, x, y );
// super.drawItemStackTooltip( stack, x, y );
}
}
@@ -237,10 +237,11 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource
this.getScrollBar().setRange( 0, ( size + 4 ) / 5 - this.rows, 1 );
}
// Vanilla version...
protected void drawItemStackTooltip( final ItemStack stack, final int x, final int y )
@Override
protected void renderToolTip( final ItemStack stack, final int x, final int y )
{
final Slot s = this.getSlot( x, y );
if( s instanceof SlotME && stack != null )
{
IAEItemStack myStack = null;
@@ -270,7 +271,8 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource
this.drawTooltip( x, y, currentToolTip );
}
}
// super.drawItemStackTooltip( stack, x, y );
super.renderToolTip( stack, x, y );
}
@Override
@@ -92,7 +92,7 @@ public class GuiSpatialIOPort extends AEBaseGui
}
else
{
this.fontRenderer.drawString( GuiText.SCSSize.getLocal() + ": " + GuiText.SCSSInvalid.getLocal(), 13, 93, 4210752 );
this.fontRenderer.drawString( GuiText.SCSSize.getLocal() + ": " + GuiText.SCSInvalid.getLocal(), 13, 93, 4210752 );
}
}
@@ -0,0 +1,69 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.client.render;
import javax.vecmath.Matrix4f;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
public abstract class DelegateBakedModel implements IBakedModel
{
private IBakedModel baseModel;
protected DelegateBakedModel( IBakedModel base )
{
this.baseModel = base;
}
@Override
public Pair<? extends IBakedModel, Matrix4f> handlePerspective( ItemCameraTransforms.TransformType type )
{
Pair<? extends IBakedModel, Matrix4f> pair = this.baseModel.handlePerspective( type );
return Pair.of( this, pair.getValue() );
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
}
public IBakedModel getBaseModel()
{
return this.baseModel;
}
}
@@ -27,9 +27,7 @@ import javax.annotation.Nullable;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
@@ -44,16 +42,13 @@ import appeng.items.parts.ItemFacade;
* on the item stack.
* A custom Item Override List is used to accomplish this.
*/
public class FacadeDispatcherBakedModel implements IBakedModel
public class FacadeDispatcherBakedModel extends DelegateBakedModel
{
private final IBakedModel baseModel;
private final VertexFormat format;
public FacadeDispatcherBakedModel( IBakedModel baseModel, VertexFormat format )
{
this.baseModel = baseModel;
super( baseModel );
this.format = format;
}
@@ -64,16 +59,10 @@ public class FacadeDispatcherBakedModel implements IBakedModel
return Collections.emptyList();
}
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return this.baseModel.isGui3d();
return this.getBaseModel().isGui3d();
}
@Override
@@ -82,18 +71,6 @@ public class FacadeDispatcherBakedModel implements IBakedModel
return false;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides()
{
@@ -112,7 +89,8 @@ public class FacadeDispatcherBakedModel implements IBakedModel
IBlockState state = itemFacade.getTextureBlockState( stack );
ItemStack textureItem = itemFacade.getTextureItem( stack );
return new FacadeWithBlockBakedModel( FacadeDispatcherBakedModel.this.baseModel, state, textureItem, FacadeDispatcherBakedModel.this.format );
return new FacadeWithBlockBakedModel( FacadeDispatcherBakedModel.this
.getBaseModel(), state, textureItem, FacadeDispatcherBakedModel.this.format );
}
};
}
@@ -30,7 +30,6 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import appeng.core.AppEng;
@@ -41,10 +40,27 @@ import appeng.core.AppEng;
*/
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
{
baseModel = ModelLoaderRegistry.getModel( MODEL_BASE );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
}
return this.baseModel;
}
@Override
public Collection<ResourceLocation> getDependencies()
{
@@ -60,17 +76,7 @@ public class FacadeItemModel implements IModel
@Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{
IModel baseModel;
try
{
baseModel = ModelLoaderRegistry.getModel( MODEL_BASE );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
IBakedModel bakedBaseModel = baseModel.bake( state, format, bakedTextureGetter );
IBakedModel bakedBaseModel = this.getBaseModel().bake( state, format, bakedTextureGetter );
return new FacadeDispatcherBakedModel( bakedBaseModel, format );
}
@@ -78,6 +84,6 @@ public class FacadeItemModel implements IModel
@Override
public IModelState getDefaultState()
{
return TRSRTransformation.identity();
return getBaseModel().getDefaultState();
}
}
@@ -29,9 +29,7 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
@@ -44,11 +42,8 @@ import appeng.client.render.cablebus.FacadeBuilder;
* This is the actual baked model that will combine the north face of a given block state
* with the base facade item model to achieve what is then actually rendered on screen.
*/
public class FacadeWithBlockBakedModel implements IBakedModel
public class FacadeWithBlockBakedModel extends DelegateBakedModel
{
private final IBakedModel baseModel;
private final IBlockState blockState;
private final IBakedModel textureModel;
@@ -59,7 +54,7 @@ public class FacadeWithBlockBakedModel implements IBakedModel
public FacadeWithBlockBakedModel( IBakedModel baseModel, IBlockState blockState, ItemStack textureItem, VertexFormat format )
{
this.baseModel = baseModel;
super( baseModel );
this.blockState = blockState;
this.textureItem = textureItem;
this.textureModel = Minecraft.getMinecraft().getBlockRendererDispatcher().getModelForState( blockState );
@@ -88,13 +83,7 @@ public class FacadeWithBlockBakedModel implements IBakedModel
}
}
return this.baseModel.getQuads( state, side, rand );
}
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
return this.getBaseModel().getQuads( state, side, rand );
}
@Override
@@ -109,18 +98,6 @@ public class FacadeWithBlockBakedModel implements IBakedModel
return false;
}
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override
public ItemOverrideList getOverrides()
{
@@ -22,6 +22,7 @@ package appeng.client.render.cablebus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -52,6 +53,8 @@ import appeng.block.networking.BlockCableBus;
public class CableBusBakedModel implements IBakedModel
{
private static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
private final CableBuilder cableBuilder;
private final FacadeBuilder facadeBuilder;
@@ -88,8 +91,15 @@ public class CableBusBakedModel implements IBakedModel
// translucent facades further down below.
if( layer == BlockRenderLayer.CUTOUT )
{
// First, handle the cable at the center of the cable bus
this.addCableQuads( renderState, quads );
final List<BakedQuad> cableModel = CABLE_MODEL_CACHE.computeIfAbsent( renderState, k ->
{
final List<BakedQuad> model = new ArrayList<>();
this.addCableQuads( renderState, model );
return model;
} );
quads.addAll( cableModel );
// Then handle attachments
for( EnumFacing facing : EnumFacing.values() )
@@ -308,10 +318,8 @@ public class CableBusBakedModel implements IBakedModel
TextureAtlasSprite particleTexture = bakedModel.getParticleTexture();
// If a part sub-model has no particle texture (indicated by it being the missing texture), don't
// add
// it,
// so we don't get ugly missing texture break particles.
// If a part sub-model has no particle texture (indicated by it being the missing texture),
// don't add it, so we don't get ugly missing texture break particles.
if( this.textureMap.getMissingSprite() != particleTexture )
{
result.add( particleTexture );
@@ -336,7 +344,7 @@ public class CableBusBakedModel implements IBakedModel
@Override
public boolean isAmbientOcclusion()
{
return false;
return true;
}
@Override
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
@@ -153,4 +154,43 @@ public class CableBusRenderState
return this.boundingBoxes;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ( ( this.attachmentConnections == null ) ? 0 : this.attachmentConnections.hashCode() );
result = prime * result + ( ( this.cableBusAdjacent == null ) ? 0 : this.cableBusAdjacent.hashCode() );
result = prime * result + ( ( this.cableColor == null ) ? 0 : this.cableColor.hashCode() );
result = prime * result + ( ( this.cableType == null ) ? 0 : this.cableType.hashCode() );
result = prime * result + ( ( this.channelsOnSide == null ) ? 0 : this.channelsOnSide.hashCode() );
result = prime * result + ( ( this.connectionTypes == null ) ? 0 : this.connectionTypes.hashCode() );
result = prime * result + ( ( this.coreType == null ) ? 0 : this.coreType.hashCode() );
return result;
}
@Override
public boolean equals( Object obj )
{
if( this == obj )
{
return true;
}
if( obj == null )
{
return false;
}
if( getClass() != obj.getClass() )
{
return false;
}
final CableBusRenderState other = (CableBusRenderState) obj;
return this.cableColor == other.cableColor && this.cableType == other.cableType && this.coreType == other.coreType && Objects
.equals( this.attachmentConnections, other.attachmentConnections ) && Objects.equals( this.cableBusAdjacent,
other.cableBusAdjacent ) && Objects.equals( this.channelsOnSide, other.channelsOnSide ) && Objects.equals( this.connectionTypes,
other.connectionTypes );
}
}
@@ -59,6 +59,8 @@ public class CubeBuilder
private int color = 0xFFFFFFFF;
private boolean useStandardUV = false;
private boolean renderFullBright;
public CubeBuilder( VertexFormat format, List<BakedQuad> output )
@@ -142,7 +144,9 @@ public class CubeBuilder
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( this.format );
builder.setTexture( texture );
builder.setQuadOrientation( face );
builder.setQuadTint( -1 );
builder.setApplyDiffuseLighting( true );
UvVector uv = new UvVector();
// The user might have set specific UV coordinates for this face
@@ -154,6 +158,10 @@ public class CubeBuilder
uv.u2 = texture.getInterpolatedU( customUv.z );
uv.v2 = texture.getInterpolatedV( customUv.w );
}
else if( this.useStandardUV )
{
uv = this.getStandardUv( face, texture, x1, y1, z1, x2, y2, z2 );
}
else
{
uv = this.getDefaultUv( face, texture, x1, y1, z1, x2, y2, z2 );
@@ -199,8 +207,7 @@ public class CubeBuilder
break;
}
int[] vertexData = builder.build().getVertexData();
this.output.add( new BakedQuad( vertexData, -1, face, texture, true, this.format ) );
this.output.add( builder.build() );
}
private UvVector getDefaultUv( EnumFacing face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 )
@@ -251,6 +258,51 @@ public class CubeBuilder
return uv;
}
private UvVector getStandardUv( EnumFacing face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 )
{
UvVector uv = new UvVector();
switch( face )
{
case DOWN:
uv.u1 = texture.getInterpolatedU( x1 * 16 );
uv.v1 = texture.getInterpolatedV( 16 - z1 * 16 );
uv.u2 = texture.getInterpolatedU( x2 * 16 );
uv.v2 = texture.getInterpolatedV( 16 - z2 * 16 );
break;
case UP:
uv.u1 = texture.getInterpolatedU( x1 * 16 );
uv.v1 = texture.getInterpolatedV( z1 * 16 );
uv.u2 = texture.getInterpolatedU( x2 * 16 );
uv.v2 = texture.getInterpolatedV( z2 * 16 );
break;
case NORTH:
uv.u1 = texture.getInterpolatedU( 16 - x1 * 16 );
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
uv.u2 = texture.getInterpolatedU( 16 - x2 * 16 );
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
break;
case SOUTH:
uv.u1 = texture.getInterpolatedU( x1 * 16 );
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
uv.u2 = texture.getInterpolatedU( x2 * 16 );
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
break;
case WEST:
uv.u1 = texture.getInterpolatedU( z1 * 16 );
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
uv.u2 = texture.getInterpolatedU( z2 * 16 );
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
break;
case EAST:
uv.u1 = texture.getInterpolatedU( 16 - z2 * 16 );
uv.v1 = texture.getInterpolatedV( 16 - y1 * 16 );
uv.u2 = texture.getInterpolatedU( 16 - z1 * 16 );
uv.v2 = texture.getInterpolatedV( 16 - y2 * 16 );
break;
}
return uv;
}
// uv.u1, uv.v1
private void putVertexTL( UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv )
{
@@ -484,6 +536,15 @@ public class CubeBuilder
this.uvRotations[facing.ordinal()] = (byte) rotation;
}
/**
* CubeBuilder uses UV optimized for cables by default.
* This switches to standard UV coordinates.
*/
public void useStandardUV()
{
this.useStandardUV = true;
}
public List<BakedQuad> getOutput()
{
return this.output;
@@ -175,6 +175,7 @@ public class FacadeBuilder
// Reset to no color multiplicator
builder.setColorRGB( 0xFFFFFF );
builder.useStandardUV();
// We only render the stilt if we don't intersect with any part directly, and if there's no part on our side
if( renderStilt && busBounds == null && layer == BlockRenderLayer.CUTOUT )
@@ -438,22 +439,22 @@ public class FacadeBuilder
private static AxisAlignedBB getFacadeBox( EnumFacing side, boolean thinFacades )
{
int thickness = thinFacades ? 1 : 2;
double thickness = ( thinFacades ? 1 : 2 ) / 16.0;
switch( side )
{
case DOWN:
return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, ( thickness ) / 16.0, 1.0 );
return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, thickness, 1.0 );
case EAST:
return new AxisAlignedBB( ( 16.0 - thickness ) / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0 );
return new AxisAlignedBB( 1.0 - thickness, 0.0, 0.0, 1.0, 1.0, 1.0 );
case NORTH:
return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, ( thickness ) / 16.0 );
return new AxisAlignedBB( 0.0, 0.0, 0.0, 1.0, 1.0, thickness );
case SOUTH:
return new AxisAlignedBB( 0.0, 0.0, ( 16.0 - thickness ) / 16.0, 1.0, 1.0, 1.0 );
return new AxisAlignedBB( 0.0, 0.0, 1.0 - thickness, 1.0, 1.0, 1.0 );
case UP:
return new AxisAlignedBB( 0.0, ( 16.0 - thickness ) / 16.0, 0.0, 1.0, 1.0, 1.0 );
return new AxisAlignedBB( 0.0, 1.0 - thickness, 0.0, 1.0, 1.0, 1.0 );
case WEST:
return new AxisAlignedBB( 0.0, 0.0, 0.0, ( thickness ) / 16.0, 1.0, 1.0 );
return new AxisAlignedBB( 0.0, 0.0, 0.0, thickness, 1.0, 1.0 );
default:
throw new IllegalArgumentException( "Unsupported face: " + side );
}
@@ -19,14 +19,11 @@
package appeng.container;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
@@ -37,8 +34,6 @@ import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.PlayerInvWrapper;
@@ -73,7 +68,7 @@ import appeng.container.slot.SlotPlayerInv;
import appeng.core.AELog;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.core.sync.packets.PacketPartialItem;
import appeng.core.sync.packets.PacketTargetItemStack;
import appeng.core.sync.packets.PacketValueConfig;
import appeng.helpers.ICustomNameObject;
import appeng.helpers.InventoryAction;
@@ -93,7 +88,6 @@ public abstract class AEBaseContainer extends Container
private final TileEntity tileEntity;
private final IPart part;
private final IGuiItemObject obj;
private final List<PacketPartialItem> dataChunks = new LinkedList<>();
private final HashMap<Integer, SyncData> syncData = new HashMap<>();
private boolean isContainerValid = true;
private String customName;
@@ -175,47 +169,6 @@ public abstract class AEBaseContainer extends Container
this.prepareSync();
}
public void postPartial( final PacketPartialItem packetPartialItem )
{
this.dataChunks.add( packetPartialItem );
if( packetPartialItem.getPageCount() == this.dataChunks.size() )
{
this.parsePartials();
}
}
private void parsePartials()
{
int total = 0;
for( final PacketPartialItem ppi : this.dataChunks )
{
total += ppi.getSize();
}
final byte[] buffer = new byte[total];
int cursor = 0;
for( final PacketPartialItem ppi : this.dataChunks )
{
cursor = ppi.write( buffer, cursor );
}
try
{
final NBTTagCompound data = CompressedStreamTools.readCompressed( new ByteArrayInputStream( buffer ) );
if( data != null )
{
this.setTargetStack( AEItemStack.fromNBT( data ) );
}
}
catch( final IOException e )
{
AELog.debug( e );
}
this.dataChunks.clear();
}
public IAEItemStack getTargetStack()
{
return this.clientRequestedTargetItem;
@@ -235,47 +188,7 @@ public abstract class AEBaseContainer extends Container
return;
}
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
final NBTTagCompound item = new NBTTagCompound();
if( stack != null )
{
stack.writeToNBT( item );
}
try
{
CompressedStreamTools.writeCompressed( item, stream );
final int maxChunkSize = 30000;
final List<byte[]> miniPackets = new LinkedList<>();
final byte[] data = stream.toByteArray();
final ByteArrayInputStream bis = new ByteArrayInputStream( data, 0, stream.size() );
while( bis.available() > 0 )
{
final int nextBLock = bis.available() > maxChunkSize ? maxChunkSize : bis.available();
final byte[] nextSegment = new byte[nextBLock];
bis.read( nextSegment );
miniPackets.add( nextSegment );
}
bis.close();
stream.close();
int page = 0;
for( final byte[] packet : miniPackets )
{
final PacketPartialItem ppi = new PacketPartialItem( page, miniPackets.size(), packet );
page++;
NetworkHandler.instance().sendToServer( ppi );
}
}
catch( final IOException e )
{
AELog.debug( e );
return;
}
NetworkHandler.instance().sendToServer( new PacketTargetItemStack( (AEItemStack) stack ) );
}
this.clientRequestedTargetItem = stack == null ? null : stack.copy();
@@ -120,28 +120,23 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
if( s == this.middle )
{
for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() )
IItemDefinition press = AEApi.instance().definitions().materials().namePress();
if( press.isSameAs( top ) || press.isSameAs( bot ) )
{
if( Platform.itemComparisons().isSameItem( optional, is ) )
{
return false;
}
return !press.isSameAs( is );
}
boolean matches = false;
boolean found = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() )
{
final boolean matchA = ( top.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top,
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and...
( ( bot.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot,
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) );
final boolean matchB = ( bot.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot,
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and...
( ( top.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top,
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) );
final boolean matchA = !top
.isEmpty() && ( Platform.itemComparisons().isSameItem( top, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
.itemComparisons()
.isSameItem( top, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
final boolean matchB = !bot
.isEmpty() && ( Platform.itemComparisons().isSameItem( bot, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
.itemComparisons()
.isSameItem( bot, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
if( matchA || matchB )
{
@@ -150,21 +145,19 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
{
if( Platform.itemComparisons().isSameItem( is, option ) )
{
found = true;
return true;
}
}
}
}
if( matches && !found )
if( matches )
{
return false;
}
}
if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
else if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
{
ItemStack otherSlot = ItemStack.EMPTY;
ItemStack otherSlot;
if( s == this.top )
{
otherSlot = this.bottom.getStack();
@@ -182,28 +175,24 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
}
// everything else
boolean isValid = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() )
{
if( Platform.itemComparisons().isSameItem( recipe.getTopOptional().orElse( ItemStack.EMPTY ), otherSlot ) )
boolean isValid = false;
if( Platform.itemComparisons().isSameItem( otherSlot, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) )
{
isValid = Platform.itemComparisons().isSameItem( is, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) );
}
else if( Platform.itemComparisons().isSameItem( recipe.getBottomOptional().orElse( ItemStack.EMPTY ), otherSlot ) )
else if( Platform.itemComparisons().isSameItem( otherSlot, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) )
{
isValid = Platform.itemComparisons().isSameItem( is, recipe.getTopOptional().orElse( ItemStack.EMPTY ) );
}
if( isValid )
{
break;
return true;
}
}
if( !isValid )
{
return false;
}
return false;
}
return true;
@@ -172,7 +172,7 @@ public class SlotRestrictedInput extends AppEngSlot
for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() )
{
if( Platform.itemComparisons().isSameItem( optional, i ) )
if( Platform.itemComparisons().isSameItem( i, optional ) )
{
return true;
}
+2
View File
@@ -189,6 +189,8 @@ public final class AppEng
AppEng.proxy.preinit();
}
IntegrationRegistry.INSTANCE.preInit();
if( versionCheckerConfig.isVersionCheckingEnabled() )
{
final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig );
+1 -1
View File
@@ -59,7 +59,7 @@ public class ApiGrid implements IGridHelper
Preconditions.checkNotNull( a );
Preconditions.checkNotNull( b );
return new GridConnection( a, b, AEPartLocation.INTERNAL );
return GridConnection.create( a, b, AEPartLocation.INTERNAL );
}
}
@@ -118,7 +118,7 @@ public enum GuiText
RequiredPower,
Efficiency,
SCSSize,
SCSSInvalid,
SCSInvalid,
InWorldCrafting,
inWorldFluix,
@@ -41,11 +41,11 @@ import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion;
import appeng.core.sync.packets.PacketPaintedEntity;
import appeng.core.sync.packets.PacketPartPlacement;
import appeng.core.sync.packets.PacketPartialItem;
import appeng.core.sync.packets.PacketPatternSlot;
import appeng.core.sync.packets.PacketProgressBar;
import appeng.core.sync.packets.PacketSwapSlots;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketTargetItemStack;
import appeng.core.sync.packets.PacketTransitionEffect;
import appeng.core.sync.packets.PacketValueConfig;
@@ -90,7 +90,7 @@ public class AppEngPacketHandlerBase
PACKET_RECIPE_JEI( PacketJEIRecipe.class ),
PACKET_PARTIAL_ITEM( PacketPartialItem.class ),
PACKET_TARGET_ITEM( PacketTargetItemStack.class ),
PACKET_CRAFTING_REQUEST( PacketCraftRequest.class ),
@@ -41,6 +41,7 @@ import appeng.api.config.Actionable;
import appeng.api.config.SecurityPermissions;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.storage.IStorageGrid;
@@ -132,6 +133,7 @@ public class PacketJEIRecipe extends AppEngPacket
final IStorageGrid inv = grid.getCache( IStorageGrid.class );
final IEnergyGrid energy = grid.getCache( IEnergyGrid.class );
final ISecurityGrid security = grid.getCache( ISecurityGrid.class );
final ICraftingGrid crafting = grid.getCache( ICraftingGrid.class );
final IItemHandler craftMatrix = cct.getInventoryByName( "crafting" );
final IItemHandler playerInventory = cct.getInventoryByName( "player" );
@@ -179,13 +181,23 @@ public class PacketJEIRecipe extends AppEngPacket
{
request.setStackSize( 1 );
IAEItemStack out;
if( cct.useRealItems() )
{
out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() );
}
else
{
out = storage.extractItems( request, Actionable.SIMULATE, cct.getActionSource() );
// Query the crafting grid if there is a pattern providing the item
if( !crafting.getCraftingFor( request, null, 0, null ).isEmpty() )
{
out = request;
}
else
{
// Fall back using an existing item
out = storage.extractItems( request, Actionable.SIMULATE, cct.getActionSource() );
}
}
if( out != null )
@@ -25,35 +25,56 @@ import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer;
import appeng.container.AEBaseContainer;
import appeng.core.AELog;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.util.item.AEItemStack;
public class PacketPartialItem extends AppEngPacket
public class PacketTargetItemStack extends AppEngPacket
{
private final short pageNum;
private final byte[] data;
private AEItemStack stack;
// automatic.
public PacketPartialItem( final ByteBuf stream )
public PacketTargetItemStack( final ByteBuf stream )
{
this.pageNum = stream.readShort();
stream.readBytes( this.data = new byte[stream.readableBytes()] );
try
{
if( stream.readableBytes() > 0 )
{
this.stack = AEItemStack.fromPacket( stream );
}
else
{
this.stack = null;
}
}
catch( Exception ex )
{
AELog.debug( ex );
this.stack = null;
}
}
// api
public PacketPartialItem( final int page, final int maxPages, final byte[] buf )
public PacketTargetItemStack( AEItemStack stack )
{
this.stack = stack;
final ByteBuf data = Unpooled.buffer();
this.pageNum = (short) ( page | ( maxPages << 8 ) );
this.data = buf;
data.writeInt( this.getPacketID() );
data.writeShort( this.pageNum );
data.writeBytes( buf );
if( stack != null )
{
try
{
stack.writeToPacket( data );
}
catch( Exception ex )
{
AELog.debug( ex );
}
}
this.configureWrite( data );
}
@@ -62,23 +83,8 @@ public class PacketPartialItem extends AppEngPacket
{
if( player.openContainer instanceof AEBaseContainer )
{
( (AEBaseContainer) player.openContainer ).postPartial( this );
( (AEBaseContainer) player.openContainer ).setTargetStack( this.stack );
}
}
public int getPageCount()
{
return this.pageNum >> 8;
}
public int getSize()
{
return this.data.length;
}
public int write( final byte[] buffer, final int cursor )
{
System.arraycopy( this.data, 0, buffer, cursor, this.data.length );
return cursor + this.data.length;
}
}
@@ -363,7 +363,7 @@ public class CraftingTreeNode
if( this.howManyEmitted > 0 )
{
final IAEItemStack i = this.what.copy();
final IAEItemStack i = this.what.copy().reset();
i.setStackSize( this.howManyEmitted );
craftingCPUCluster.addEmitable( i );
}
@@ -19,6 +19,8 @@
package appeng.entity;
import java.util.List;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
@@ -136,19 +138,20 @@ public final class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntit
return;
}
for( final Object e : this.world.getEntitiesWithinAABBExcludingEntity( this,
new AxisAlignedBB( this.posX - 1.5, this.posY - 1.5f, this.posZ - 1.5, this.posX + 1.5, this.posY + 1.5, this.posZ + 1.5 ) ) )
final Explosion ex = new Explosion( this.world, this, this.posX, this.posY, this.posZ, 0.2f, false, false );
final AxisAlignedBB area = new AxisAlignedBB( this.posX - 1.5, this.posY - 1.5f, this.posZ - 1.5, this.posX + 1.5, this.posY + 1.5, this.posZ + 1.5 );
final List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity( this, area );
net.minecraftforge.event.ForgeEventFactory.onExplosionDetonate( this.world, ex, list, 0.2f * 2d );
for( final Entity e : list )
{
if( e instanceof Entity )
{
( (Entity) e ).attackEntityFrom( DamageSource.causeExplosionDamage( (Explosion) null ), 6 );
}
e.attackEntityFrom( DamageSource.causeExplosionDamage( ex ), 6 );
}
if( AEConfig.instance().isFeatureEnabled( AEFeature.TINY_TNT_BLOCK_DAMAGE ) )
{
this.posY -= 0.25;
final Explosion ex = new Explosion( this.world, this, this.posX, this.posY, this.posZ, 0.2f, false, false );
for( int x = (int) ( this.posX - 2 ); x <= this.posX + 2; x++ )
{
@@ -159,6 +162,7 @@ public final class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntit
final BlockPos point = new BlockPos( x, y, z );
final IBlockState state = this.world.getBlockState( point );
final Block block = state.getBlock();
if( block != null && !block.isAir( state, this.world, point ) )
{
float strength = (float) ( 2.3f - ( ( ( x + 0.5f ) - this.posX ) * ( ( x + 0.5f ) - this.posX ) + ( ( y + 0.5f ) - this.posY ) * ( ( y + 0.5f ) - this.posY ) + ( ( z + 0.5f ) - this.posZ ) * ( ( z + 0.5f ) - this.posZ ) ) );
@@ -47,13 +47,16 @@ public enum IntegrationRegistry
this.modules.add( new IntegrationNode( type.dspName, type.modID, type ) );
}
public void init()
public void preInit()
{
for( final IntegrationNode node : this.modules )
{
node.call( IntegrationStage.PRE_INIT );
}
}
public void init()
{
for( final IntegrationNode node : this.modules )
{
node.call( IntegrationStage.INIT );
@@ -19,6 +19,7 @@
package appeng.integration;
import appeng.integration.modules.crafttweaker.CTModule;
import appeng.integration.modules.ic2.IC2Module;
import appeng.integration.modules.jei.JEIModule;
import appeng.integration.modules.theoneprobe.TheOneProbeModule;
@@ -73,7 +74,16 @@ public enum IntegrationType
}
},
TESLA( IntegrationSide.BOTH, "Tesla", "tesla" );
TESLA( IntegrationSide.BOTH, "Tesla", "tesla" ),
CRAFTTWEAKER( IntegrationSide.BOTH, "CraftTweaker", "crafttweaker" )
{
@Override
public IIntegrationModule createInstance()
{
return new CTModule();
}
};
public final IntegrationSide side;
public final String dspName;
@@ -0,0 +1,28 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.integration.abstraction;
import appeng.integration.IIntegrationModule;
public interface ICraftTweaker extends IIntegrationModule
{
}
@@ -0,0 +1,132 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.integration.modules.crafttweaker;
import crafttweaker.api.item.IIngredient;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.config.TunnelType;
import appeng.api.features.IP2PTunnelRegistry;
@ZenClass( "mods.appliedenergistics2.Attunement" )
public class AttunementRegistry
{
private AttunementRegistry()
{
}
@ZenMethod
public static void attuneME( IIngredient itemStack )
{
attune( itemStack, TunnelType.ME );
}
@ZenMethod
public static void attuneME( String modId )
{
attune( modId, TunnelType.ME );
}
@ZenMethod
public static void attuneItem( IIngredient itemStack )
{
attune( itemStack, TunnelType.ITEM );
}
@ZenMethod
public static void attuneItem( String modId )
{
attune( modId, TunnelType.ITEM );
}
@ZenMethod
public static void attuneFluid( IIngredient itemStack )
{
attune( itemStack, TunnelType.FLUID );
}
@ZenMethod
public static void attuneFluid( String modId )
{
attune( modId, TunnelType.FLUID );
}
@ZenMethod
public static void attuneRedstone( IIngredient itemStack )
{
attune( itemStack, TunnelType.REDSTONE );
}
@ZenMethod
public static void attuneRedstone( String modId )
{
attune( modId, TunnelType.REDSTONE );
}
@ZenMethod
public static void attuneRF( IIngredient itemStack )
{
attune( itemStack, TunnelType.FE_POWER );
}
@ZenMethod
public static void attuneRF( String modId )
{
attune( modId, TunnelType.FE_POWER );
}
@ZenMethod
public static void attuneIC2( IIngredient itemStack )
{
attune( itemStack, TunnelType.IC2_POWER );
}
@ZenMethod
public static void attuneIC2( String modId )
{
attune( modId, TunnelType.IC2_POWER );
}
@ZenMethod
public static void attuneLight( IIngredient itemStack )
{
attune( itemStack, TunnelType.LIGHT );
}
@ZenMethod
public static void attuneLight( String modId )
{
attune( modId, TunnelType.LIGHT );
}
private static void attune( IIngredient itemStack, TunnelType type )
{
IP2PTunnelRegistry registry = AEApi.instance().registries().p2pTunnel();
CTModule.toStacks( itemStack ).ifPresent( c -> c.forEach( i -> registry.addNewAttunement( i, type ) ) );
}
private static void attune( String modid, TunnelType type )
{
AEApi.instance().registries().p2pTunnel().addNewAttunement( modid, type );
}
}
@@ -0,0 +1,130 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.integration.modules.crafttweaker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraftforge.oredict.OreDictionary;
import crafttweaker.CraftTweakerAPI;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import appeng.integration.abstraction.ICraftTweaker;
import appeng.util.Platform;
public class CTModule implements ICraftTweaker
{
static final List<IAction> MODIFICATIONS = new ArrayList<>();
@Override
public void preInit()
{
CraftTweakerAPI.registerClass( GrinderRecipes.class );
CraftTweakerAPI.registerClass( InscriberRecipes.class );
CraftTweakerAPI.registerClass( SpatialRegistry.class );
CraftTweakerAPI.registerClass( AttunementRegistry.class );
CraftTweakerAPI.registerClass( CannonRegistry.class );
}
@Override
public void postInit()
{
MODIFICATIONS.forEach( CraftTweakerAPI::apply );
}
public static ItemStack toStack( IItemStack iStack )
{
if( iStack == null )
{
return ItemStack.EMPTY;
}
else
{
return (ItemStack) iStack.getInternal();
}
}
public static List<ItemStack> toStackExpand( IItemStack iStack )
{
if( iStack == null )
{
return Collections.emptyList();
}
else
{
ItemStack is = (ItemStack) iStack.getInternal();
if( !is.isItemStackDamageable() && is.getItemDamage() == OreDictionary.WILDCARD_VALUE )
{
NonNullList<ItemStack> ret = NonNullList.create();
is.getItem().getSubItems( CreativeTabs.SEARCH, ret );
return ret.stream().map( i -> new ItemStack( i.getItem(), iStack.getAmount(), i.getItemDamage() ) ).collect( Collectors.toList() );
}
else
{
return Collections.singletonList( is );
}
}
}
public static Optional<Collection<ItemStack>> toStacks( IIngredient ingredient )
{
if( ingredient == null )
{
return Optional.empty();
}
Set<ItemStack> ret = new TreeSet<>( CTModule::compareItemStacks );
ingredient.getItems().stream().map( CTModule::toStackExpand ).forEach( ret::addAll );
if( ret.isEmpty() )
{
return Optional.empty();
}
return Optional.of( ret );
}
private static int compareItemStacks( ItemStack a, ItemStack b )
{
if( Platform.itemComparisons().isSameItem( a, b ) )
{
return 0;
}
if( a == null )
{
return -1;
}
if( b == null )
{
return 1;
}
return System.identityHashCode( a ) - System.identityHashCode( b );
}
}
@@ -0,0 +1,43 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.integration.modules.crafttweaker;
import crafttweaker.api.item.IIngredient;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IMatterCannonAmmoRegistry;
@ZenClass( "mods.appliedenergistics2.Cannon" )
public class CannonRegistry
{
private CannonRegistry()
{
}
@ZenMethod
public static void registerAmmo( IIngredient itemStack, double weight )
{
IMatterCannonAmmoRegistry registry = AEApi.instance().registries().matterCannon();
CTModule.toStacks( itemStack ).ifPresent( c -> c.forEach( i -> registry.registerAmmo( i, weight ) ) );
}
}
@@ -0,0 +1,127 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.integration.modules.crafttweaker;
import java.util.Collection;
import java.util.Collections;
import net.minecraft.item.ItemStack;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IGrinderRecipe;
import appeng.api.features.IGrinderRecipeBuilder;
@ZenClass( "mods.appliedenergistics2.Grinder" )
public class GrinderRecipes
{
private GrinderRecipes()
{
}
@ZenMethod
public static void addRecipe( IItemStack output, IIngredient input, int turns, @stanhebben.zenscript.annotations.Optional IItemStack secondary1Output, @stanhebben.zenscript.annotations.Optional Float secondary1Chance, @stanhebben.zenscript.annotations.Optional IItemStack secondary2Output, @stanhebben.zenscript.annotations.Optional Float secondary2Chance )
{
Collection<ItemStack> inStacks = CTModule.toStacks( input ).orElse( Collections.emptySet() );
for( ItemStack inStack : inStacks )
{
IGrinderRecipeBuilder builder = AEApi.instance().registries().grinder().builder();
builder.withInput( inStack )
.withOutput( CTModule.toStack( output ) )
.withTurns( turns );
final ItemStack s1 = CTModule.toStack( secondary1Output );
if( !s1.isEmpty() )
{
builder.withFirstOptional( s1, secondary1Chance == null ? 1.0f : secondary1Chance );
}
final ItemStack s2 = CTModule.toStack( secondary2Output );
if( !s2.isEmpty() )
{
builder.withFirstOptional( s2, secondary2Chance == null ? 1.0f : secondary2Chance );
}
CTModule.MODIFICATIONS.add( new Add( builder.build() ) );
}
}
@ZenMethod
public static void removeRecipe( IIngredient input )
{
for( ItemStack inStack : CTModule.toStacks( input ).orElse( Collections.emptySet() ) )
{
CTModule.MODIFICATIONS.add( new Remove( inStack ) );
}
}
private static class Add implements IAction
{
private final IGrinderRecipe entry;
private Add( IGrinderRecipe entry )
{
this.entry = entry;
}
@Override
public void apply()
{
AEApi.instance().registries().grinder().addRecipe( entry );
}
@Override
public String describe()
{
return "Adding Grinder Entry for " + entry.getInput().getDisplayName();
}
}
private static class Remove implements IAction
{
private final ItemStack stack;
private Remove( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
IGrinderRecipe recipe = AEApi.instance().registries().grinder().getRecipeForInput( stack );
if( recipe != null )
{
AEApi.instance().registries().grinder().removeRecipe( recipe );
}
}
@Override
public String describe()
{
return "Removing Grinder Entry for " + stack.getDisplayName();
}
}
}
@@ -0,0 +1,138 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.integration.modules.crafttweaker;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.item.ItemStack;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IInscriberRecipe;
import appeng.api.features.IInscriberRecipeBuilder;
import appeng.api.features.IInscriberRegistry;
import appeng.api.features.InscriberProcessType;
@ZenClass( "mods.appliedenergistics2.Inscriber" )
public class InscriberRecipes
{
private InscriberRecipes()
{
}
@ZenMethod
public static void addRecipe( IItemStack output, IIngredient input, boolean inscribe, @stanhebben.zenscript.annotations.Optional IIngredient top, @stanhebben.zenscript.annotations.Optional IIngredient bottom )
{
Optional<Collection<ItemStack>> inStacks = CTModule.toStacks( input );
if( !inStacks.isPresent() )
{
return;
}
Collection<ItemStack> topList = CTModule.toStacks( top ).orElse( Collections.singleton( ItemStack.EMPTY ) );
Collection<ItemStack> bottomList = CTModule.toStacks( bottom ).orElse( Collections.singleton( ItemStack.EMPTY ) );
for( ItemStack topStack : topList )
{
for( ItemStack bottomStack : bottomList )
{
final IInscriberRecipeBuilder builder = AEApi.instance().registries().inscriber().builder();
builder.withProcessType( inscribe ? InscriberProcessType.INSCRIBE : InscriberProcessType.PRESS )
.withOutput( CTModule.toStack( output ) )
.withInputs( inStacks.get() );
if( !topStack.isEmpty() )
{
builder.withTopOptional( topStack );
}
if( !bottomStack.isEmpty() )
{
builder.withBottomOptional( bottomStack );
}
CTModule.MODIFICATIONS.add( new Add( builder.build() ) );
}
}
}
@ZenMethod
public static void removeRecipe( IItemStack output )
{
CTModule.MODIFICATIONS.add( new Remove( (ItemStack) output.getInternal() ) );
}
private static class Add implements IAction
{
private final IInscriberRecipe entry;
private Add( IInscriberRecipe entry )
{
this.entry = entry;
}
@Override
public void apply()
{
AEApi.instance().registries().inscriber().addRecipe( entry );
}
@Override
public String describe()
{
return "Adding Inscriber Entry for " + entry.getOutput().getDisplayName();
}
}
private static class Remove implements IAction
{
private final ItemStack stack;
private Remove( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
final IInscriberRegistry inscriber = AEApi.instance().registries().inscriber();
inscriber.getRecipes()
.stream()
.filter( r -> r.getOutput().isItemEqual( this.stack ) )
.collect( Collectors.toList() )
.forEach( inscriber::removeRecipe );
}
@Override
public String describe()
{
return "Removing Inscriber Entry for " + stack.getDisplayName();
}
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.integration.modules.crafttweaker;
import net.minecraft.tileentity.TileEntity;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.core.AELog;
@ZenClass( "mods.appliedenergistics2.Spatial" )
public class SpatialRegistry
{
private SpatialRegistry()
{
}
@ZenMethod
public static void whitelistEntity( String entityClassName )
{
Class<? extends TileEntity> entityClass = loadClass( entityClassName );
if( entityClass != null )
{
AEApi.instance().registries().movable().whiteListTileEntity( entityClass );
}
}
@SuppressWarnings( "unchecked" )
private static Class<? extends TileEntity> loadClass( String className )
{
try
{
return (Class<? extends TileEntity>) Class.forName( className );
}
catch( Exception e )
{
AELog.warn( e, "Failed to load TileEntity class '" + className + "'" );
}
return null;
}
}
@@ -54,13 +54,12 @@ public class NetworkToolViewer implements INetworkTool, IAEAppEngInventory
@Override
public void saveChanges()
{
this.inv.markDirty( -1 );
this.inv.writeToNBT( Platform.openNbtData( this.is ), "inv" );
}
@Override
public void onChangeInventory( IItemHandler inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack )
{
this.inv.writeToNBT( Platform.openNbtData( this.is ), "inv" );
}
@Override
@@ -219,13 +219,11 @@ public class ToolNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench,
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{
user.swingArm( user.getActiveHand() );
}
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{
user.swingArm( user.getActiveHand() );
}
// IToolHammer - end
@@ -85,21 +85,10 @@ class PoweredItemCapabilities implements ICapabilityProvider, IEnergyStorage
@Override
public int receiveEnergy( int maxReceive, boolean simulate )
{
if( simulate )
{
final int required = (int) PowerUnits.AE.convertTo( PowerUnits.RF, this.item.getAEMaxPower( this.is ) - this.item.getAECurrentPower( this.is ) );
final double convertedOffer = PowerUnits.RF.convertTo( PowerUnits.AE, maxReceive );
final double overflow = this.item.injectAEPower( this.is, convertedOffer, simulate ? Actionable.SIMULATE : Actionable.MODULATE );
if( maxReceive < required )
{
return 0;
}
return maxReceive - required;
}
else
{
final double powerRemainder = this.item.injectAEPower( this.is, PowerUnits.RF.convertTo( PowerUnits.AE, maxReceive ), Actionable.MODULATE );
return maxReceive - (int) PowerUnits.AE.convertTo( PowerUnits.RF, powerRemainder );
}
return maxReceive - (int) PowerUnits.AE.convertTo( PowerUnits.RF, overflow );
}
@Override
@@ -103,14 +103,13 @@ public class ToolQuartzWrench extends AEBaseItem implements IAEWrench, IToolHamm
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{
user.swingArm( user.getActiveHand() );
}
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{
user.swingArm( user.getActiveHand() );
}
// IToolHammer - end
// TODO: BC Wrench Integration
+80 -72
View File
@@ -54,80 +54,11 @@ public class GridConnection implements IGridConnection, IPathItem
private AEPartLocation fromAtoB;
private GridNode sideB;
public GridConnection( final IGridNode aNode, final IGridNode bNode, final AEPartLocation fromAtoB ) throws FailedConnectionException
private GridConnection( final GridNode aNode, final GridNode bNode, final AEPartLocation fromAtoB )
{
final GridNode a = (GridNode) aNode;
final GridNode b = (GridNode) bNode;
if( Platform.securityCheck( a, b ) )
{
if( AEConfig.instance().isFeatureEnabled( AEFeature.LOG_SECURITY_AUDITS ) )
{
final DimensionalCoord aCoordinates = a.getGridBlock().getLocation();
final DimensionalCoord bCoordinates = b.getGridBlock().getLocation();
AELog.info( "Security audit 1 failed at [%s] belonging to player [id=%d]", aCoordinates.toString(), a.getPlayerID() );
AELog.info( "Security audit 2 failed at [%s] belonging to player [id=%d]", bCoordinates.toString(), b.getPlayerID() );
}
throw new SecurityConnectionException();
}
if( a == null || b == null )
{
throw new NullNodeConnectionException();
}
if( a.hasConnection( b ) || b.hasConnection( a ) )
{
final String aMachineClass = a.getGridBlock().getMachine().getClass().getSimpleName();
final String bMachineClass = b.getGridBlock().getMachine().getClass().getSimpleName();
final String aCoordinates = a.getGridBlock().getLocation().toString();
final String bCoordinates = b.getGridBlock().getLocation().toString();
throw new ExistingConnectionException( String.format( EXISTING_CONNECTION_MESSAGE, aMachineClass, aCoordinates, bMachineClass, bCoordinates,
fromAtoB ) );
}
this.sideA = a;
this.sideA = aNode;
this.fromAtoB = fromAtoB;
this.sideB = b;
if( b.getMyGrid() == null )
{
b.setGrid( a.getInternalGrid() );
}
else
{
if( a.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
a.beginVisit( gp );
}
else if( b.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
b.beginVisit( gp );
}
else if( this.isNetworkABetter( a, b ) )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
b.beginVisit( gp );
}
else
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
a.beginVisit( gp );
}
}
// a connection was destroyed RE-PATH!!
final IPathingGrid p = this.sideA.getInternalGrid().getCache( IPathingGrid.class );
p.repath();
this.sideA.addConnection( this );
this.sideB.addConnection( this );
this.sideB = bNode;
}
private boolean isNetworkABetter( final GridNode a, final GridNode b )
@@ -291,4 +222,81 @@ public class GridConnection implements IGridConnection, IPathItem
{
this.visitorIterationNumber = visitorIterationNumber;
}
public static GridConnection create( final IGridNode aNode, final IGridNode bNode, final AEPartLocation fromAtoB ) throws FailedConnectionException
{
if( aNode == null || bNode == null )
{
throw new NullNodeConnectionException();
}
final GridNode a = (GridNode) aNode;
final GridNode b = (GridNode) bNode;
if( a.hasConnection( b ) || b.hasConnection( a ) )
{
final String aMachineClass = a.getGridBlock().getMachine().getClass().getSimpleName();
final String bMachineClass = b.getGridBlock().getMachine().getClass().getSimpleName();
final String aCoordinates = a.getGridBlock().getLocation().toString();
final String bCoordinates = b.getGridBlock().getLocation().toString();
throw new ExistingConnectionException( String.format( EXISTING_CONNECTION_MESSAGE, aMachineClass, aCoordinates, bMachineClass, bCoordinates,
fromAtoB ) );
}
if( !Platform.securityCheck( a, b ) )
{
if( AEConfig.instance().isFeatureEnabled( AEFeature.LOG_SECURITY_AUDITS ) )
{
final DimensionalCoord aCoordinates = a.getGridBlock().getLocation();
final DimensionalCoord bCoordinates = b.getGridBlock().getLocation();
AELog.info( "Security audit 1 failed at [%s] belonging to player [id=%d]", aCoordinates.toString(), a.getPlayerID() );
AELog.info( "Security audit 2 failed at [%s] belonging to player [id=%d]", bCoordinates.toString(), b.getPlayerID() );
}
throw new SecurityConnectionException();
}
// Create the actual connection
final GridConnection connection = new GridConnection( a, b, fromAtoB );
// Update both nodes with the new connection.
if( a.getMyGrid() == null )
{
b.setGrid( a.getInternalGrid() );
}
else
{
if( a.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
aNode.beginVisit( gp );
}
else if( b.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
bNode.beginVisit( gp );
}
else if( connection.isNetworkABetter( a, b ) )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
b.beginVisit( gp );
}
else
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
a.beginVisit( gp );
}
}
// a connection was destroyed RE-PATH!!
final IPathingGrid p = connection.sideA.getInternalGrid().getCache( IPathingGrid.class );
p.repath();
connection.sideA.addConnection( connection );
connection.sideB.addConnection( connection );
return connection;
}
}
+23 -6
View File
@@ -33,6 +33,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.exceptions.FailedConnectionException;
import appeng.api.exceptions.SecurityConnectionException;
import appeng.api.networking.GridFlags;
import appeng.api.networking.GridNotification;
import appeng.api.networking.IGrid;
@@ -50,6 +51,7 @@ import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.IReadOnlyCollection;
import appeng.core.AELog;
import appeng.core.worlddata.WorldData;
import appeng.hooks.TickHandler;
import appeng.me.pathfinding.IPathItem;
@@ -216,7 +218,7 @@ public class GridNode implements IGridNode, IPathItem
this.compressedData |= ( 1 << ( dir.ordinal() + 8 ) );
}
this.FindConnections();
this.findConnections();
this.getInternalGrid();
}
@@ -393,7 +395,7 @@ public class GridNode implements IGridNode, IPathItem
return this.usedChannels;
}
private void FindConnections()
private void findConnections()
{
if( !this.gridProxy.isWorldAccessible() )
{
@@ -455,11 +457,18 @@ public class GridNode implements IGridNode, IPathItem
// construct a new connection between these two nodes.
try
{
new GridConnection( node, this, f.getOpposite() );
GridConnection.create( node, this, f.getOpposite() );
}
catch( SecurityConnectionException e )
{
AELog.debug( e );
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
return;
}
catch( final FailedConnectionException e )
{
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
AELog.debug( e );
return;
}
@@ -482,11 +491,19 @@ public class GridNode implements IGridNode, IPathItem
// construct a new connection between these two nodes.
try
{
new GridConnection( node, this, f.getOpposite() );
GridConnection.create( node, this, f.getOpposite() );
}
catch( SecurityConnectionException e )
{
AELog.debug( e );
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
return;
}
catch( final FailedConnectionException e )
{
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
AELog.debug( e );
return;
}
@@ -440,7 +440,6 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
this.lastTime = 0;
this.elapsedTime = 0;
this.isComplete = true;
}
private void updateCPU()
@@ -38,6 +38,7 @@ import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.util.AEPartLocation;
import appeng.api.util.WorldCoord;
import appeng.core.AELog;
import appeng.me.cache.helpers.ConnectionWrapper;
import appeng.me.cluster.IAECluster;
import appeng.tile.qnb.TileQuantumBridge;
@@ -161,6 +162,7 @@ public class QuantumCluster implements ILocatable, IAECluster
catch( final FailedConnectionException e )
{
// :(
AELog.debug( e );
}
}
else
@@ -241,11 +241,11 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{
try
{
new GridConnection( cn, sn, AEPartLocation.INTERNAL );
GridConnection.create( cn, sn, AEPartLocation.INTERNAL );
}
catch( final FailedConnectionException e )
{
// ekk!
AELog.debug( e );
bp.removeFromWorld();
this.setCenter( null );
@@ -292,11 +292,11 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{
try
{
new GridConnection( cn, sn, AEPartLocation.INTERNAL );
GridConnection.create( cn, sn, AEPartLocation.INTERNAL );
}
catch( final FailedConnectionException e )
{
// ekk!
AELog.debug( e );
bp.removeFromWorld();
this.setSide( side, null );
@@ -637,6 +637,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
catch( final FailedConnectionException e )
{
// ekk
AELog.debug( e );
}
}
}
@@ -1087,7 +1088,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
this.getFacadeContainer().readFromNBT( data );
}
public List getDrops( final List drops )
public List<ItemStack> getDrops( final List<ItemStack> drops )
{
for( final AEPartLocation s : AEPartLocation.values() )
{
@@ -1111,7 +1112,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
return drops;
}
public List getNoDrops( final List drops )
public List<ItemStack> getNoDrops( final List<ItemStack> drops )
{
for( final AEPartLocation s : AEPartLocation.values() )
{
@@ -1150,12 +1151,15 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
@Override
public CableBusRenderState getRenderState()
{
PartCable cable = (PartCable) this.getCenter();
final PartCable cable = (PartCable) this.getCenter();
CableBusRenderState renderState = new CableBusRenderState();
final CableBusRenderState renderState = new CableBusRenderState();
if( cable != null )
{
final boolean isSmart = cable.getCableConnectionType() == AECableType.SMART || cable.getCableConnectionType() == AECableType.DENSE_SMART;
final boolean isDense = cable.getCableConnectionType() == AECableType.DENSE_COVERED || cable.getCableConnectionType() == AECableType.DENSE_SMART;
renderState.setCableColor( cable.getCableColor() );
renderState.setCableType( cable.getCableConnectionType() );
renderState.setCoreType( CableCoreType.fromCableType( cable.getCableConnectionType() ) );
@@ -1175,12 +1179,12 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// Only use the incoming cable-type of the adjacent block, if it's not a cable bus itself
// Dense cables however also respect the adjacent cable-type since their outgoing connection
// point would look too big for other cable types
BlockPos adjacentPos = this.getTile().getPos().offset( facing );
TileEntity adjacentTe = this.getTile().getWorld().getTileEntity( adjacentPos );
final BlockPos adjacentPos = this.getTile().getPos().offset( facing );
final TileEntity adjacentTe = this.getTile().getWorld().getTileEntity( adjacentPos );
if( adjacentTe instanceof IGridHost )
{
if( !( adjacentTe instanceof IPartHost ) || cable.getCableConnectionType() == AECableType.DENSE_SMART || cable
.getCableConnectionType() == AECableType.DENSE_COVERED )
if( !( adjacentTe instanceof IPartHost ) || isDense )
{
IGridHost gridHost = (IGridHost) adjacentTe;
connectionType = gridHost.getCableConnectionType( AEPartLocation.fromFacing( facing.getOpposite() ) );
@@ -1201,7 +1205,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// adjacent tile requires it
for( EnumFacing facing : EnumFacing.values() )
{
int channels = cable.getChannelsOnSide( facing );
int channels = isSmart ? cable.getChannelsOnSide( facing ) : 0;
renderState.getChannelsOnSide().put( facing, channels );
}
}
@@ -1209,14 +1213,14 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// Determine attachments and facades
for( EnumFacing facing : EnumFacing.values() )
{
final FacadeRenderState facadeState = this.getFacadeRenderState( facing );
FacadeRenderState facadeState = this.getFacadeRenderState( facing );
if( facadeState != null )
{
renderState.getFacades().put( facing, facadeState );
}
IPart part = this.getPart( facing );
final IPart part = this.getPart( facing );
if( part == null )
{
@@ -1224,15 +1228,17 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
}
// This will add the part's bounding boxes to the render state, which is required for facades
AEPartLocation loc = AEPartLocation.fromFacing( facing );
IPartCollisionHelper bch = new BusCollisionHelper( renderState.getBoundingBoxes(), loc, null, true );
final AEPartLocation loc = AEPartLocation.fromFacing( facing );
final IPartCollisionHelper bch = new BusCollisionHelper( renderState.getBoundingBoxes(), loc, null, true );
part.getBoxes( bch );
if( part instanceof IGridHost )
{
// Some attachments want a thicker cable than glass, account for that
IGridHost gridHost = (IGridHost) part;
AECableType desiredType = gridHost.getCableConnectionType( AEPartLocation.INTERNAL );
final IGridHost gridHost = (IGridHost) part;
final AECableType desiredType = gridHost.getCableConnectionType( AEPartLocation.INTERNAL );
if( renderState.getCoreType() == CableCoreType.GLASS && ( desiredType == AECableType.SMART || desiredType == AECableType.COVERED ) )
{
renderState.setCoreType( CableCoreType.COVERED );
@@ -1254,14 +1260,16 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
private FacadeRenderState getFacadeRenderState( EnumFacing side )
{
// Store the "masqueraded" itemstack for the given side, if there is a facade
IFacadePart facade = this.getFacade( side.ordinal() );
final IFacadePart facade = this.getFacade( side.ordinal() );
if( facade != null )
{
ItemStack textureItem = facade.getTextureItem();
IBlockState blockState = facade.getBlockState();
final ItemStack textureItem = facade.getTextureItem();
final IBlockState blockState = facade.getBlockState();
if( blockState != null && textureItem != null )
{
EnumSet<EnumFacing> openFaces = this.calculateFaceOpenFaces( side );
final EnumSet<EnumFacing> openFaces = this.calculateFaceOpenFaces( side );
return new FacadeRenderState( blockState, openFaces, textureItem );
}
}
@@ -1273,9 +1281,9 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{
final EnumSet<EnumFacing> out = EnumSet.of( side, side.getOpposite() );
final IFacadePart facade = this.getFacade( side.ordinal() );
final IBlockAccess blockAccess = this.getTile().getWorld();
final BlockPos pos = this.getTile().getPos();
IBlockAccess blockAccess = this.getTile().getWorld();
BlockPos pos = this.getTile().getPos();
for( final EnumFacing it : EnumFacing.values() )
{
if( !out.contains( it ) && this.hasAlphaDiff( blockAccess.getTileEntity( pos.offset( it ) ), side, facade ) )
@@ -29,6 +29,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemBlockSpecial;
import net.minecraft.item.ItemFirework;
import net.minecraft.item.ItemSkull;
import net.minecraft.item.ItemStack;
@@ -452,32 +453,14 @@ public class PartFormationPlane extends PartUpgradeable implements ICellContaine
if( w.getBlockState( tePos ).getBlock().isReplaceable( w, tePos ) )
{
if( placeBlock == YesNo.YES && ( i instanceof ItemBlock || i instanceof IPlantable || i instanceof ItemSkull || i instanceof ItemFirework || i instanceof IPartItem || i == Item
.getItemFromBlock(
Blocks.REEDS ) ) )
if( placeBlock == YesNo.YES && ( i instanceof ItemBlock || i instanceof ItemBlockSpecial || i instanceof IPlantable || i instanceof ItemSkull || i instanceof ItemFirework || i instanceof IPartItem || i == Item
.getItemFromBlock( Blocks.REEDS ) ) )
{
final EntityPlayer player = Platform.getPlayer( (WorldServer) w );
Platform.configurePlayer( player, side, this.getTile() );
EnumHand hand = player.getActiveHand();
player.setHeldItem( hand, is );
// TODO: LIMIT FIREWORKS
/*
* if( i instanceof ItemFirework )
* {
* Chunk c = w.getChunkFromBlockCoords( tePos );
* int sum = 0;
* for( List Z : c.geten )
* {
* sum += Z.size();
* }
* if( sum > 32 )
* {
* return input;
* }
* }
*/
maxStorage = is.getCount();
worked = true;
if( type == Actionable.MODULATE )
@@ -29,7 +29,6 @@ import net.minecraft.util.math.Vec3d;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings;
import appeng.api.config.Upgrades;
@@ -41,7 +40,6 @@ import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartModel;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
@@ -72,9 +70,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/import_bus_has_channel" ) );
private final IActionSource source;
private IMEInventory<IAEItemStack> destination = null;
private IAEItemStack lastItemChecked = null;
private int itemToSend; // used in tickingRequest
private int itemsToSend; // used in tickingRequest
private boolean worked; // used in tickingRequest
@Reflected
@@ -95,14 +91,24 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
return false;
}
final IAEItemStack out = this.destination.injectItems(
this.lastItemChecked = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( stack ), Actionable.SIMULATE,
this.source );
if( out == null )
try
{
return true;
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage().getInventory(
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
final IAEItemStack out = inv.injectItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( stack ),
Actionable.SIMULATE,
this.source );
if( out == null )
{
return true;
}
return out.getStackSize() != stack.getCount();
}
catch( GridAccessException ex )
{
return false;
}
return out.getStackSize() != stack.getCount();
}
@Override
@@ -165,9 +171,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
{
try
{
this.itemToSend = this.calculateItemsToSend();
this.itemToSend = Math.min( this.itemToSend,
(int) ( 0.01 + this.getProxy().getEnergy().extractAEPower( this.itemToSend, Actionable.SIMULATE, PowerMultiplier.CONFIG ) ) );
this.itemsToSend = this.calculateItemsToSend();
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage().getInventory(
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
@@ -177,10 +181,10 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
for( int x = 0; x < this.availableSlots(); x++ )
{
final IAEItemStack ais = this.getConfig().getAEStackInSlot( x );
if( ais != null && this.itemToSend > 0 )
if( ais != null && itemsToSend > 0 )
{
Configured = true;
while( this.itemToSend > 0 )
while( itemsToSend > 0 )
{
if( this.importStuff( myAdaptor, ais, inv, energy, fzMode ) )
{
@@ -192,7 +196,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
if( !Configured )
{
while( this.itemToSend > 0 )
while( itemsToSend > 0 )
{
if( this.importStuff( myAdaptor, null, inv, energy, fzMode ) )
{
@@ -221,38 +225,32 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{
newItems = myAdaptor.removeSimilarItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), fzMode,
this.configDestination( inv ) );
newItems = myAdaptor.removeSimilarItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), fzMode, this );
}
else
{
newItems = myAdaptor.removeItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), this.configDestination( inv ) );
newItems = myAdaptor.removeItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), this );
}
if( !newItems.isEmpty() )
{
newItems.setCount( (int) ( Math.min( newItems.getCount(),
energy.extractAEPower( newItems.getCount(), Actionable.SIMULATE, PowerMultiplier.CONFIG ) ) + 0.01 ) );
this.itemToSend -= newItems.getCount();
if( this.lastItemChecked == null || !this.lastItemChecked.isSameType( newItems ) )
{
this.lastItemChecked = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( newItems );
}
else
{
this.lastItemChecked.setStackSize( newItems.getCount() );
}
final IAEItemStack failed = Platform.poweredInsert( energy, this.destination, this.lastItemChecked, this.source );
final IAEItemStack aeStack = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( newItems );
final IAEItemStack failed = Platform.poweredInsert( energy, inv, aeStack, this.source );
if( failed != null )
{
myAdaptor.addItems( failed.createItemStack() );
// try unpowered insert, better be a bit lenient then void items
final IAEItemStack spill = inv.injectItems( failed, Actionable.MODULATE, this.source );
if( spill != null )
{
// last resort try to put it back .. lets hope it's a chest type of thing
myAdaptor.addItems( spill.createItemStack() );
}
return true;
}
else
{
this.itemsToSend -= newItems.getCount();
this.worked = true;
}
}
@@ -266,7 +264,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
private int calculateMaximumAmountToImport( final InventoryAdaptor myAdaptor, final IAEItemStack whatToImport, final IMEMonitor<IAEItemStack> inv, final FuzzyMode fzMode )
{
final int toSend = Math.min( this.itemToSend, 64 );
final int toSend = Math.min( this.itemsToSend, 64 );
final ItemStack itemStackToImport;
if( whatToImport == null )
@@ -282,13 +280,13 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
final ItemStack simResult;
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{
simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, this.configDestination( inv ) );
itemAmountNotStorable = this.destination.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, this );
itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
}
else
{
simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, this.configDestination( inv ) );
itemAmountNotStorable = this.destination.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, this );
itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
}
if( itemAmountNotStorable != null )
@@ -299,12 +297,6 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
return toSend;
}
private IInventoryDestination configDestination( final IMEMonitor<IAEItemStack> itemInventory )
{
this.destination = itemInventory;
return this;
}
@Override
protected boolean isSleeping()
{
@@ -19,10 +19,10 @@
package appeng.parts.misc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -36,11 +36,12 @@ import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.core.AELog;
import appeng.me.GridAccessException;
import appeng.me.helpers.IGridProxyable;
import appeng.me.storage.ITickingMonitor;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
@@ -51,20 +52,17 @@ import appeng.util.item.AEItemStack;
*/
class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor
{
private final Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
private IActionSource mySource;
private final IItemHandler itemHandler;
private final IGridProxyable proxyable;
private final InventoryCache cache;
private ItemStack[] cachedStacks = new ItemStack[0];
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
ItemHandlerAdapter( IItemHandler itemHandler )
ItemHandlerAdapter( IItemHandler itemHandler, IGridProxyable proxy )
{
this.itemHandler = itemHandler;
this.proxyable = proxy;
this.cache = new InventoryCache( this.itemHandler );
}
@Override
@@ -91,7 +89,14 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( type == Actionable.MODULATE )
{
this.onTick();
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
return AEItemStack.fromItemStack( remaining );
@@ -167,7 +172,14 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{
if( mode == Actionable.MODULATE )
{
this.onTick();
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
return AEItemStack.fromItemStack( gathered );
@@ -176,72 +188,10 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
return null;
}
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];
}
@Override
public TickRateModulation onTick()
{
LinkedList<IAEItemStack> changes = new LinkedList<>();
int slots = this.itemHandler.getSlots();
// Make room for new slots
if( slots > this.cachedStacks.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];
ItemStack newIS = this.itemHandler.getStackInSlot( slot );
if( this.isDifferent( newIS, oldIS ) )
{
this.addItemChange( slot, oldAeIS, newIS, changes );
}
else if( !newIS.isEmpty() && !oldIS.isEmpty() )
{
this.addPossibleStackSizeChange( slot, oldAeIS, newIS, changes );
}
}
// Handle cases where the number of slots actually is lower now than before
if( slots < this.cachedStacks.length )
{
for( int slot = slots; slot < this.cachedStacks.length; slot++ )
{
IAEItemStack aeStack = this.cachedAeStacks[slot];
if( aeStack != null )
{
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 );
}
List<IAEItemStack> changes = this.cache.update();
if( !changes.isEmpty() )
{
this.postDifference( changes );
@@ -253,73 +203,6 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
}
private void addItemChange( 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( oldAeIS != null )
{
oldAeIS.setStackSize( -oldAeIS.getStackSize() );
changes.add( oldAeIS );
}
// Notify the network about the new stack. Note that this is null if newIS was null
if( this.cachedAeStacks[slot] != null )
{
changes.add( this.cachedAeStacks[slot] );
}
}
private void addPossibleStackSizeChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
// Still the same item, but amount might have changed
long diff = newIS.getCount() - oldAeIS.getStackSize();
if( diff != 0 )
{
IAEItemStack stack = oldAeIS.copy();
stack.setStackSize( newIS.getCount() );
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = stack;
final IAEItemStack a = stack.copy();
a.setStackSize( diff );
changes.add( a );
}
}
private 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 );
}
private void postDifference( Iterable<IAEItemStack> a )
{
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while( i.hasNext() )
{
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) )
{
key.postChange( this, a, this.mySource );
}
else
{
i.remove();
}
}
}
@Override
public void setActionSource( final IActionSource mySource )
{
@@ -339,7 +222,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
@Override
public IStorageChannel getChannel()
public IItemStorageChannel getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
@@ -355,4 +238,152 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{
this.listeners.remove( l );
}
private void postDifference( Iterable<IAEItemStack> a )
{
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while( i.hasNext() )
{
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) )
{
key.postChange( this, a, this.mySource );
}
else
{
i.remove();
}
}
}
private static class InventoryCache
{
private ItemStack[] cachedStacks = new ItemStack[0];
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
private final IItemHandler itemHandler;
public InventoryCache( IItemHandler itemHandler )
{
this.itemHandler = itemHandler;
}
public List<IAEItemStack> update()
{
List<IAEItemStack> changes = new ArrayList<>();
int slots = this.itemHandler.getSlots();
// Make room for new slots
if( slots > this.cachedStacks.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];
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 );
}
}
// Handle cases where the number of slots actually is lower now than before
if( slots < this.cachedStacks.length )
{
for( int slot = slots; slot < this.cachedStacks.length; slot++ )
{
IAEItemStack aeStack = this.cachedAeStacks[slot];
if( aeStack != null )
{
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 )
{
// Still the same item, but amount might have changed
long diff = newIS.getCount() - oldAeIS.getStackSize();
if( diff != 0 )
{
IAEItemStack stack = oldAeIS.copy();
stack.setStackSize( newIS.getCount() );
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = stack;
final IAEItemStack a = stack.copy();
a.setStackSize( diff );
changes.add( a );
}
}
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 )
{
// 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( oldAeIS != null )
{
oldAeIS.setStackSize( -oldAeIS.getStackSize() );
changes.add( oldAeIS );
}
// Notify the network about the new stack. Note that this is null if newIS was null
if( this.cachedAeStacks[slot] != null )
{
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 );
}
}
}
@@ -66,7 +66,6 @@ import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
@@ -112,7 +111,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
private int priority = 0;
private boolean cached = false;
private ITickingMonitor monitor = null;
private MEInventoryHandler<? extends IAEStack> handler = null;
private MEInventoryHandler<IAEItemStack> handler = null;
private int handlerHash = 0;
private boolean wasActive = false;
private byte resetCacheLogic = 0;
@@ -355,22 +354,18 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
final IMEInventory<IAEItemStack> out = this.getInternalHandler();
if( this.monitor != null )
if( in != out )
{
this.monitor.onTick();
IItemList<IAEItemStack> after = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
if( out != null )
{
after = out.getAvailableItems( after );
}
Platform.postListChanges( before, after, this, this.mySrc );
}
IItemList<IAEItemStack> after = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
if( out != null )
{
after = out.getAvailableItems( after );
}
Platform.postListChanges( before, after, this, this.mySrc );
}
@SuppressWarnings( "unchecked" )
private IMEInventory<? extends IAEItemStack> getInventoryWrapper( TileEntity target )
private IMEInventory<IAEItemStack> getInventoryWrapper( TileEntity target )
{
EnumFacing targetSide = this.getSide().getFacing().getOpposite();
@@ -397,7 +392,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
IItemHandler handlerExt = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide );
if( handlerExt != null )
{
return new ItemHandlerAdapter( handlerExt );
return new ItemHandlerAdapter( handlerExt, this );
}
return null;
@@ -428,7 +423,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return 0;
}
public MEInventoryHandler getInternalHandler()
public MEInventoryHandler<IAEItemStack> getInternalHandler()
{
if( this.cached )
{
@@ -452,7 +447,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
this.monitor = null;
if( target != null )
{
IMEInventory<? extends IAEStack> inv = this.getInventoryWrapper( target );
IMEInventory<IAEItemStack> inv = this.getInventoryWrapper( target );
if( inv instanceof MEMonitorIInventory )
{
@@ -470,7 +465,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{
this.checkInterfaceVsStorageBus( target, this.getSide().getOpposite() );
this.handler = new MEInventoryHandler( inv, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
this.handler = new MEInventoryHandler<IAEItemStack>( inv, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
this.handler.setBaseAccess( (AccessRestriction) this.getConfigManager().getSetting( Settings.ACCESS ) );
this.handler.setWhitelist( this.getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST );
@@ -491,16 +486,17 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{
this.handler
.setPartitionList( new FuzzyPriorityList( priorityList, (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ) ) );
.setPartitionList( new FuzzyPriorityList<IAEItemStack>( priorityList, (FuzzyMode) this.getConfigManager()
.getSetting( Settings.FUZZY_MODE ) ) );
}
else
{
this.handler.setPartitionList( new PrecisePriorityList( priorityList ) );
this.handler.setPartitionList( new PrecisePriorityList<IAEItemStack>( priorityList ) );
}
if( inv instanceof IBaseMonitor )
{
( (IBaseMonitor) inv ).addListener( this, this.handler );
( (IBaseMonitor<IAEItemStack>) inv ).addListener( this, this.handler );
}
}
}
@@ -570,7 +566,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{
if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{
final IMEInventoryHandler out = this.getProxy().isActive() ? this.getInternalHandler() : null;
final IMEInventoryHandler<IAEItemStack> out = this.getProxy().isActive() ? this.getInternalHandler() : null;
if( out != null )
{
return Collections.singletonList( out );
@@ -41,6 +41,7 @@ import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.helpers.Reflected;
import appeng.items.parts.PartModels;
@@ -208,6 +209,7 @@ public class PartToggleBus extends PartBasicState
catch( final FailedConnectionException e )
{
// :(
AELog.debug( e );
}
}
else
@@ -247,6 +247,8 @@ public class PartP2PTunnelME extends PartP2PTunnel<PartP2PTunnelME> implements I
{
final TileEntity start = this.getTile();
final TileEntity end = me.getTile();
AELog.debug( e );
AELog.warn( "Failed to establish a ME P2P Tunnel between the tunnels at [x=%d, y=%d, z=%d] and [x=%d, y=%d, z=%d]",
start.getPos().getX(), start.getPos().getY(), start.getPos().getZ(), end.getPos().getX(), end.getPos().getY(),
@@ -19,19 +19,34 @@
package appeng.recipes.factories.recipes;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.IRecipeFactory;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapedOreRecipe;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import appeng.api.AEApi;
import appeng.api.recipes.ResolverResult;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.recipes.helpers.PartShapedCraftingFactory;
import appeng.recipes.helpers.PartShapelessCraftingFactory;
/**
@@ -45,25 +60,148 @@ public class PartRecipeFactory implements IRecipeFactory
String type = JsonUtils.getString( json, "type" );
if( type.contains( "shaped" ) )
{
PartShapedCraftingFactory recipe = PartShapedCraftingFactory.factory( context, json );
CraftingHelper.ShapedPrimer primer = new CraftingHelper.ShapedPrimer();
primer.width = recipe.getWidth();
primer.height = recipe.getHeight();
primer.mirrored = JsonUtils.getBoolean( json, "mirrored", true );
primer.input = recipe.getIngredients();
return new PartShapedCraftingFactory( new ResourceLocation( AppEng.MOD_ID, "part_shaped_crafting" ), recipe.getRecipeOutput(), primer );
return shapedFactory( context, json );
}
else if( type.contains( "shapeless" ) )
{
PartShapelessCraftingFactory recipe = PartShapelessCraftingFactory.factory( context, json );
return new PartShapelessCraftingFactory( new ResourceLocation( AppEng.MOD_ID, "part_shapeless_crafting" ), recipe.getIngredients(), recipe
.getRecipeOutput() );
return shapelessFactory( context, json );
}
else
{
throw new JsonSyntaxException( "Applied Energistics 2 was given a custom recipe that it does not know how to handle!\n" + "Type should either be '" + AppEng.MOD_ID + ":shapeless' or '" + AppEng.MOD_ID + ":shaped', got '" + type + "'!" );
}
}
public static ItemStack getResult( JsonObject json, JsonContext context )
{
JsonObject resultObject = JsonUtils.getJsonObject( json, "result" );
if( resultObject.has( "part" ) )
{
return getPart( resultObject );
}
else if( resultObject.has( "item" ) )
{
return CraftingHelper.getItemStack( resultObject, context );
}
else
{
throw new JsonSyntaxException( "Result has no 'part' or 'item' property." );
}
}
private static ItemStack getPart( JsonObject resultObject )
{
String ingredient = JsonUtils.getString( resultObject, "part" );
Object result = AEApi.instance().registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
return new ItemStack( item, JsonUtils.getInt( resultObject, "count", 1 ), resolverResult.damageValue, resolverResult.compound );
}
else
{
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\n" + "Was looking for : '" + ingredient + "'." );
}
}
// Copied from ShapedOreRecipe.java, modified a bit.
private static ShapedOreRecipe shapedFactory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
Map<Character, Ingredient> ingMap = Maps.newHashMap();
for( Map.Entry<String, JsonElement> entry : JsonUtils.getJsonObject( json, "key" ).entrySet() )
{
if( entry.getKey().length() != 1 )
{
throw new JsonSyntaxException( "Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only)." );
}
if( " ".equals( entry.getKey() ) )
{
throw new JsonSyntaxException( "Invalid key entry: ' ' is a reserved symbol." );
}
ingMap.put( entry.getKey().toCharArray()[0], CraftingHelper.getIngredient( entry.getValue(), context ) );
}
ingMap.put( ' ', net.minecraft.item.crafting.Ingredient.EMPTY );
JsonArray patternJ = JsonUtils.getJsonArray( json, "pattern" );
if( patternJ.size() == 0 )
{
throw new JsonSyntaxException( "Invalid pattern: empty pattern not allowed" );
}
String[] pattern = new String[patternJ.size()];
for( int x = 0; x < pattern.length; ++x )
{
String line = JsonUtils.getString( patternJ.get( x ), "pattern[" + x + "]" );
if( x > 0 && pattern[0].length() != line.length() )
{
throw new JsonSyntaxException( "Invalid pattern: each row must be the same width" );
}
pattern[x] = line;
}
CraftingHelper.ShapedPrimer primer = new CraftingHelper.ShapedPrimer();
primer.width = pattern[0].length();
primer.height = pattern.length;
primer.mirrored = JsonUtils.getBoolean( json, "mirrored", true );
primer.input = NonNullList.withSize( primer.width * primer.height, net.minecraft.item.crafting.Ingredient.EMPTY );
Set<Character> keys = Sets.newHashSet( ingMap.keySet() );
keys.remove( ' ' );
int x = 0;
for( String line : pattern )
{
for( char chr : line.toCharArray() )
{
net.minecraft.item.crafting.Ingredient ing = ingMap.get( chr );
if( ing == null )
{
throw new JsonSyntaxException( "Pattern references symbol '" + chr + "' but it's not defined in the key" );
}
primer.input.set( x++, ing );
keys.remove( chr );
}
}
if( !keys.isEmpty() )
{
throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + keys );
}
return new ShapedOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), getResult( json, context ), primer );
}
// Copied from ShapelessOreRecipe.java, modified a bit.
private static ShapelessOreRecipe shapelessFactory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
NonNullList<Ingredient> ings = NonNullList.create();
for( JsonElement ele : JsonUtils.getJsonArray( json, "ingredients" ) )
{
ings.add( CraftingHelper.getIngredient( ele, context ) );
}
if( ings.isEmpty() )
{
throw new JsonParseException( "No ingredients for shapeless recipe" );
}
return new ShapelessOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), ings, getResult( json, context ) );
}
}
@@ -1,153 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.recipes.helpers;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapedOreRecipe;
import appeng.api.recipes.ResolverResult;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.core.AppEng;
/**
* @author GuntherDW
*/
public class PartShapedCraftingFactory extends ShapedOreRecipe
{
public PartShapedCraftingFactory( ResourceLocation group, @Nonnull ItemStack result, CraftingHelper.ShapedPrimer primer )
{
super( group, result, primer );
}
// Copied from ShapedOreRecipe.java, modified a bit.
public static PartShapedCraftingFactory factory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
Map<Character, Ingredient> ingMap = Maps.newHashMap();
for( Map.Entry<String, JsonElement> entry : JsonUtils.getJsonObject( json, "key" ).entrySet() )
{
if( entry.getKey().length() != 1 )
{
throw new JsonSyntaxException( "Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only)." );
}
if( " ".equals( entry.getKey() ) )
{
throw new JsonSyntaxException( "Invalid key entry: ' ' is a reserved symbol." );
}
ingMap.put( entry.getKey().toCharArray()[0], CraftingHelper.getIngredient( entry.getValue(), context ) );
}
ingMap.put( ' ', net.minecraft.item.crafting.Ingredient.EMPTY );
JsonArray patternJ = JsonUtils.getJsonArray( json, "pattern" );
if( patternJ.size() == 0 )
{
throw new JsonSyntaxException( "Invalid pattern: empty pattern not allowed" );
}
String[] pattern = new String[patternJ.size()];
for( int x = 0; x < pattern.length; ++x )
{
String line = JsonUtils.getString( patternJ.get( x ), "pattern[" + x + "]" );
if( x > 0 && pattern[0].length() != line.length() )
{
throw new JsonSyntaxException( "Invalid pattern: each row must be the same width" );
}
pattern[x] = line;
}
CraftingHelper.ShapedPrimer primer = new CraftingHelper.ShapedPrimer();
primer.width = pattern[0].length();
primer.height = pattern.length;
primer.mirrored = JsonUtils.getBoolean( json, "mirrored", true );
primer.input = NonNullList.withSize( primer.width * primer.height, net.minecraft.item.crafting.Ingredient.EMPTY );
Set<Character> keys = Sets.newHashSet( ingMap.keySet() );
keys.remove( ' ' );
int x = 0;
for( String line : pattern )
{
for( char chr : line.toCharArray() )
{
net.minecraft.item.crafting.Ingredient ing = ingMap.get( chr );
if( ing == null )
{
throw new JsonSyntaxException( "Pattern references symbol '" + chr + "' but it's not defined in the key" );
}
primer.input.set( x++, ing );
keys.remove( chr );
}
}
if( !keys.isEmpty() )
{
throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + keys );
}
JsonObject resultObject = (JsonObject) json.get( "result" );
int count = JsonUtils.getInt( resultObject, "count", 1 );
String ingredient = resultObject.get( "part" ).getAsString();
Object result = (Object) Api.INSTANCE.registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
ItemStack itemStack = new ItemStack( item, count, resolverResult.damageValue, resolverResult.compound );
return new PartShapedCraftingFactory( group.isEmpty() ? null : new ResourceLocation( group ), itemStack, primer );
}
// Should never reach this part unless mangled JSON or bug in AE.
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\nWas looking for : '" + ingredient + "'." );
}
}
@@ -1,96 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, 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.recipes.helpers;
import javax.annotation.Nonnull;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import appeng.api.recipes.ResolverResult;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.core.AppEng;
/**
* @author GuntherDW
*/
public class PartShapelessCraftingFactory extends ShapelessOreRecipe
{
public PartShapelessCraftingFactory( ResourceLocation group, NonNullList<Ingredient> input, @Nonnull ItemStack result )
{
super( group, input, result );
}
// Copied from ShapelessOreRecipe.java, modified a bit.
public static PartShapelessCraftingFactory factory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
NonNullList<Ingredient> ings = NonNullList.create();
for( JsonElement ele : JsonUtils.getJsonArray( json, "ingredients" ) )
{
ings.add( CraftingHelper.getIngredient( ele, context ) );
}
if( ings.isEmpty() )
{
throw new JsonParseException( "No ingredients for shapeless recipe" );
}
JsonObject resultObject = (JsonObject) json.get( "result" );
int count = JsonUtils.getInt( resultObject, "count", 1 );
String ingredient = resultObject.get( "part" ).getAsString();
Object result = (Object) Api.INSTANCE.registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
ItemStack itemStack = new ItemStack( item, count, resolverResult.damageValue, resolverResult.compound );
return new PartShapelessCraftingFactory( group.isEmpty() ? null : new ResourceLocation( group ), ings, itemStack );
}
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\n" + "Was looking for : '" + ingredient + "'." );
}
}
@@ -27,7 +27,7 @@ public class BiomeGenStorage extends Biome
public BiomeGenStorage()
{
super( new BiomeProperties( "Storage Cell" ).setRainDisabled().setTemperature( -100 ) );
super( new BiomeProperties( "Storage Cell" ).setBaseBiome( "void" ).setRainDisabled().setTemperature( -100 ) );
this.decorator.treesPerChunk = 0;
this.decorator.flowersPerChunk = 0;
+39 -30
View File
@@ -27,6 +27,7 @@ import java.util.Map.Entry;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.NextTickListEntry;
import net.minecraft.world.World;
@@ -34,7 +35,6 @@ import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import appeng.api.AEApi;
import appeng.api.definitions.IBlockDefinition;
import appeng.api.movable.IMovableHandler;
import appeng.api.movable.IMovableRegistry;
import appeng.api.util.AEPartLocation;
@@ -61,7 +61,6 @@ public class CachedPlane
private final World world;
private final IMovableRegistry reg = AEApi.instance().registries().movable();
private final LinkedList<WorldCoord> updates = new LinkedList<>();
private final IBlockDefinition matrixFrame = AEApi.instance().definitions().blocks().matrixFrame();
private int verticalBits;
private final IBlockState matrixBlockState;
@@ -146,11 +145,11 @@ public class CachedPlane
}
else
{
final Object[] details = this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].getDetails( tePOS.getY() );
final IBlockState blkState = (IBlockState) details[0];
final BlockStorageData details = new BlockStorageData();
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].fillData( tePOS.getY(), details );
// don't skip air, just let the code replace it...
if( blkState != null && blkState.getBlock() == Platform.AIR_BLOCK && blkState.getMaterial().isReplaceable() )
if( details.state != null && details.state.getBlock() == Platform.AIR_BLOCK && details.state.getMaterial().isReplaceable() )
{
w.setBlockToAir( tePOS );
}
@@ -168,12 +167,11 @@ public class CachedPlane
}
final long k = this.getWorld().getTotalWorldTime();
final List list = this.getWorld().getPendingBlockUpdates( c, false );
final List<NextTickListEntry> list = this.getWorld().getPendingBlockUpdates( c, false );
if( list != null )
{
for( final Object o : list )
for( final NextTickListEntry entry : list )
{
final NextTickListEntry entry = (NextTickListEntry) o;
final BlockPos tePOS = entry.position;
if( tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS
.getZ() <= maxZ )
@@ -192,6 +190,10 @@ public class CachedPlane
try
{
this.getWorld().loadedTileEntityList.remove( te );
if( te instanceof ITickable )
{
this.getWorld().tickableTileEntities.remove( te );
}
}
catch( final Exception e )
{
@@ -215,6 +217,8 @@ public class CachedPlane
AELog.info( "Block Copy Scale: " + this.x_size + ", " + this.y_size + ", " + this.z_size );
long startTime = System.nanoTime();
final BlockStorageData aD = new BlockStorageData();
final BlockStorageData bD = new BlockStorageData();
for( int x = 0; x < this.x_size; x++ )
{
@@ -230,8 +234,8 @@ public class CachedPlane
if( a.doNotSkip( src_y ) && b.doNotSkip( dst_y ) )
{
final Object[] aD = a.getDetails( src_y );
final Object[] bD = b.getDetails( dst_y );
a.fillData( src_y, aD );
b.fillData( dst_y, bD );
a.setBlockIDWithMetadata( src_y, bD );
b.setBlockIDWithMetadata( dst_y, aD );
@@ -386,14 +390,17 @@ public class CachedPlane
return this.world;
}
private static class BlockStorageData
{
public IBlockState state;
public int light;
}
private class Column
{
private final int x;
private final int z;
private final Chunk c;
private final Object[] ch = { 0, 0 };
private final ExtendedBlockStorage[] storage;
private List<Integer> skipThese = null;
public Column( final Chunk chunk, final int x, final int z, final int chunkY, final int chunkHeight )
@@ -401,44 +408,46 @@ public class CachedPlane
this.x = x;
this.z = z;
this.c = chunk;
this.storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
// make sure storage exists before hand...
for( int ay = 0; ay < chunkHeight; ay++ )
{
final int by = ( ay + chunkY );
ExtendedBlockStorage extendedblockstorage = this.storage[by];
ExtendedBlockStorage extendedblockstorage = storage[by];
if( extendedblockstorage == null )
{
extendedblockstorage = this.storage[by] = new ExtendedBlockStorage( by << 4, !this.c.getWorld().provider.hasSkyLight() );
extendedblockstorage = storage[by] = new ExtendedBlockStorage( by << 4, !this.c.getWorld().provider.hasSkyLight() );
}
}
}
private void setBlockIDWithMetadata( final int y, final Object[] blk )
private void setBlockIDWithMetadata( final int y, BlockStorageData data )
{
if( blk[0] == CachedPlane.this.matrixBlockState )
if( data.state == CachedPlane.this.matrixBlockState )
{
blk[0] = Platform.AIR_BLOCK.getDefaultState();
data.state = Platform.AIR_BLOCK.getDefaultState();
}
final ExtendedBlockStorage extendedBlockStorage = this.storage[y >> 4];
extendedBlockStorage.set( this.x, y & 15, this.z, (IBlockState) blk[0] );
// extendedBlockStorage.setExtBlockID( x, y & 15, z, blk[0] );
extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, (Integer) blk[1] );
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage extendedBlockStorage = storage[y >> 4];
extendedBlockStorage.set( this.x, y & 15, this.z, data.state );
extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, data.light );
}
private Object[] getDetails( final int y )
private void fillData( final int y, BlockStorageData data )
{
final ExtendedBlockStorage extendedblockstorage = this.storage[y >> 4];
this.ch[0] = extendedblockstorage.get( this.x, y & 15, this.z );
this.ch[1] = extendedblockstorage.getBlockLight( this.x, y & 15, this.z );
return this.ch;
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage extendedblockstorage = storage[y >> 4];
data.state = extendedblockstorage.get( this.x, y & 15, this.z );
data.light = extendedblockstorage.getBlockLight( this.x, y & 15, this.z );
}
private boolean doNotSkip( final int y )
{
final ExtendedBlockStorage extendedblockstorage = this.storage[y >> 4];
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage extendedblockstorage = storage[y >> 4];
if( CachedPlane.this.reg.isBlacklisted( extendedblockstorage.get( this.x, y & 15, this.z ).getBlock() ) )
{
return false;
@@ -19,6 +19,7 @@
package appeng.spatial;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@@ -54,8 +55,9 @@ public class DefaultSpatialHandler implements IMovableHandler
if( c.isLoaded() )
{
final IBlockState state = w.getBlockState( newPosition );
w.addTileEntity( te );
w.notifyBlockUpdate( newPosition, w.getBlockState( newPosition ), w.getBlockState( newPosition ), 0 );
w.notifyBlockUpdate( newPosition, state, state, 1 );
}
}
}
@@ -122,6 +122,11 @@ public class StorageHelper
}
else
{
// really remove from world, forge only marks it as removed
final boolean wasDead = entity.isDead;
oldWorld.removeEntityDangerously( entity );
entity.isDead = wasDead;
entity.getServer().getPlayerList().transferEntityToWorld( entity, entity.dimension,
entity.getServer().getWorld( entity.dimension ), (WorldServer) link.dim, new METeleporter( newWorld, link ) );
}
@@ -46,6 +46,7 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
private final IAEItemStack[] inv;
private final int size;
private int maxStack;
private boolean dirtyFlag = false;
public AppEngInternalAEInventory( final IAEAppEngInventory te, final int s )
{
@@ -252,8 +253,10 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
{
if( this.te != null && Platform.isServer() )
{
this.dirtyFlag = true;
this.te.onChangeInventory( this, slot, op, removed, inserted );
this.te.saveChanges();
this.dirtyFlag = false;
}
}
@@ -283,6 +286,9 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
@Override
public void markDirty( int slot )
{
this.fireOnChangeInventory( slot, InvOperation.DIRTY, ItemStack.EMPTY, ItemStack.EMPTY );
if( !this.dirtyFlag )
{
this.fireOnChangeInventory( slot, InvOperation.DIRTY, ItemStack.EMPTY, ItemStack.EMPTY );
}
}
}
@@ -43,6 +43,7 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
private final int[] maxStack;
private ItemStack previousStack = ItemStack.EMPTY;
private IAEItemFilter filter;
private boolean dirtyFlag = false;
public AppEngInternalInventory( final IAEAppEngInventory inventory, final int size, final int maxStack, IAEItemFilter filter )
{
@@ -118,6 +119,7 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
{
if( this.getTileEntity() != null && this.eventsEnabled() )
{
this.dirtyFlag = true;
ItemStack newStack = this.getStackInSlot( slot ).copy();
ItemStack oldStack = this.previousStack;
InvOperation op = InvOperation.SET;
@@ -141,6 +143,7 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
this.getTileEntity().onChangeInventory( this, slot, op, oldStack, newStack );
this.getTileEntity().saveChanges();
this.previousStack = ItemStack.EMPTY;
this.dirtyFlag = false;
}
super.onContentsChanged( slot );
}
@@ -158,10 +161,12 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
@Override
public void markDirty( final int slot )
{
if( this.getTileEntity() != null && this.eventsEnabled() )
if( this.getTileEntity() != null && this.eventsEnabled() && !this.dirtyFlag )
{
this.dirtyFlag = true;
this.getTileEntity().onChangeInventory( this, slot, InvOperation.DIRTY, ItemStack.EMPTY, ItemStack.EMPTY );
this.getTileEntity().saveChanges();
this.dirtyFlag = false;
}
}
@@ -19,23 +19,37 @@
package appeng.tile.misc;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import net.minecraft.item.ItemStack;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.networking.security.IActionSource;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.me.helpers.BaseActionSource;
import appeng.me.storage.ITickingMonitor;
import appeng.util.item.AEItemStack;
import appeng.util.item.ItemList;
class CondenserItemInventory implements IMEMonitor<IAEItemStack>
class CondenserItemInventory implements IMEMonitor<IAEItemStack>, ITickingMonitor
{
private final HashMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
private final TileCondenser target;
private boolean hasChanged = true;
private final ItemList cachedList = new ItemList();
private IActionSource actionSource = new BaseActionSource();
private ItemList changeSet = new ItemList();
CondenserItemInventory( final TileCondenser te )
{
@@ -49,30 +63,46 @@ class CondenserItemInventory implements IMEMonitor<IAEItemStack>
{
this.target.addPower( input.getStackSize() );
}
return null;
}
@Override
public IAEItemStack extractItems( final IAEItemStack request, final Actionable mode, final IActionSource src )
{
return null;
AEItemStack ret = null;
ItemStack slotItem = target.getOutputSlot().getStackInSlot( 0 );
if( !slotItem.isEmpty() && request.isSameType( slotItem ) )
{
int count = (int) Math.min( request.getStackSize(), Integer.MAX_VALUE );
ret = AEItemStack.fromItemStack( target.getOutputSlot().extractItem( 0, count, mode == Actionable.SIMULATE ) );
}
return ret;
}
@Override
public IItemList<IAEItemStack> getAvailableItems( final IItemList out )
public IItemList<IAEItemStack> getAvailableItems( final IItemList<IAEItemStack> out )
{
if( !target.getOutputSlot().getStackInSlot( 0 ).isEmpty() )
{
out.add( AEItemStack.fromItemStack( target.getOutputSlot().getStackInSlot( 0 ) ) );
}
return out;
}
@Override
public IItemList<IAEItemStack> getStorageList()
{
return new ItemList();
if( this.hasChanged )
{
this.hasChanged = false;
this.cachedList.resetStatus();
return this.getAvailableItems( this.cachedList );
}
return this.cachedList;
}
@Override
public IStorageChannel getChannel()
public IStorageChannel<IAEItemStack> getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
@@ -80,7 +110,7 @@ class CondenserItemInventory implements IMEMonitor<IAEItemStack>
@Override
public AccessRestriction getAccess()
{
return AccessRestriction.WRITE;
return AccessRestriction.READ_WRITE;
}
@Override
@@ -114,14 +144,62 @@ class CondenserItemInventory implements IMEMonitor<IAEItemStack>
}
@Override
public void addListener( IMEMonitorHandlerReceiver<IAEItemStack> l, Object verificationToken )
public void addListener( final IMEMonitorHandlerReceiver<IAEItemStack> l, final Object verificationToken )
{
// Not implemented since the Condenser automatically voids everything, and there are no updates
this.listeners.put( l, verificationToken );
}
@Override
public void removeListener( IMEMonitorHandlerReceiver<IAEItemStack> l )
public void removeListener( final IMEMonitorHandlerReceiver<IAEItemStack> l )
{
// Not implemented since we don't remember registered listeners anyway
this.listeners.remove( l );
}
public void updateOutput( ItemStack added, ItemStack removed )
{
this.hasChanged = true;
if( !added.isEmpty() )
{
this.changeSet.add( AEItemStack.fromItemStack( added ) );
}
if( !removed.isEmpty() )
{
this.changeSet.add( AEItemStack.fromItemStack( removed ).setStackSize( -removed.getCount() ) );
}
}
@Override
public TickRateModulation onTick()
{
final ItemList currentChanges = this.changeSet;
if( currentChanges.isEmpty() )
{
return TickRateModulation.IDLE;
}
this.changeSet = new ItemList();
final Iterator<Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while( i.hasNext() )
{
final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) )
{
key.postChange( this, currentChanges, this.actionSource );
}
else
{
i.remove();
}
}
return TickRateModulation.URGENT;
}
@Override
public void setActionSource( IActionSource actionSource )
{
this.actionSource = actionSource;
}
}
@@ -55,6 +55,8 @@ import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.inv.InvOperation;
import appeng.util.inv.WrapperChainedItemHandler;
import appeng.util.inv.WrapperFilteredItemHandler;
import appeng.util.inv.filter.AEItemFilters;
public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost, IConfigurableObject
@@ -62,14 +64,16 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
public static final int BYTE_MULTIPLIER = 8;
private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 );
private final ConfigManager cm = new ConfigManager( this );
private final AppEngInternalInventory outputSlot = new AppEngInternalInventory( this, 1 );
private final AppEngInternalInventory storageSlot = new AppEngInternalInventory( this, 1 );
private final IItemHandler inputSlot = new CondenseItemHandler();
private final IFluidHandler fluidHandler = new FluidHandler();
private final MEHandler meHandler = new MEHandler();
private final IItemHandler combinedInv = new WrapperChainedItemHandler( this.inputSlot, this.inv );
private final IItemHandler externalInv = new WrapperChainedItemHandler( this.inputSlot, new WrapperFilteredItemHandler( this.outputSlot, AEItemFilters.EXTRACT_ONLY ) );
private final IItemHandler combinedInv = new WrapperChainedItemHandler( this.inputSlot, this.outputSlot, this.storageSlot );
private double storedPower = 0;
@@ -97,7 +101,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
public double getStorage()
{
final ItemStack is = this.inv.getStackInSlot( 1 );
final ItemStack is = this.storageSlot.getStackInSlot( 0 );
if( !is.isEmpty() )
{
if( is.getItem() instanceof IStorageComponent )
@@ -135,7 +139,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
private boolean canAddOutput( final ItemStack output )
{
return this.inv.insertItem( 0, output, true ).isEmpty();
return this.outputSlot.insertItem( 0, output, true ).isEmpty();
}
/**
@@ -145,7 +149,12 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
*/
private void addOutput( final ItemStack output )
{
this.inv.insertItem( 0, output, false );
this.outputSlot.insertItem( 0, output, false );
}
IItemHandler getOutputSlot()
{
return this.outputSlot;
}
private ItemStack getOutput()
@@ -180,7 +189,10 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
@Override
public void onChangeInventory( final IItemHandler inv, final int slot, final InvOperation mc, final ItemStack removed, final ItemStack added )
{
// nothing
if( inv == this.outputSlot )
{
this.meHandler.outputChanged( added, removed );
}
}
@Override
@@ -225,7 +237,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
{
if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY )
{
return (T) this.inputSlot;
return (T) this.externalInv;
}
else if( capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY )
{
@@ -336,6 +348,11 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
private final CondenserItemInventory itemInventory = new CondenserItemInventory( TileCondenser.this );
void outputChanged( ItemStack added, ItemStack removed )
{
itemInventory.updateOutput( added, removed );
}
@Nullable
@Override
public IStorageMonitorable getInventory( IActionSource src )
@@ -281,9 +281,13 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
@Nullable
public IInscriberRecipe getTask()
{
final ItemStack plateA = this.topItemHandler.getStackInSlot( 0 );
final ItemStack plateB = this.bottomItemHandler.getStackInSlot( 0 );
ItemStack renamedItem = this.sideItemHandler.getStackInSlot( 0 );
return getTask( this.sideItemHandler.getStackInSlot( 0 ), this.topItemHandler.getStackInSlot( 0 ), this.bottomItemHandler.getStackInSlot( 0 ) );
}
@Nullable
private IInscriberRecipe getTask( final ItemStack input, final ItemStack plateA, final ItemStack plateB )
{
ItemStack renamedItem = input;
if( !plateA.isEmpty() && plateA.getCount() > 1 )
{
@@ -379,7 +383,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
{
for( final ItemStack option : recipe.getInputs() )
{
if( Platform.itemComparisons().isSameItem( option, this.sideItemHandler.getStackInSlot( 0 ) ) )
if( Platform.itemComparisons().isSameItem( input, option ) )
{
return recipe;
}
@@ -606,7 +610,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
}
for( final ItemStack optionals : AEApi.instance().registries().inscriber().getOptionals() )
{
if( Platform.itemComparisons().isSameItem( optionals, stack ) )
if( Platform.itemComparisons().isSameItem( stack, optionals ) )
{
return true;
}
@@ -209,8 +209,7 @@ public class TileController extends AENetworkPowerTile
*/
private boolean checkController( final BlockPos pos )
{
final BlockPos ownPos = this.getPos();
if( this.world.getChunkProvider().getLoadedChunk( ownPos.getX() >> 4, ownPos.getZ() >> 4 ) != null )
if( this.world.getChunkProvider().getLoadedChunk( pos.getX() >> 4, pos.getZ() >> 4 ) != null )
{
return this.world.getTileEntity( pos ) instanceof TileController;
}
+13 -11
View File
@@ -1296,11 +1296,11 @@ public class Platform
{
if( a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1 )
{
return false;
return true;
}
else if( a.getLastSecurityKey() == b.getLastSecurityKey() )
{
return false;
return true;
}
final boolean a_isSecure = isPowered( a.getGrid() ) && a.getLastSecurityKey() != -1;
@@ -1308,15 +1308,17 @@ public class Platform
if( AEConfig.instance().isFeatureEnabled( AEFeature.LOG_SECURITY_AUDITS ) )
{
AELog.info(
"Audit: " + a_isSecure + " : " + b_isSecure + " @ " + a.getLastSecurityKey() + " vs " + b.getLastSecurityKey() + " & " + a
.getPlayerID() + " vs " + b.getPlayerID() );
final String locationA = a.getGridBlock().isWorldAccessible() ? a.getGridBlock().getLocation().toString() : "notInWorld";
final String locationB = b.getGridBlock().isWorldAccessible() ? b.getGridBlock().getLocation().toString() : "notInWorld";
AELog.info( "Audit: Node A [isSecure=%b, key=%d, playerID=%d, location={%s}] vs Node B[isSecure=%b, key=%d, playerID=%d, location={%s}]",
a_isSecure, a.getLastSecurityKey(), a.getPlayerID(), locationA, b_isSecure, b.getLastSecurityKey(), b.getPlayerID(), locationB );
}
// can't do that son...
if( a_isSecure && b_isSecure )
{
return true;
return false;
}
if( !a_isSecure && b_isSecure )
@@ -1329,7 +1331,7 @@ public class Platform
return checkPlayerPermissions( a.getGrid(), b.getPlayerID() );
}
return false;
return true;
}
private static boolean isPowered( final IGrid grid )
@@ -1347,22 +1349,22 @@ public class Platform
{
if( grid == null )
{
return false;
return true;
}
final ISecurityGrid gs = grid.getCache( ISecurityGrid.class );
if( gs == null )
{
return false;
return true;
}
if( !gs.isAvailable() )
{
return false;
return true;
}
return !gs.hasPermission( playerID, SecurityPermissions.BUILD );
return gs.hasPermission( playerID, SecurityPermissions.BUILD );
}
public static void configurePlayer( final EntityPlayer player, final AEPartLocation side, final TileEntity tile )
@@ -21,7 +21,7 @@ package appeng.util.inv;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.wrapper.PlayerInvWrapper;
import net.minecraftforge.items.wrapper.PlayerMainInvWrapper;
import appeng.util.Platform;
@@ -30,7 +30,7 @@ public class AdaptorItemHandlerPlayerInv extends AdaptorItemHandler
{
public AdaptorItemHandlerPlayerInv( final EntityPlayer playerInv )
{
super( new PlayerInvWrapper( playerInv.inventory ) );
super( new PlayerMainInvWrapper( playerInv.inventory ) );
}
/**
@@ -101,7 +101,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
}
final AEFluidStack fluid = AEFluidStack.fromFluidStack( fluidStack );
// fluid.priority = i.getInteger( "Priority" );
fluid.setStackSize( i.getLong( "Cnt" ) );
fluid.setCountRequestable( i.getLong( "Req" ) );
fluid.setCraftable( i.getBoolean( "Craft" ) );
@@ -111,12 +110,10 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
public static IAEFluidStack fromPacket( final ByteBuf data ) throws IOException
{
final byte mask = data.readByte();
// byte PriorityType = (byte) (mask & 0x03);
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0;
final boolean hasTagCompound = ( mask & 0x80 ) > 0;
boolean showCraftingLabel = data.readBoolean();
// don't send this...
final NBTTagCompound d = new NBTTagCompound();
@@ -139,17 +136,11 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
d.setTag( "tag", CompressedStreamTools.read( di ) );
}
// long priority = getPacketValue( PriorityType, data );
final long stackSize = getPacketValue( stackType, data );
final long countRequestable = getPacketValue( countReqType, data );
final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( d );
if( !showCraftingLabel )
{
showCraftingLabel = stackSize == 0;
}
if( fluidStack == null )
{
return null;
@@ -170,10 +161,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
{
return;
}
// if ( priority < ((AEFluidStack) option).priority )
// priority = ((AEFluidStack) option).priority;
this.incStackSize( option.getStackSize() );
this.setCountRequestable( this.getCountRequestable() + option.getCountRequestable() );
this.setCraftable( this.isCraftable() || option.isCraftable() );
@@ -364,7 +351,20 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
}
@Override
protected void writeToStream( final ByteBuf i ) throws IOException
public void writeToPacket( final ByteBuf i ) throws IOException
{
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 );
i.writeByte( mask );
writeToStream( i );
this.putPacketValue( i, this.getStackSize() );
this.putPacketValue( i, this.getCountRequestable() );
}
private void writeToStream( final ByteBuf i ) throws IOException
{
final byte[] name = this.fluid.getName().getBytes( "UTF-8" );
i.writeByte( (byte) name.length );
+26 -22
View File
@@ -19,8 +19,8 @@
package appeng.util.item;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nonnull;
@@ -106,15 +106,23 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return item;
}
public static IAEItemStack fromPacket( final ByteBuf data ) throws IOException
@Override
public void writeToNBT( final NBTTagCompound i )
{
this.getDefinition().writeToNBT( i );
i.setLong( "Cnt", this.getStackSize() );
i.setLong( "Req", this.getCountRequestable() );
i.setBoolean( "Craft", this.isCraftable() );
}
public static AEItemStack fromPacket( final ByteBuf data )
{
final byte mask = data.readByte();
// byte PriorityType = (byte) (mask & 0x03);
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0;
final ItemStack itemstack = ByteBufUtils.readItemStack( data );
final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) );
final long stackSize = getPacketValue( stackType, data );
final long countRequestable = getPacketValue( countReqType, data );
@@ -123,13 +131,24 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return null;
}
final AEItemStack item = AEItemStack.fromItemStack( itemstack );
item.setStackSize( stackSize );
final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize );
item.setCountRequestable( countRequestable );
item.setCraftable( isCraftable );
return item;
}
@Override
public void writeToPacket( final ByteBuf i )
{
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 );
i.writeByte( mask );
ByteBufUtils.writeTag( i, this.getDefinition().serializeNBT() );
this.putPacketValue( i, this.getStackSize() );
this.putPacketValue( i, this.getCountRequestable() );
}
@Override
public void add( final IAEItemStack option )
{
@@ -143,15 +162,6 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
this.setCraftable( this.isCraftable() || option.isCraftable() );
}
@Override
public void writeToNBT( final NBTTagCompound i )
{
this.getDefinition().writeToNBT( i );
i.setLong( "Cnt", this.getStackSize() );
i.setLong( "Req", this.getCountRequestable() );
i.setBoolean( "Craft", this.isCraftable() );
}
@Override
public boolean fuzzyComparison( final Object st, final FuzzyMode mode )
{
@@ -338,7 +348,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return false;
}
return this.sharedStack == ( (AEItemStack) otherStack ).sharedStack;
return Objects.equals( this.sharedStack, ( (AEItemStack) otherStack ).sharedStack );
}
@Override
@@ -424,12 +434,6 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return this.oreReference;
}
@Override
protected void writeToStream( final ByteBuf data ) throws IOException
{
ByteBufUtils.writeItemStack( data, this.getDefinition() );
}
@Override
public boolean hasTagCompound()
{
@@ -31,15 +31,30 @@ import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack;
import appeng.util.Platform;
public final class AEItemStackRegistry
{
private static final WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> REGISTRY = new WeakHashMap<>();
private static final WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> SERVER_REGISTRY = new WeakHashMap<>();
private static final WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> CLIENT_REGISTRY = new WeakHashMap<>();
private AEItemStackRegistry()
{
}
private static WeakHashMap<AESharedItemStack, WeakReference<AESharedItemStack>> registry()
{
if( Platform.isClient() )
{
return CLIENT_REGISTRY;
}
else
{
return SERVER_REGISTRY;
}
}
static synchronized AESharedItemStack getRegisteredStack( final @Nonnull ItemStack itemStack )
{
if( itemStack.isEmpty() )
@@ -51,7 +66,7 @@ public final class AEItemStackRegistry
itemStack.setCount( 1 );
AESharedItemStack search = new AESharedItemStack( itemStack );
WeakReference<AESharedItemStack> weak = REGISTRY.get( search );
WeakReference<AESharedItemStack> weak = registry().get( search );
AESharedItemStack ret = null;
if( weak != null )
@@ -62,7 +77,7 @@ public final class AEItemStackRegistry
if( ret == null )
{
ret = new AESharedItemStack( itemStack.copy() );
REGISTRY.put( ret, new WeakReference<>( ret ) );
registry().put( ret, new WeakReference<>( ret ) );
}
itemStack.setCount( oldStackSize );
@@ -56,6 +56,11 @@ final class AESharedItemStack implements Comparable<AESharedItemStack>
return this.itemDamage;
}
int getItemID()
{
return this.itemId;
}
@Override
public int hashCode()
{
@@ -104,7 +109,17 @@ final class AESharedItemStack implements Comparable<AESharedItemStack>
return damageValue;
}
return this.compareNBT( b.getDefinition() );
final int nbt = this.compareNBT( b.getDefinition() );
if( nbt != 0 )
{
return nbt;
}
if( !this.itemStack.areCapsCompatible( b.getDefinition() ) )
{
return System.identityHashCode( this.itemStack ) - System.identityHashCode( b.getDefinition() );
}
return 0;
}
private int compareNBT( final ItemStack b )
+2 -20
View File
@@ -19,8 +19,6 @@
package appeng.util.item;
import java.io.IOException;
import io.netty.buffer.ByteBuf;
import appeng.api.storage.data.IAEStack;
@@ -144,23 +142,7 @@ public abstract class AEStack<StackType extends IAEStack<StackType>> implements
this.countRequestable -= i;
}
@Override
public void writeToPacket( final ByteBuf i ) throws IOException
{
final byte mask = (byte) ( this.getType( 0 ) | ( this.getType( this.stackSize ) << 2 ) | ( this
.getType( this.countRequestable ) << 4 ) | ( (byte) ( this.isCraftable ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 );
i.writeByte( mask );
this.writeToStream( i );
this.putPacketValue( i, this.stackSize );
this.putPacketValue( i, this.countRequestable );
}
protected abstract void writeToStream( final ByteBuf data ) throws IOException;
private byte getType( final long num )
protected byte getType( final long num )
{
if( num <= 255 )
{
@@ -182,7 +164,7 @@ public abstract class AEStack<StackType extends IAEStack<StackType>> implements
abstract boolean hasTagCompound();
private void putPacketValue( final ByteBuf tag, final long num )
protected void putPacketValue( final ByteBuf tag, final long num )
{
if( num <= 255 )
{
@@ -1,10 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:part", "data": 16
},
"title": { "translate": "achievement.ae2.GlassCable" },
"description": { "translate": "achievement.ae2.GlassCable.desc" }
"icon": {
"item": "appliedenergistics2:part",
"data": 16
},
"title": {
"translate": "achievement.ae2.GlassCable"
},
"description": {
"translate": "achievement.ae2.GlassCable.desc"
}
},
"parent": "appliedenergistics2:main/fluix",
"criteria": {
@@ -13,11 +18,11 @@
"conditions": {
"items": [
{
"type": "appliedenergistics2:part",
"part": "CABLE_GLASS"
"type": "appliedenergistics2:part",
"part": "CABLE_GLASS"
}
]
}
}
}
}
}
@@ -1,11 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:material",
"data": 1
},
"title": { "translate": "achievement.ae2.ChargedQuartz" },
"description": { "translate": "achievement.ae2.ChargedQuartz.desc" }
"icon": {
"item": "appliedenergistics2:material",
"data": 1
},
"title": {
"translate": "achievement.ae2.ChargedQuartz"
},
"description": {
"translate": "achievement.ae2.ChargedQuartz.desc"
}
},
"parent": "appliedenergistics2:main/root",
"criteria": {
@@ -14,11 +18,11 @@
"conditions": {
"items": [
{
"item": "appliedenergistics2:material",
"item": "appliedenergistics2:material",
"data": 1
}
]
}
}
}
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:charger"
},
"title": { "translate": "achievement.ae2.Charger" },
"description": { "translate": "achievement.ae2.Charger.desc" }
"icon": {
"item": "appliedenergistics2:charger"
},
"title": {
"translate": "achievement.ae2.Charger"
},
"description": {
"translate": "achievement.ae2.Charger.desc"
}
},
"parent": "appliedenergistics2:main/charged_quartz",
"criteria": {
@@ -19,4 +23,4 @@
}
}
}
}
}
@@ -1,8 +1,14 @@
{
"display": {
"icon": { "item": "appliedenergistics2:sky_compass" },
"title": { "translate": "achievement.ae2.Compass" },
"description": { "translate": "achievement.ae2.Compass.desc" }
"icon": {
"item": "appliedenergistics2:sky_compass"
},
"title": {
"translate": "achievement.ae2.Compass"
},
"description": {
"translate": "achievement.ae2.Compass.desc"
}
},
"parent": "appliedenergistics2:main/root",
"criteria": {
@@ -17,4 +23,4 @@
}
}
}
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:controller"
},
"title": { "translate": "achievement.ae2.Controller" },
"description": { "translate": "achievement.ae2.Controller.desc" }
"icon": {
"item": "appliedenergistics2:controller"
},
"title": {
"translate": "achievement.ae2.Controller"
},
"description": {
"translate": "achievement.ae2.Controller.desc"
}
},
"parent": "appliedenergistics2:main/presses",
"criteria": {
@@ -19,4 +23,4 @@
}
}
}
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:crafting_storage_64k"
},
"title": { "translate": "achievement.ae2.CraftingCPU" },
"description": { "translate": "achievement.ae2.CraftingCPU.desc" }
"icon": {
"item": "appliedenergistics2:crafting_storage_64k"
},
"title": {
"translate": "achievement.ae2.CraftingCPU"
},
"description": {
"translate": "achievement.ae2.CraftingCPU.desc"
}
},
"parent": "appliedenergistics2:main/pattern_terminal",
"criteria": {
@@ -47,9 +51,14 @@
}
]
}
}
}
},
"requirements": [
[ "c1k", "c4k", "c16k", "c64k" ]
[
"c1k",
"c4k",
"c16k",
"c64k"
]
]
}
}
@@ -1,10 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:part", "data": 360
},
"title": { "translate": "achievement.ae2.CraftingTerminal" },
"description": { "translate": "achievement.ae2.CraftingTerminal.desc" }
"icon": {
"item": "appliedenergistics2:part",
"data": 360
},
"title": {
"translate": "achievement.ae2.CraftingTerminal"
},
"description": {
"translate": "achievement.ae2.CraftingTerminal.desc"
}
},
"parent": "appliedenergistics2:main/controller",
"criteria": {
@@ -13,11 +18,11 @@
"conditions": {
"items": [
{
"type": "appliedenergistics2:part",
"part": "CRAFTING_TERMINAL"
"type": "appliedenergistics2:part",
"part": "CRAFTING_TERMINAL"
}
]
}
}
}
}
}
@@ -1,8 +1,14 @@
{
"display": {
"icon": { "item": "appliedenergistics2:facade" },
"title": { "translate": "achievement.ae2.Facade" },
"description": { "translate": "achievement.ae2.Facade.desc" }
"icon": {
"item": "appliedenergistics2:facade"
},
"title": {
"translate": "achievement.ae2.Facade"
},
"description": {
"translate": "achievement.ae2.Facade.desc"
}
},
"parent": "appliedenergistics2:main/cable_glass",
"criteria": {
@@ -17,4 +23,4 @@
}
}
}
}
}
@@ -1,11 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:material",
"data": 7
},
"title": { "translate": "achievement.ae2.Fluix" },
"description": { "translate": "achievement.ae2.Fluix.desc" }
"icon": {
"item": "appliedenergistics2:material",
"data": 7
},
"title": {
"translate": "achievement.ae2.Fluix"
},
"description": {
"translate": "achievement.ae2.Fluix.desc"
}
},
"parent": "appliedenergistics2:main/charged_quartz",
"criteria": {
@@ -14,11 +18,11 @@
"conditions": {
"items": [
{
"item": "appliedenergistics2:material",
"item": "appliedenergistics2:material",
"data": 7
}
]
}
}
}
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:quartz_growth_accelerator"
},
"title": { "translate": "achievement.ae2.CrystalGrowthAccelerator" },
"description": { "translate": "achievement.ae2.CrystalGrowthAccelerator.desc" }
"icon": {
"item": "appliedenergistics2:quartz_growth_accelerator"
},
"title": {
"translate": "achievement.ae2.CrystalGrowthAccelerator"
},
"description": {
"translate": "achievement.ae2.CrystalGrowthAccelerator.desc"
}
},
"parent": "appliedenergistics2:main/fluix",
"criteria": {
@@ -19,4 +23,4 @@
}
}
}
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:interface"
},
"title": { "translate": "achievement.ae2.Recursive" },
"description": { "translate": "achievement.ae2.Recursive.desc" }
"icon": {
"item": "appliedenergistics2:interface"
},
"title": {
"translate": "achievement.ae2.Recursive"
},
"description": {
"translate": "achievement.ae2.Recursive.desc"
}
},
"parent": "appliedenergistics2:main/cable_glass",
"criteria": {
@@ -19,4 +23,4 @@
}
}
}
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:io_port"
},
"title": { "translate": "achievement.ae2.IOPort" },
"description": { "translate": "achievement.ae2.IOPort.desc" }
"icon": {
"item": "appliedenergistics2:io_port"
},
"title": {
"translate": "achievement.ae2.IOPort"
},
"description": {
"translate": "achievement.ae2.IOPort.desc"
}
},
"parent": "appliedenergistics2:main/storage_cell",
"criteria": {
@@ -19,4 +23,4 @@
}
}
}
}
}
@@ -1,15 +1,20 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:part", "data": 36
},
"title": { "translate": "achievement.ae2.Networking1" },
"description": { "translate": "achievement.ae2.Networking1.desc" }
"icon": {
"item": "appliedenergistics2:part",
"data": 36
},
"title": {
"translate": "achievement.ae2.Networking1"
},
"description": {
"translate": "achievement.ae2.Networking1.desc"
}
},
"parent": "appliedenergistics2:main/cable_glass",
"criteria": {
"cable": {
"trigger": "appliedenergistics2:network_apprentice"
"trigger": "appliedenergistics2:network_apprentice"
}
}
}
}
@@ -1,10 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:part", "data": 56
},
"title": { "translate": "achievement.ae2.Networking2" },
"description": { "translate": "achievement.ae2.Networking2.desc" }
"icon": {
"item": "appliedenergistics2:part",
"data": 56
},
"title": {
"translate": "achievement.ae2.Networking2"
},
"description": {
"translate": "achievement.ae2.Networking2.desc"
}
},
"parent": "appliedenergistics2:main/network1",
"criteria": {
@@ -12,4 +17,4 @@
"trigger": "appliedenergistics2:network_engineer"
}
}
}
}
@@ -1,10 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:part", "data": 76
},
"title": { "translate": "achievement.ae2.Networking3" },
"description": { "translate": "achievement.ae2.Networking3.desc" }
"icon": {
"item": "appliedenergistics2:part",
"data": 76
},
"title": {
"translate": "achievement.ae2.Networking3"
},
"description": {
"translate": "achievement.ae2.Networking3.desc"
}
},
"parent": "appliedenergistics2:main/network2",
"criteria": {
@@ -12,4 +17,4 @@
"trigger": "appliedenergistics2:network_admin"
}
}
}
}
@@ -1,8 +1,14 @@
{
"display": {
"icon": { "item": "appliedenergistics2:network_tool" },
"title": { "translate": "achievement.ae2.NetworkTool" },
"description": { "translate": "achievement.ae2.NetworkTool.desc" }
"icon": {
"item": "appliedenergistics2:network_tool"
},
"title": {
"translate": "achievement.ae2.NetworkTool"
},
"description": {
"translate": "achievement.ae2.NetworkTool.desc"
}
},
"parent": "appliedenergistics2:main/controller",
"criteria": {
@@ -17,4 +23,4 @@
}
}
}
}
}
@@ -1,10 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:part", "data": 460
},
"title": { "translate": "achievement.ae2.P2P" },
"description": { "translate": "achievement.ae2.P2P.desc" }
"icon": {
"item": "appliedenergistics2:part",
"data": 460
},
"title": {
"translate": "achievement.ae2.P2P"
},
"description": {
"translate": "achievement.ae2.P2P.desc"
}
},
"parent": "appliedenergistics2:main/cable_glass",
"criteria": {
@@ -13,11 +18,11 @@
"conditions": {
"items": [
{
"type": "appliedenergistics2:part",
"part": "P2P_TUNNEL_ME"
"type": "appliedenergistics2:part",
"part": "P2P_TUNNEL_ME"
}
]
}
}
}
}
}
@@ -1,10 +1,15 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:part", "data": 340
},
"title": { "translate": "achievement.ae2.PatternTerminal" },
"description": { "translate": "achievement.ae2.PatternTerminal.desc" }
"icon": {
"item": "appliedenergistics2:part",
"data": 340
},
"title": {
"translate": "achievement.ae2.PatternTerminal"
},
"description": {
"translate": "achievement.ae2.PatternTerminal.desc"
}
},
"parent": "appliedenergistics2:main/crafting_terminal",
"criteria": {
@@ -13,11 +18,11 @@
"conditions": {
"items": [
{
"type": "appliedenergistics2:part",
"part": "PATTERN_TERMINAL"
"type": "appliedenergistics2:part",
"part": "PATTERN_TERMINAL"
}
]
}
}
}
}
}
@@ -1,8 +1,14 @@
{
"display": {
"icon": { "item": "appliedenergistics2:portable_cell" },
"title": { "translate": "achievement.ae2.PortableCell" },
"description": { "translate": "achievement.ae2.PortableCell.desc" }
"icon": {
"item": "appliedenergistics2:portable_cell"
},
"title": {
"translate": "achievement.ae2.PortableCell"
},
"description": {
"translate": "achievement.ae2.PortableCell.desc"
}
},
"parent": "appliedenergistics2:main/storage_cell",
"criteria": {
@@ -17,4 +23,4 @@
}
}
}
}
}
@@ -1,8 +1,15 @@
{
"display": {
"icon": { "item": "appliedenergistics2:material", "data": 15 },
"title": { "translate": "achievement.ae2.Presses" },
"description": { "translate": "achievement.ae2.Presses.desc" }
"icon": {
"item": "appliedenergistics2:material",
"data": 15
},
"title": {
"translate": "achievement.ae2.Presses"
},
"description": {
"translate": "achievement.ae2.Presses.desc"
}
},
"parent": "appliedenergistics2:main/root",
"criteria": {
@@ -11,7 +18,8 @@
"conditions": {
"items": [
{
"item": "appliedenergistics2:material", "data": 13
"item": "appliedenergistics2:material",
"data": 13
}
]
}
@@ -21,7 +29,8 @@
"conditions": {
"items": [
{
"item": "appliedenergistics2:material", "data": 14
"item": "appliedenergistics2:material",
"data": 14
}
]
}
@@ -31,7 +40,8 @@
"conditions": {
"items": [
{
"item": "appliedenergistics2:material", "data": 15
"item": "appliedenergistics2:material",
"data": 15
}
]
}
@@ -41,13 +51,19 @@
"conditions": {
"items": [
{
"item": "appliedenergistics2:material", "data": 19
"item": "appliedenergistics2:material",
"data": 19
}
]
}
}
},
"requirements": [
[ "calc", "eng", "logic", "silicon" ]
[
"calc",
"eng",
"logic",
"silicon"
]
]
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:quantum_link"
},
"title": { "translate": "achievement.ae2.QNB" },
"description": { "translate": "achievement.ae2.QNB.desc" }
"icon": {
"item": "appliedenergistics2:quantum_link"
},
"title": {
"translate": "achievement.ae2.QNB"
},
"description": {
"translate": "achievement.ae2.QNB.desc"
}
},
"parent": "appliedenergistics2:main/p2p",
"criteria": {
@@ -19,4 +23,4 @@
}
}
}
}
}
@@ -1,14 +1,18 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:material",
"data": 0
},
"title": { "translate": "achievement.ae2.Root" },
"description": { "translate": "achievement.ae2.Root.desc" },
"background": "appliedenergistics2:textures/blocks/sky_stone_brick.png",
"show_toast": false,
"announce_to_chat": false
"icon": {
"item": "appliedenergistics2:material",
"data": 0
},
"title": {
"translate": "achievement.ae2.Root"
},
"description": {
"translate": "achievement.ae2.Root.desc"
},
"background": "appliedenergistics2:textures/blocks/sky_stone_brick.png",
"show_toast": false,
"announce_to_chat": false
},
"criteria": {
"certus": {
@@ -16,11 +20,11 @@
"conditions": {
"items": [
{
"item": "appliedenergistics2:material",
"item": "appliedenergistics2:material",
"data": 0
}
]
}
}
}
}
}
@@ -1,15 +1,19 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:spatial_storage_cell_128_cubed"
},
"title": { "translate": "achievement.ae2.SpatialIOExplorer" },
"description": { "translate": "achievement.ae2.SpatialIOExplorer.desc" }
"icon": {
"item": "appliedenergistics2:spatial_storage_cell_128_cubed"
},
"title": {
"translate": "achievement.ae2.SpatialIOExplorer"
},
"description": {
"translate": "achievement.ae2.SpatialIOExplorer.desc"
}
},
"parent": "appliedenergistics2:main/spatial_ioport",
"criteria": {
"explorer": {
"trigger": "appliedenergistics2:spatial_explorer"
"trigger": "appliedenergistics2:spatial_explorer"
}
}
}
}
@@ -1,10 +1,14 @@
{
"display": {
"icon": {
"item": "appliedenergistics2:spatial_io_port"
},
"title": { "translate": "achievement.ae2.SpatialIO" },
"description": { "translate": "achievement.ae2.SpatialIO.desc" }
"icon": {
"item": "appliedenergistics2:spatial_io_port"
},
"title": {
"translate": "achievement.ae2.SpatialIO"
},
"description": {
"translate": "achievement.ae2.SpatialIO.desc"
}
},
"parent": "appliedenergistics2:main/ioport",
"criteria": {
@@ -19,4 +23,4 @@
}
}
}
}
}

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