Compare commits

...

51 Commits

Author SHA1 Message Date
yueh 36d6681eac Rework fuzzy comparison for 99 percent threshold (#3367)
* Rework fuzzy comparison for 99 percent threshold

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

* Use metadata explicitly for comparison

Some item could use metadata to pack damageable and undamageable items
into the same id. Thus could lead to get ItemStack#getItemDamage() to
return bogus values for undamageable items.
2018-02-05 15:20:02 +01:00
yueh 6cffe93970 Fixes #3370: Avoid caching the model for facades locally. (#3371) 2018-02-05 15:19:20 +01:00
yueh b1472c58d0 Fixes #3363: Energy providers/requesters incorrectly removed on simulate (#3364) 2018-01-29 15:30:56 +01:00
yueh 96450a76c7 Fixes #3239: Torches should not be placeable on cranks. (#3359) 2018-01-28 13:47:49 +01:00
yueh ac209053b9 Fixes #3345: Added missing sky stone brick recipes. (#3357) 2018-01-28 13:31:07 +01:00
Foxgreat dce1aa37eb Update ru_RU.lang (#3336) 2018-01-28 12:52:53 +01:00
sfs131010 0b6831e4d7 Update zh_TW.lang (#3337) 2018-01-28 12:52:25 +01:00
yueh da6d8ba9a8 Fixes #3338: Upgrade inventory dupe bug due to ignoring player hand. (#3340) 2018-01-28 12:50:20 +01:00
yueh f0e45c7a3c Fixes #3288: Fixes various item rotations when held in 3rd person. (#3330) 2018-01-14 14:36:04 +01:00
fscan cbfc88c87f Fix light sync (#3304)
* Sync light opacity changes to client
* While at it, also fix Light P2P
* Use int for opacity, dont store it in NBT
2018-01-14 13:44:12 +01:00
yueh 8c5842aca9 Fixes #3315: Slightly more permissive checks for autocrafting (#3319)
* Fixes #3315: Slightly more permissive checks for autocrafting

Also fixes a bug in the fallback for looking up patterns to only use
ItemStack.EMPTY.
2018-01-14 13:43:31 +01:00
yueh 483049f555 Fixes #3293: Only update light level if the panel-facing block changes. (#3302) 2017-12-31 13:11:26 +01:00
yueh a7a65ae39d Fixes #3296: Prevent invalid TileEntites from updating their block. (#3301)
Updating the blockstate of invalid TEs will cause Forge to restore the
block including the TE leading to invalid TEs sticking around after
being moved.
2017-12-31 13:06:18 +01:00
yueh 45878df17d Fixes #3286: Incorrectly inverted hasSkyLight causes crashes on spatial transfer. (#3299) 2017-12-31 13:06:08 +01:00
yueh 98142d8ade Fixes CraftTweaker deploying incomplete releases. (#3300)
Due to CraftTweaker not deploying necessary dependencies, we cannot
rely on building against the most recent compatible version. Instead we
have to build against a specific known release to avoid it but have to
risk incompatibilities should there be changes on later versions.
2017-12-30 11:12:04 +01:00
yueh 7956872d1d Reworked IO Port to handle StorageChannels better. (#3284)
* Reworked IO Port to handle custom StorageChannels in a better way.
* Added a transferFactor to `IStorageChannel` to allow addons to speedup the IO Port to transfer faster. E.g. 1000 mB fluid as fast as transfering 1 bucket (item) per operation, not just 1 mB. 
* Also some changes to avoid moving fluids being 1000x as energy expensive as items.
2017-12-21 19:12:45 +01:00
yueh e243c8e9a2 Adds a debug generator for ForgeEnergy. (#3259)
* Adds a debug generator for ForgeEnergy.

This adds a simple debug block to test external energy injection via
ForgeEnergy and not rely solely on creative cells.

The energy has two functions. The first is acting as an infinite
ForgEnergy battery, this is unused by AE2 itself as nothing pulls
energy.
The second one is injecting energy every tick into any adjacent block
accepting ForgeEnergy.
The base generation is 8 per tick, but this is increased by the power of
adjacent TileEnergyGenerators.
2017-12-21 17:29:39 +01:00
yueh 641d0d40cc Fixes #3265: Do not strip special chars when extracting recipes. (#3266) 2017-12-21 17:28:31 +01:00
yueh 50fad685b6 Fixes #3282: Stacksizes > 64 prevent applicator from cycling. (#3287) 2017-12-21 17:28:16 +01:00
yueh 1ad49edd76 Fixes #3260: Only match damaged items when selected and set to 99%. (#3261) 2017-12-01 21:14:29 +01:00
yueh 7ceaa4cc3e Fixes #3217: Allow caps to be used as P2P attunements. (#3257)
Adds a more abstract approach to map a cap to a certain type instead of
the hardcoded ForgeEnergy case.
Reorders the check from exact ItemStack > ModId > ForgeEnergy to
ItemStack > Cap > ModId. Thus the mod wildcard will be used last.
Support for ForgeEnergy and FluidHandlerItems by default.
Result for items supporting multiple capabilities is not defined.
2017-12-01 21:14:11 +01:00
yueh b70c86542b Fixes #3255: Cache invalid patterns instead computing them every frame. (#3256) 2017-12-01 21:13:23 +01:00
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
728 changed files with 19702 additions and 11170 deletions
+52
View File
@@ -14,6 +14,7 @@
* [Building](#building) * [Building](#building)
* [Contribution](#contribution) * [Contribution](#contribution)
* [API](#applied-energistics-2-api) * [API](#applied-energistics-2-api)
* [CraftTweaker](#applied-energistics-2-crafttweaker)
* [Localization](#applied-energistics-2-localization) * [Localization](#applied-energistics-2-localization)
* [Credits](#credits) * [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` 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 ## Applied Energistics 2 Localization
### English Text ### English Text
+2 -1
View File
@@ -9,7 +9,7 @@ aebasename=appliedenergistics2
######################################################### #########################################################
minecraft_version=1.12.2 minecraft_version=1.12.2
mcp_mappings=snapshot_20171003 mcp_mappings=snapshot_20171003
forge_version=14.23.0.2491 forge_version=14.23.1.2554
######################################################### #########################################################
# Installable # # Installable #
@@ -24,6 +24,7 @@ tesla_version=1.0.61
ic2_version=2.8.19-ex112 ic2_version=2.8.19-ex112
top_version=1.12-1.4.18-10 top_version=1.12-1.4.18-10
cofhcore_version=1.12-4.+ cofhcore_version=1.12-4.+
crafttweaker_version=4.0.10.310
######################################################### #########################################################
# Deployment # # Deployment #
+6
View File
@@ -58,6 +58,11 @@ repositories {
name 'tehnut' name 'tehnut'
url "http://tehnut.info/maven" url "http://tehnut.info/maven"
} }
maven { // CraftTweaker
name 'jared maven'
url "http://maven.blamejared.com/"
}
} }
configurations { configurations {
@@ -77,6 +82,7 @@ dependencies {
compileOnly "net.industrial-craft:industrialcraft-2:${ic2_version}:api" compileOnly "net.industrial-craft:industrialcraft-2:${ic2_version}:api"
compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api" compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api"
compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf" compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf"
compileOnly "CraftTweaker2:CraftTweaker2-API:${crafttweaker_version}"
// at runtime, use the full JEI jar // at runtime, use the full JEI jar
runtime "mezz.jei:jei_${minecraft_version}:${jei_version}" runtime "mezz.jei:jei_${minecraft_version}:${jei_version}"
@@ -28,6 +28,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraftforge.common.capabilities.Capability;
import appeng.api.config.TunnelType; import appeng.api.config.TunnelType;
@@ -47,6 +48,7 @@ public interface IP2PTunnelRegistry
*/ */
void addNewAttunement( @Nonnull ItemStack trigger, @Nullable TunnelType type ); void addNewAttunement( @Nonnull ItemStack trigger, @Nullable TunnelType type );
void addNewAttunement( @Nonnull String ModId, @Nullable TunnelType type ); void addNewAttunement( @Nonnull String ModId, @Nullable TunnelType type );
void addNewAttunement( @Nonnull Capability<?> cap, @Nullable TunnelType type );
/** /**
* returns null if no attunement can be found. * returns null if no attunement can be found.
@@ -48,6 +48,7 @@ public interface IRecipeHandlerRegistry
* @param name name of crafthandler * @param name name of crafthandler
* @param handler class of crafthandler * @param handler class of crafthandler
*/ */
@Deprecated
void addNewCraftHandler( String name, Class<? extends ICraftHandler> handler ); 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. * @return A recipe handler by name, returns null on failure.
*/ */
@Nullable @Nullable
@Deprecated
ICraftHandler getCraftHandlerFor( String name ); ICraftHandler getCraftHandlerFor( String name );
/** /**
* @return a new recipe handler, which can be used to parse, and read recipe files. * @return a new recipe handler, which can be used to parse, and read recipe files.
*/ */
@Deprecated
IRecipeHandler createNewRecipehandler(); IRecipeHandler createNewRecipehandler();
/** /**
@@ -30,7 +30,7 @@ import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException; import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException; import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface ICraftHandler public interface ICraftHandler
{ {
@@ -29,7 +29,7 @@ import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException; import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException; import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface IIngredient public interface IIngredient
{ {
@@ -27,6 +27,7 @@ package appeng.api.recipes;
/** /**
* Represents the AE2 Recipe Loading/Reading Class * Represents the AE2 Recipe Loading/Reading Class
*/ */
@Deprecated
public interface IRecipeHandler public interface IRecipeHandler
{ {
@@ -28,7 +28,7 @@ import java.io.BufferedReader;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@Deprecated
public interface IRecipeLoader public interface IRecipeLoader
{ {
/** /**
@@ -43,6 +43,19 @@ import appeng.api.storage.data.IItemList;
public interface IStorageChannel<T extends IAEStack<T>> public interface IStorageChannel<T extends IAEStack<T>>
{ {
/**
* Can be used as factor for transferring stacks of a channel.
*
* E.g. used by IO Ports to transfer 1000 mB, not 1 mB to match the
* item channel transferring a full bucket per operation.
*
* @return
*/
default int transferFactor()
{
return 1;
}
/** /**
* Create a new {@link IItemList} of the specific type. * Create a new {@link IItemList} of the specific type.
* *
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -32,6 +33,7 @@ import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayer;
@@ -164,4 +166,16 @@ public class BlockCrank extends AEBaseTileBlock
return false; return false;
} }
@Override
public boolean canPlaceTorchOnTop( IBlockState state, IBlockAccess world, BlockPos pos )
{
return false;
}
@Override
public BlockFaceShape getBlockFaceShape( IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face )
{
return BlockFaceShape.UNDEFINED;
}
} }
@@ -101,7 +101,6 @@ public class BlockCableBus extends AEBaseTileBlock
// this will actually be overwritten later through setupTile and the // this will actually be overwritten later through setupTile and the
// combined layers // combined layers
this.setTileEntity( TileCableBus.class ); this.setTileEntity( TileCableBus.class );
this.useNeighborBrightness = true;
} }
@Override @Override
@@ -47,9 +47,9 @@ import appeng.util.Platform;
public class BlockSkyChest extends AEBaseTileBlock implements ICustomCollision public class BlockSkyChest extends AEBaseTileBlock implements ICustomCollision
{ {
private static final double AABB_OFFSET_BOTTOM = .0625d; private static final double AABB_OFFSET_BOTTOM = 0.00;
private static final double AABB_OFFSET_SIDES = 0; private static final double AABB_OFFSET_SIDES = 0.06;
private static final double AABB_OFFSET_TOP = .125d; private static final double AABB_OFFSET_TOP = 0.125;
public enum SkyChestType public enum SkyChestType
{ {
@@ -111,18 +111,18 @@ public class BlockSkyChest extends AEBaseTileBlock implements ICustomCollision
o = sk.getUp(); o = sk.getUp();
} }
final double offsetX = o.getFrontOffsetX() == 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_BOTTOM : AABB_OFFSET_SIDES; final double offsetY = o.getFrontOffsetY() == 0 ? AABB_OFFSET_SIDES : 0.0;
final double offsetZ = o.getFrontOffsetZ() == 0 ? AABB_OFFSET_BOTTOM : AABB_OFFSET_SIDES; 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. // for x/z top and bottom is swapped
final double minX = Math.max( 0.0, offsetX + o.getFrontOffsetX() * AABB_OFFSET_TOP ); 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() * 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() * AABB_OFFSET_TOP ); 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 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() * AABB_OFFSET_TOP ); 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() * 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 ); return new AxisAlignedBB( minX, minY, minZ, maxX, maxY, maxZ );
} }
@@ -23,7 +23,6 @@ import java.text.NumberFormat;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.inventory.Container; import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot; import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -43,70 +42,17 @@ public abstract class AEBaseMEGui extends AEBaseGui
super( container ); 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 @Override
protected void renderToolTip( final ItemStack stack, final int x, final int y ) protected void renderToolTip( final ItemStack stack, final int x, final int y )
{ {
final Slot s = this.getSlot( x, y ); final Slot s = this.getSlot( x, y );
if( s instanceof SlotME && !stack.isEmpty() ) 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; IAEItemStack myStack = null;
final List<String> currentToolTip = this.getItemToolTip( stack );
try 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 ) 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 ) 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; return;
} }
else if( stack.getCount() > BigNumber ) else if( stack.getCount() > bigNumber )
{ {
List<String> var4 = stack.getTooltip( this.mc.player, tooltipFlag ); final String local = ButtonToolTips.ItemsStored.getLocal();
var4.add( "Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() ) ); final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() );
this.drawTooltip( x, y, var4 ); final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
this.drawHoveringText( currentToolTip, x, y, this.fontRenderer );
return; return;
} }
} }
super.renderToolTip( stack, x, y ); 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 ); this.getScrollBar().setRange( 0, ( size + 4 ) / 5 - this.rows, 1 );
} }
// Vanilla version... @Override
protected void drawItemStackTooltip( final ItemStack stack, final int x, final int y ) protected void renderToolTip( final ItemStack stack, final int x, final int y )
{ {
final Slot s = this.getSlot( x, y ); final Slot s = this.getSlot( x, y );
if( s instanceof SlotME && stack != null ) if( s instanceof SlotME && stack != null )
{ {
IAEItemStack myStack = null; IAEItemStack myStack = null;
@@ -270,7 +271,8 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource
this.drawTooltip( x, y, currentToolTip ); this.drawTooltip( x, y, currentToolTip );
} }
} }
// super.drawItemStackTooltip( stack, x, y );
super.renderToolTip( stack, x, y );
} }
@Override @Override
@@ -92,7 +92,7 @@ public class GuiSpatialIOPort extends AEBaseGui
} }
else 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.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel; 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.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -44,16 +42,13 @@ import appeng.items.parts.ItemFacade;
* on the item stack. * on the item stack.
* A custom Item Override List is used to accomplish this. * 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; private final VertexFormat format;
public FacadeDispatcherBakedModel( IBakedModel baseModel, VertexFormat format ) public FacadeDispatcherBakedModel( IBakedModel baseModel, VertexFormat format )
{ {
this.baseModel = baseModel; super( baseModel );
this.format = format; this.format = format;
} }
@@ -64,16 +59,10 @@ public class FacadeDispatcherBakedModel implements IBakedModel
return Collections.emptyList(); return Collections.emptyList();
} }
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
}
@Override @Override
public boolean isGui3d() public boolean isGui3d()
{ {
return this.baseModel.isGui3d(); return this.getBaseModel().isGui3d();
} }
@Override @Override
@@ -82,18 +71,6 @@ public class FacadeDispatcherBakedModel implements IBakedModel
return false; return false;
} }
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override @Override
public ItemOverrideList getOverrides() public ItemOverrideList getOverrides()
{ {
@@ -112,7 +89,8 @@ public class FacadeDispatcherBakedModel implements IBakedModel
IBlockState state = itemFacade.getTextureBlockState( stack ); IBlockState state = itemFacade.getTextureBlockState( stack );
ItemStack textureItem = itemFacade.getTextureItem( 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.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry; import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState; import net.minecraftforge.common.model.IModelState;
import net.minecraftforge.common.model.TRSRTransformation;
import appeng.core.AppEng; import appeng.core.AppEng;
@@ -41,10 +40,21 @@ import appeng.core.AppEng;
*/ */
public class FacadeItemModel implements IModel public class FacadeItemModel implements IModel
{ {
// We use this to get the default item transforms and make our lives easier // 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 static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "item/facade_base" );
private IModel getBaseModel()
{
try
{
return ModelLoaderRegistry.getModel( MODEL_BASE );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
}
@Override @Override
public Collection<ResourceLocation> getDependencies() public Collection<ResourceLocation> getDependencies()
{ {
@@ -60,17 +70,7 @@ public class FacadeItemModel implements IModel
@Override @Override
public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter ) public IBakedModel bake( IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter )
{ {
IModel baseModel; IBakedModel bakedBaseModel = this.getBaseModel().bake( state, format, bakedTextureGetter );
try
{
baseModel = ModelLoaderRegistry.getModel( MODEL_BASE );
}
catch( Exception e )
{
throw new RuntimeException( e );
}
IBakedModel bakedBaseModel = baseModel.bake( state, format, bakedTextureGetter );
return new FacadeDispatcherBakedModel( bakedBaseModel, format ); return new FacadeDispatcherBakedModel( bakedBaseModel, format );
} }
@@ -78,6 +78,6 @@ public class FacadeItemModel implements IModel
@Override @Override
public IModelState getDefaultState() public IModelState getDefaultState()
{ {
return TRSRTransformation.identity(); return this.getBaseModel().getDefaultState();
} }
} }
@@ -29,9 +29,7 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel; 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.block.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing; 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 * 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. * 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 IBlockState blockState;
private final IBakedModel textureModel; private final IBakedModel textureModel;
@@ -59,7 +54,7 @@ public class FacadeWithBlockBakedModel implements IBakedModel
public FacadeWithBlockBakedModel( IBakedModel baseModel, IBlockState blockState, ItemStack textureItem, VertexFormat format ) public FacadeWithBlockBakedModel( IBakedModel baseModel, IBlockState blockState, ItemStack textureItem, VertexFormat format )
{ {
this.baseModel = baseModel; super( baseModel );
this.blockState = blockState; this.blockState = blockState;
this.textureItem = textureItem; this.textureItem = textureItem;
this.textureModel = Minecraft.getMinecraft().getBlockRendererDispatcher().getModelForState( blockState ); this.textureModel = Minecraft.getMinecraft().getBlockRendererDispatcher().getModelForState( blockState );
@@ -88,13 +83,7 @@ public class FacadeWithBlockBakedModel implements IBakedModel
} }
} }
return this.baseModel.getQuads( state, side, rand ); return this.getBaseModel().getQuads( state, side, rand );
}
@Override
public boolean isAmbientOcclusion()
{
return this.baseModel.isAmbientOcclusion();
} }
@Override @Override
@@ -109,18 +98,6 @@ public class FacadeWithBlockBakedModel implements IBakedModel
return false; return false;
} }
@Override
public TextureAtlasSprite getParticleTexture()
{
return this.baseModel.getParticleTexture();
}
@Override
public ItemCameraTransforms getItemCameraTransforms()
{
return this.baseModel.getItemCameraTransforms();
}
@Override @Override
public ItemOverrideList getOverrides() public ItemOverrideList getOverrides()
{ {
@@ -22,6 +22,7 @@ package appeng.client.render.cablebus;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -52,6 +53,8 @@ import appeng.block.networking.BlockCableBus;
public class CableBusBakedModel implements IBakedModel public class CableBusBakedModel implements IBakedModel
{ {
private static final Map<CableBusRenderState, List<BakedQuad>> CABLE_MODEL_CACHE = new HashMap<>();
private final CableBuilder cableBuilder; private final CableBuilder cableBuilder;
private final FacadeBuilder facadeBuilder; private final FacadeBuilder facadeBuilder;
@@ -88,8 +91,15 @@ public class CableBusBakedModel implements IBakedModel
// translucent facades further down below. // translucent facades further down below.
if( layer == BlockRenderLayer.CUTOUT ) if( layer == BlockRenderLayer.CUTOUT )
{ {
// First, handle the cable at the center of the cable bus // 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 // Then handle attachments
for( EnumFacing facing : EnumFacing.values() ) for( EnumFacing facing : EnumFacing.values() )
@@ -308,10 +318,8 @@ public class CableBusBakedModel implements IBakedModel
TextureAtlasSprite particleTexture = bakedModel.getParticleTexture(); TextureAtlasSprite particleTexture = bakedModel.getParticleTexture();
// If a part sub-model has no particle texture (indicated by it being the missing texture), don't // If a part sub-model has no particle texture (indicated by it being the missing texture),
// add // don't add it, so we don't get ugly missing texture break particles.
// it,
// so we don't get ugly missing texture break particles.
if( this.textureMap.getMissingSprite() != particleTexture ) if( this.textureMap.getMissingSprite() != particleTexture )
{ {
result.add( particleTexture ); result.add( particleTexture );
@@ -336,7 +344,7 @@ public class CableBusBakedModel implements IBakedModel
@Override @Override
public boolean isAmbientOcclusion() public boolean isAmbientOcclusion()
{ {
return false; return true;
} }
@Override @Override
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Objects;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
@@ -153,4 +154,43 @@ public class CableBusRenderState
return this.boundingBoxes; 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 int color = 0xFFFFFFFF;
private boolean useStandardUV = false;
private boolean renderFullBright; private boolean renderFullBright;
public CubeBuilder( VertexFormat format, List<BakedQuad> output ) public CubeBuilder( VertexFormat format, List<BakedQuad> output )
@@ -142,7 +144,9 @@ public class CubeBuilder
UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( this.format ); UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder( this.format );
builder.setTexture( texture ); builder.setTexture( texture );
builder.setQuadOrientation( face ); builder.setQuadOrientation( face );
builder.setQuadTint( -1 );
builder.setApplyDiffuseLighting( true );
UvVector uv = new UvVector(); UvVector uv = new UvVector();
// The user might have set specific UV coordinates for this face // 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.u2 = texture.getInterpolatedU( customUv.z );
uv.v2 = texture.getInterpolatedV( customUv.w ); uv.v2 = texture.getInterpolatedV( customUv.w );
} }
else if( this.useStandardUV )
{
uv = this.getStandardUv( face, texture, x1, y1, z1, x2, y2, z2 );
}
else else
{ {
uv = this.getDefaultUv( face, texture, x1, y1, z1, x2, y2, z2 ); uv = this.getDefaultUv( face, texture, x1, y1, z1, x2, y2, z2 );
@@ -199,8 +207,7 @@ public class CubeBuilder
break; break;
} }
int[] vertexData = builder.build().getVertexData(); this.output.add( builder.build() );
this.output.add( new BakedQuad( vertexData, -1, face, texture, true, this.format ) );
} }
private UvVector getDefaultUv( EnumFacing face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2 ) 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; 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 // uv.u1, uv.v1
private void putVertexTL( UnpackedBakedQuad.Builder builder, EnumFacing face, float x, float y, float z, UvVector uv ) 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; 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() public List<BakedQuad> getOutput()
{ {
return this.output; return this.output;
@@ -175,6 +175,7 @@ public class FacadeBuilder
// Reset to no color multiplicator // Reset to no color multiplicator
builder.setColorRGB( 0xFFFFFF ); 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 // 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 ) if( renderStilt && busBounds == null && layer == BlockRenderLayer.CUTOUT )
@@ -438,22 +439,22 @@ public class FacadeBuilder
private static AxisAlignedBB getFacadeBox( EnumFacing side, boolean thinFacades ) private static AxisAlignedBB getFacadeBox( EnumFacing side, boolean thinFacades )
{ {
int thickness = thinFacades ? 1 : 2; double thickness = ( thinFacades ? 1 : 2 ) / 16.0;
switch( side ) switch( side )
{ {
case DOWN: 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: 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: 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: 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: 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: 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: default:
throw new IllegalArgumentException( "Unsupported face: " + side ); throw new IllegalArgumentException( "Unsupported face: " + side );
} }
@@ -19,14 +19,11 @@
package appeng.container; package appeng.container;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -37,8 +34,6 @@ import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot; import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.PlayerInvWrapper; import net.minecraftforge.items.wrapper.PlayerInvWrapper;
@@ -73,7 +68,7 @@ import appeng.container.slot.SlotPlayerInv;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInventoryAction; 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.core.sync.packets.PacketValueConfig;
import appeng.helpers.ICustomNameObject; import appeng.helpers.ICustomNameObject;
import appeng.helpers.InventoryAction; import appeng.helpers.InventoryAction;
@@ -93,7 +88,6 @@ public abstract class AEBaseContainer extends Container
private final TileEntity tileEntity; private final TileEntity tileEntity;
private final IPart part; private final IPart part;
private final IGuiItemObject obj; private final IGuiItemObject obj;
private final List<PacketPartialItem> dataChunks = new LinkedList<>();
private final HashMap<Integer, SyncData> syncData = new HashMap<>(); private final HashMap<Integer, SyncData> syncData = new HashMap<>();
private boolean isContainerValid = true; private boolean isContainerValid = true;
private String customName; private String customName;
@@ -175,47 +169,6 @@ public abstract class AEBaseContainer extends Container
this.prepareSync(); 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() public IAEItemStack getTargetStack()
{ {
return this.clientRequestedTargetItem; return this.clientRequestedTargetItem;
@@ -235,47 +188,7 @@ public abstract class AEBaseContainer extends Container
return; return;
} }
final ByteArrayOutputStream stream = new ByteArrayOutputStream(); NetworkHandler.instance().sendToServer( new PacketTargetItemStack( (AEItemStack) stack ) );
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;
}
} }
this.clientRequestedTargetItem = stack == null ? null : stack.copy(); this.clientRequestedTargetItem = stack == null ? null : stack.copy();
@@ -120,28 +120,23 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
if( s == this.middle ) 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 !press.isSameAs( is );
{
return false;
}
} }
boolean matches = false; boolean matches = false;
boolean found = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() )
{ {
final boolean matchA = ( top.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top, final boolean matchA = !top
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and... .isEmpty() && ( Platform.itemComparisons().isSameItem( top, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
( ( bot.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot, .itemComparisons()
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) ); .isSameItem( top, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
final boolean matchB = !bot
final boolean matchB = ( bot.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot, .isEmpty() && ( Platform.itemComparisons().isSameItem( bot, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and... .itemComparisons()
( ( top.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top, .isSameItem( bot, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) );
if( matchA || matchB ) if( matchA || matchB )
{ {
@@ -150,21 +145,19 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
{ {
if( Platform.itemComparisons().isSameItem( is, option ) ) if( Platform.itemComparisons().isSameItem( is, option ) )
{ {
found = true; return true;
} }
} }
} }
} }
if( matches )
if( matches && !found )
{ {
return false; return false;
} }
} }
else if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
{ {
ItemStack otherSlot = ItemStack.EMPTY; ItemStack otherSlot;
if( s == this.top ) if( s == this.top )
{ {
otherSlot = this.bottom.getStack(); otherSlot = this.bottom.getStack();
@@ -182,28 +175,24 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
} }
// everything else // everything else
boolean isValid = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() ) 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 ) ); 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 ) ); isValid = Platform.itemComparisons().isSameItem( is, recipe.getTopOptional().orElse( ItemStack.EMPTY ) );
} }
if( isValid ) if( isValid )
{ {
break; return true;
} }
} }
return false;
if( !isValid )
{
return false;
}
} }
return true; return true;
@@ -172,7 +172,7 @@ public class SlotRestrictedInput extends AppEngSlot
for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() ) for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() )
{ {
if( Platform.itemComparisons().isSameItem( optional, i ) ) if( Platform.itemComparisons().isSameItem( i, optional ) )
{ {
return true; return true;
} }
+2
View File
@@ -189,6 +189,8 @@ public final class AppEng
AppEng.proxy.preinit(); AppEng.proxy.preinit();
} }
IntegrationRegistry.INSTANCE.preInit();
if( versionCheckerConfig.isVersionCheckingEnabled() ) if( versionCheckerConfig.isVersionCheckingEnabled() )
{ {
final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig ); final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig );
+1 -1
View File
@@ -59,7 +59,7 @@ public class ApiGrid implements IGridHelper
Preconditions.checkNotNull( a ); Preconditions.checkNotNull( a );
Preconditions.checkNotNull( b ); Preconditions.checkNotNull( b );
return new GridConnection( a, b, AEPartLocation.INTERNAL ); return GridConnection.create( a, b, AEPartLocation.INTERNAL );
} }
} }
@@ -160,6 +160,12 @@ public class ApiStorage implements IStorageHelper
private static final class FluidStorageChannel implements IFluidStorageChannel private static final class FluidStorageChannel implements IFluidStorageChannel
{ {
@Override
public int transferFactor()
{
return 1000;
}
@Override @Override
public IItemList<IAEFluidStack> createList() public IItemList<IAEFluidStack> createList()
{ {
@@ -195,7 +201,7 @@ public class ApiStorage implements IStorageHelper
Preconditions.checkNotNull( request ); Preconditions.checkNotNull( request );
Preconditions.checkNotNull( src ); Preconditions.checkNotNull( src );
return null; return Platform.poweredExtraction( energy, cell, request, src );
} }
@Override @Override
@@ -206,7 +212,7 @@ public class ApiStorage implements IStorageHelper
Preconditions.checkNotNull( input ); Preconditions.checkNotNull( input );
Preconditions.checkNotNull( src ); Preconditions.checkNotNull( src );
return input; return Platform.poweredInsert( energy, cell, input, src );
} }
} }
@@ -106,10 +106,12 @@ import appeng.core.features.BlockDefinition;
import appeng.core.features.registries.PartModels; import appeng.core.features.registries.PartModels;
import appeng.debug.BlockChunkloader; import appeng.debug.BlockChunkloader;
import appeng.debug.BlockCubeGenerator; import appeng.debug.BlockCubeGenerator;
import appeng.debug.BlockEnergyGenerator;
import appeng.debug.BlockItemGen; import appeng.debug.BlockItemGen;
import appeng.debug.BlockPhantomNode; import appeng.debug.BlockPhantomNode;
import appeng.debug.TileChunkLoader; import appeng.debug.TileChunkLoader;
import appeng.debug.TileCubeGenerator; import appeng.debug.TileCubeGenerator;
import appeng.debug.TileEnergyGenerator;
import appeng.debug.TileItemGen; import appeng.debug.TileItemGen;
import appeng.debug.TilePhantomNode; import appeng.debug.TilePhantomNode;
import appeng.decorative.slab.BlockSlabCommon; import appeng.decorative.slab.BlockSlabCommon;
@@ -236,6 +238,7 @@ public final class ApiBlocks implements IBlocks
private final IBlockDefinition chunkLoader; private final IBlockDefinition chunkLoader;
private final IBlockDefinition phantomNode; private final IBlockDefinition phantomNode;
private final IBlockDefinition cubeGenerator; private final IBlockDefinition cubeGenerator;
private final IBlockDefinition energyGenerator;
public ApiBlocks( FeatureFactory registry, PartModels partModels ) public ApiBlocks( FeatureFactory registry, PartModels partModels )
{ {
@@ -526,6 +529,11 @@ public final class ApiBlocks implements IBlocks
.tileEntity( new TileEntityDefinition( TileCubeGenerator.class ) ) .tileEntity( new TileEntityDefinition( TileCubeGenerator.class ) )
.useCustomItemModel() .useCustomItemModel()
.build(); .build();
this.energyGenerator = registry.block( "debug_energy_gen", BlockEnergyGenerator::new )
.features( AEFeature.UNSUPPORTED_DEVELOPER_TOOLS, AEFeature.CREATIVE )
.tileEntity( new TileEntityDefinition( TileEnergyGenerator.class ) )
.useCustomItemModel()
.build();
} }
private static IBlockDefinition makeSlab( String slabId, String doubleSlabId, FeatureFactory registry, IBlockDefinition blockDef ) private static IBlockDefinition makeSlab( String slabId, String doubleSlabId, FeatureFactory registry, IBlockDefinition blockDef )
@@ -1014,4 +1022,9 @@ public final class ApiBlocks implements IBlocks
{ {
return this.cubeGenerator; return this.cubeGenerator;
} }
public IBlockDefinition energyGenerator()
{
return energyGenerator;
}
} }
@@ -21,6 +21,7 @@ package appeng.core.features.registries;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -30,6 +31,8 @@ import net.minecraft.init.Items;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.oredict.OreDictionary; import net.minecraftforge.oredict.OreDictionary;
import appeng.api.AEApi; import appeng.api.AEApi;
@@ -49,6 +52,7 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
private final Map<ItemStack, TunnelType> tunnels = new HashMap<>( INITIAL_CAPACITY ); private final Map<ItemStack, TunnelType> tunnels = new HashMap<>( INITIAL_CAPACITY );
private final Map<String, TunnelType> modIdTunnels = new HashMap<>( INITIAL_CAPACITY ); private final Map<String, TunnelType> modIdTunnels = new HashMap<>( INITIAL_CAPACITY );
private final Map<Capability<?>, TunnelType> capTunnels = new HashMap<>( INITIAL_CAPACITY );
public void configure() public void configure()
{ {
@@ -159,6 +163,12 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
this.addNewAttunement( parts.cableDenseSmart().stack( c, 1 ), TunnelType.ME ); this.addNewAttunement( parts.cableDenseSmart().stack( c, 1 ), TunnelType.ME );
} }
/**
* attune based caps
*/
this.addNewAttunement( Capabilities.FORGE_ENERGY, TunnelType.FE_POWER );
this.addNewAttunement( CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, TunnelType.FLUID );
/** /**
* attune based on the ItemStack's modId * attune based on the ItemStack's modId
*/ */
@@ -186,6 +196,16 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
this.modIdTunnels.put( modId, type ); this.modIdTunnels.put( modId, type );
} }
@Override
public void addNewAttunement( @Nonnull final Capability<?> cap, @Nullable final TunnelType type )
{
if( type == null || cap == null )
{
return;
}
this.capTunnels.put( cap, type );
}
@Override @Override
public void addNewAttunement( @Nonnull final ItemStack trigger, @Nullable final TunnelType type ) public void addNewAttunement( @Nonnull final ItemStack trigger, @Nullable final TunnelType type )
{ {
@@ -203,39 +223,40 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
{ {
if( !trigger.isEmpty() ) if( !trigger.isEmpty() )
{ {
// if( FluidRegistry.isContainer( trigger ) ) // First match exact items
// { for( final Entry<ItemStack, TunnelType> entry : this.tunnels.entrySet() )
// return TunnelType.FLUID;
// }
for( final ItemStack is : this.tunnels.keySet() )
{ {
final ItemStack is = entry.getKey();
if( is.getItem() == trigger.getItem() && is.getItemDamage() == OreDictionary.WILDCARD_VALUE ) if( is.getItem() == trigger.getItem() && is.getItemDamage() == OreDictionary.WILDCARD_VALUE )
{ {
return this.tunnels.get( is ); return entry.getValue();
} }
if( ItemStack.areItemsEqual( is, trigger ) ) if( ItemStack.areItemsEqual( is, trigger ) )
{ {
return this.tunnels.get( is ); return entry.getValue();
} }
} }
// Try by ModId next // Next, check if the Item you're holding supports any registered capability
for( final String modId : this.modIdTunnels.keySet() )
{
if( trigger.getItem().getRegistryName() != null && trigger.getItem().getRegistryName().getResourceDomain().equals( modId ) )
{
return this.modIdTunnels.get( modId );
}
}
// Next, check if the Item you're holding supports Forge Energy
for( EnumFacing face : EnumFacing.VALUES ) for( EnumFacing face : EnumFacing.VALUES )
{ {
if( trigger.hasCapability( Capabilities.FORGE_ENERGY, face ) ) for( Entry<Capability<?>, TunnelType> entry : this.capTunnels.entrySet() )
{ {
return TunnelType.FE_POWER; if( trigger.hasCapability( entry.getKey(), face ) )
{
return entry.getValue();
}
}
}
// Use the mod id as last option.
for( final Entry<String, TunnelType> entry : this.modIdTunnels.entrySet() )
{
if( trigger.getItem().getRegistryName() != null && trigger.getItem().getRegistryName().getResourceDomain().equals( entry.getKey() ) )
{
return entry.getValue();
} }
} }
} }
@@ -118,7 +118,7 @@ public enum GuiText
RequiredPower, RequiredPower,
Efficiency, Efficiency,
SCSSize, SCSSize,
SCSSInvalid, SCSInvalid,
InWorldCrafting, InWorldCrafting,
inWorldFluix, inWorldFluix,
@@ -47,7 +47,7 @@ public enum TickRates
ItemTunnel( 5, 60 ), ItemTunnel( 5, 60 ),
LightTunnel( 5, 120 ), LightTunnel( 5, 60 ),
OpenComputersTunnel( 1, 5 ), OpenComputersTunnel( 1, 5 ),
@@ -41,11 +41,11 @@ import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion; import appeng.core.sync.packets.PacketMockExplosion;
import appeng.core.sync.packets.PacketPaintedEntity; import appeng.core.sync.packets.PacketPaintedEntity;
import appeng.core.sync.packets.PacketPartPlacement; import appeng.core.sync.packets.PacketPartPlacement;
import appeng.core.sync.packets.PacketPartialItem;
import appeng.core.sync.packets.PacketPatternSlot; import appeng.core.sync.packets.PacketPatternSlot;
import appeng.core.sync.packets.PacketProgressBar; import appeng.core.sync.packets.PacketProgressBar;
import appeng.core.sync.packets.PacketSwapSlots; import appeng.core.sync.packets.PacketSwapSlots;
import appeng.core.sync.packets.PacketSwitchGuis; import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketTargetItemStack;
import appeng.core.sync.packets.PacketTransitionEffect; import appeng.core.sync.packets.PacketTransitionEffect;
import appeng.core.sync.packets.PacketValueConfig; import appeng.core.sync.packets.PacketValueConfig;
@@ -90,7 +90,7 @@ public class AppEngPacketHandlerBase
PACKET_RECIPE_JEI( PacketJEIRecipe.class ), PACKET_RECIPE_JEI( PacketJEIRecipe.class ),
PACKET_PARTIAL_ITEM( PacketPartialItem.class ), PACKET_TARGET_ITEM( PacketTargetItemStack.class ),
PACKET_CRAFTING_REQUEST( PacketCraftRequest.class ), PACKET_CRAFTING_REQUEST( PacketCraftRequest.class ),
@@ -41,6 +41,7 @@ import appeng.api.config.Actionable;
import appeng.api.config.SecurityPermissions; import appeng.api.config.SecurityPermissions;
import appeng.api.networking.IGrid; import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid; import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.security.ISecurityGrid; import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.storage.IStorageGrid; import appeng.api.networking.storage.IStorageGrid;
@@ -132,6 +133,7 @@ public class PacketJEIRecipe extends AppEngPacket
final IStorageGrid inv = grid.getCache( IStorageGrid.class ); final IStorageGrid inv = grid.getCache( IStorageGrid.class );
final IEnergyGrid energy = grid.getCache( IEnergyGrid.class ); final IEnergyGrid energy = grid.getCache( IEnergyGrid.class );
final ISecurityGrid security = grid.getCache( ISecurityGrid.class ); final ISecurityGrid security = grid.getCache( ISecurityGrid.class );
final ICraftingGrid crafting = grid.getCache( ICraftingGrid.class );
final IItemHandler craftMatrix = cct.getInventoryByName( "crafting" ); final IItemHandler craftMatrix = cct.getInventoryByName( "crafting" );
final IItemHandler playerInventory = cct.getInventoryByName( "player" ); final IItemHandler playerInventory = cct.getInventoryByName( "player" );
@@ -179,13 +181,23 @@ public class PacketJEIRecipe extends AppEngPacket
{ {
request.setStackSize( 1 ); request.setStackSize( 1 );
IAEItemStack out; IAEItemStack out;
if( cct.useRealItems() ) if( cct.useRealItems() )
{ {
out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() ); out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() );
} }
else 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 ) if( out != null )
@@ -25,35 +25,56 @@ import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import appeng.container.AEBaseContainer; import appeng.container.AEBaseContainer;
import appeng.core.AELog;
import appeng.core.sync.AppEngPacket; import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo; import appeng.core.sync.network.INetworkInfo;
import appeng.util.item.AEItemStack;
public class PacketPartialItem extends AppEngPacket public class PacketTargetItemStack extends AppEngPacket
{ {
private AEItemStack stack;
private final short pageNum;
private final byte[] data;
// automatic. // automatic.
public PacketPartialItem( final ByteBuf stream ) public PacketTargetItemStack( final ByteBuf stream )
{ {
this.pageNum = stream.readShort(); try
stream.readBytes( this.data = new byte[stream.readableBytes()] ); {
if( stream.readableBytes() > 0 )
{
this.stack = AEItemStack.fromPacket( stream );
}
else
{
this.stack = null;
}
}
catch( Exception ex )
{
AELog.debug( ex );
this.stack = null;
}
} }
// api // api
public PacketPartialItem( final int page, final int maxPages, final byte[] buf ) public PacketTargetItemStack( AEItemStack stack )
{ {
this.stack = stack;
final ByteBuf data = Unpooled.buffer(); final ByteBuf data = Unpooled.buffer();
this.pageNum = (short) ( page | ( maxPages << 8 ) );
this.data = buf;
data.writeInt( this.getPacketID() ); data.writeInt( this.getPacketID() );
data.writeShort( this.pageNum ); if( stack != null )
data.writeBytes( buf ); {
try
{
stack.writeToPacket( data );
}
catch( Exception ex )
{
AELog.debug( ex );
}
}
this.configureWrite( data ); this.configureWrite( data );
} }
@@ -62,23 +83,8 @@ public class PacketPartialItem extends AppEngPacket
{ {
if( player.openContainer instanceof AEBaseContainer ) 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 ) if( this.howManyEmitted > 0 )
{ {
final IAEItemStack i = this.what.copy(); final IAEItemStack i = this.what.copy().reset();
i.setStackSize( this.howManyEmitted ); i.setStackSize( this.howManyEmitted );
craftingCPUCluster.addEmitable( i ); craftingCPUCluster.addEmitable( i );
} }
@@ -0,0 +1,35 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.debug;
import net.minecraft.block.material.Material;
import appeng.block.AEBaseTileBlock;
public class BlockEnergyGenerator extends AEBaseTileBlock
{
public BlockEnergyGenerator()
{
super( Material.IRON );
}
}
@@ -0,0 +1,139 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, 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.debug;
import java.util.EnumSet;
import javax.annotation.Nullable;
import com.google.common.math.IntMath;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import appeng.tile.AEBaseTile;
public class TileEnergyGenerator extends AEBaseTile implements ITickable, IEnergyStorage
{
/**
* The base energy injected each tick.
* Adjacent TileEnergyGenerators will increase it to pow(base, #generators).
*/
private static final int BASE_ENERGY = 8;
@Override
public void update()
{
int tier = 1;
final EnumSet<EnumFacing> validEnergyReceivers = EnumSet.noneOf( EnumFacing.class );
for( EnumFacing facing : EnumFacing.values() )
{
final TileEntity te = this.getWorld().getTileEntity( this.getPos().offset( facing ) );
if( te instanceof TileEnergyGenerator )
{
tier++;
}
if( te != null && te.hasCapability( CapabilityEnergy.ENERGY, facing.getOpposite() ) )
{
validEnergyReceivers.add( facing );
}
}
final int energyToInsert = IntMath.pow( BASE_ENERGY, tier );
for( EnumFacing facing : validEnergyReceivers )
{
final TileEntity te = this.getWorld().getTileEntity( this.getPos().offset( facing ) );
final IEnergyStorage cap = te.getCapability( CapabilityEnergy.ENERGY, facing.getOpposite() );
if( cap.canReceive() )
{
cap.receiveEnergy( energyToInsert, false );
}
}
}
@Override
public boolean hasCapability( Capability<?> capability, @Nullable EnumFacing facing )
{
if( capability == CapabilityEnergy.ENERGY )
{
return true;
}
return super.hasCapability( capability, facing );
}
@Override
@Nullable
public <T> T getCapability( Capability<T> capability, @Nullable EnumFacing facing )
{
if( capability == CapabilityEnergy.ENERGY )
{
return (T) this;
}
return super.getCapability( capability, facing );
}
@Override
public int receiveEnergy( int maxReceive, boolean simulate )
{
return 0;
}
@Override
public int extractEnergy( int maxExtract, boolean simulate )
{
return maxExtract;
}
@Override
public int getEnergyStored()
{
return Integer.MAX_VALUE;
}
@Override
public int getMaxEnergyStored()
{
return Integer.MAX_VALUE;
}
@Override
public boolean canExtract()
{
return true;
}
@Override
public boolean canReceive()
{
return false;
}
}
@@ -19,6 +19,8 @@
package appeng.entity; package appeng.entity;
import java.util.List;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@@ -136,19 +138,20 @@ public final class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntit
return; return;
} }
for( final Object e : this.world.getEntitiesWithinAABBExcludingEntity( this, final Explosion ex = new Explosion( this.world, this, this.posX, this.posY, this.posZ, 0.2f, false, false );
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 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 ) e.attackEntityFrom( DamageSource.causeExplosionDamage( ex ), 6 );
{
( (Entity) e ).attackEntityFrom( DamageSource.causeExplosionDamage( (Explosion) null ), 6 );
}
} }
if( AEConfig.instance().isFeatureEnabled( AEFeature.TINY_TNT_BLOCK_DAMAGE ) ) if( AEConfig.instance().isFeatureEnabled( AEFeature.TINY_TNT_BLOCK_DAMAGE ) )
{ {
this.posY -= 0.25; 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++ ) 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 BlockPos point = new BlockPos( x, y, z );
final IBlockState state = this.world.getBlockState( point ); final IBlockState state = this.world.getBlockState( point );
final Block block = state.getBlock(); final Block block = state.getBlock();
if( block != null && !block.isAir( state, this.world, point ) ) 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 ) ) ); 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 ) ); this.modules.add( new IntegrationNode( type.dspName, type.modID, type ) );
} }
public void init() public void preInit()
{ {
for( final IntegrationNode node : this.modules ) for( final IntegrationNode node : this.modules )
{ {
node.call( IntegrationStage.PRE_INIT ); node.call( IntegrationStage.PRE_INIT );
} }
}
public void init()
{
for( final IntegrationNode node : this.modules ) for( final IntegrationNode node : this.modules )
{ {
node.call( IntegrationStage.INIT ); node.call( IntegrationStage.INIT );
@@ -19,6 +19,7 @@
package appeng.integration; package appeng.integration;
import appeng.integration.modules.crafttweaker.CTModule;
import appeng.integration.modules.ic2.IC2Module; import appeng.integration.modules.ic2.IC2Module;
import appeng.integration.modules.jei.JEIModule; import appeng.integration.modules.jei.JEIModule;
import appeng.integration.modules.theoneprobe.TheOneProbeModule; 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 IntegrationSide side;
public final String dspName; 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 @Override
public void saveChanges() public void saveChanges()
{ {
this.inv.markDirty( -1 ); this.inv.writeToNBT( Platform.openNbtData( this.is ), "inv" );
} }
@Override @Override
public void onChangeInventory( IItemHandler inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack ) public void onChangeInventory( IItemHandler inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack )
{ {
this.inv.writeToNBT( Platform.openNbtData( this.is ), "inv" );
} }
@Override @Override
@@ -318,7 +318,7 @@ public final class ItemMaterial extends AEBaseItem implements IStorageComponent,
} }
final InventoryAdaptor ad = new AdaptorItemHandler( upgrades ); final InventoryAdaptor ad = new AdaptorItemHandler( upgrades );
player.inventory.setInventorySlotContents( player.inventory.currentItem, ad.addItems( player.getHeldItem( hand ) ) ); player.setHeldItem( hand, ad.addItems( player.getHeldItem( hand ) ) );
return EnumActionResult.SUCCESS; return EnumActionResult.SUCCESS;
} }
} }
@@ -211,6 +211,7 @@ public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternIt
public ItemStack getOutput( final ItemStack item ) public ItemStack getOutput( final ItemStack item )
{ {
ItemStack out = SIMPLE_CACHE.get( item ); ItemStack out = SIMPLE_CACHE.get( item );
if( out != null ) if( out != null )
{ {
return out; return out;
@@ -224,12 +225,9 @@ public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternIt
final ICraftingPatternDetails details = this.getPatternForItem( item, w ); final ICraftingPatternDetails details = this.getPatternForItem( item, w );
if( details == null ) out = details != null ? details.getOutputs()[0].createItemStack() : ItemStack.EMPTY;
{
return ItemStack.EMPTY;
}
SIMPLE_CACHE.put( item, out = details.getCondensedOutputs()[0].createItemStack() ); SIMPLE_CACHE.put( item, out );
return out; return out;
} }
} }
@@ -219,13 +219,11 @@ public class ToolNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench,
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos ) public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{ {
user.swingArm( user.getActiveHand() );
} }
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity ) public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{ {
user.swingArm( user.getActiveHand() );
} }
// IToolHammer - end // IToolHammer - end
@@ -277,7 +277,7 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe
final IAEItemStack firstItem = itemList.getFirstItem(); final IAEItemStack firstItem = itemList.getFirstItem();
if( firstItem != null ) if( firstItem != null )
{ {
newColor = firstItem.createItemStack(); newColor = firstItem.asItemStackRepresentation();
} }
} }
else else
@@ -324,7 +324,7 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe
list.addFirst( list.removeLast() ); list.addFirst( list.removeLast() );
} }
return list.get( 0 ).createItemStack(); return list.get( 0 ).asItemStackRepresentation();
} }
} }
@@ -85,21 +85,10 @@ class PoweredItemCapabilities implements ICapabilityProvider, IEnergyStorage
@Override @Override
public int receiveEnergy( int maxReceive, boolean simulate ) public int receiveEnergy( int maxReceive, boolean simulate )
{ {
if( simulate ) final double convertedOffer = PowerUnits.RF.convertTo( PowerUnits.AE, maxReceive );
{ final double overflow = this.item.injectAEPower( this.is, convertedOffer, simulate ? Actionable.SIMULATE : Actionable.MODULATE );
final int required = (int) PowerUnits.AE.convertTo( PowerUnits.RF, this.item.getAEMaxPower( this.is ) - this.item.getAECurrentPower( this.is ) );
if( maxReceive < required ) return maxReceive - (int) PowerUnits.AE.convertTo( PowerUnits.RF, overflow );
{
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 );
}
} }
@Override @Override
@@ -103,14 +103,13 @@ public class ToolQuartzWrench extends AEBaseItem implements IAEWrench, IToolHamm
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos ) public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{ {
user.swingArm( user.getActiveHand() );
} }
@Override @Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity ) public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{ {
user.swingArm( user.getActiveHand() );
} }
// IToolHammer - end // IToolHammer - end
// TODO: BC Wrench Integration // TODO: BC Wrench Integration
+80 -72
View File
@@ -54,80 +54,11 @@ public class GridConnection implements IGridConnection, IPathItem
private AEPartLocation fromAtoB; private AEPartLocation fromAtoB;
private GridNode sideB; 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 )
{ {
this.sideA = aNode;
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.fromAtoB = fromAtoB; this.fromAtoB = fromAtoB;
this.sideB = b; this.sideB = bNode;
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 );
} }
private boolean isNetworkABetter( final GridNode a, final GridNode b ) private boolean isNetworkABetter( final GridNode a, final GridNode b )
@@ -291,4 +222,81 @@ public class GridConnection implements IGridConnection, IPathItem
{ {
this.visitorIterationNumber = visitorIterationNumber; 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 net.minecraft.world.World;
import appeng.api.exceptions.FailedConnectionException; import appeng.api.exceptions.FailedConnectionException;
import appeng.api.exceptions.SecurityConnectionException;
import appeng.api.networking.GridFlags; import appeng.api.networking.GridFlags;
import appeng.api.networking.GridNotification; import appeng.api.networking.GridNotification;
import appeng.api.networking.IGrid; import appeng.api.networking.IGrid;
@@ -50,6 +51,7 @@ import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord; import appeng.api.util.DimensionalCoord;
import appeng.api.util.IReadOnlyCollection; import appeng.api.util.IReadOnlyCollection;
import appeng.core.AELog;
import appeng.core.worlddata.WorldData; import appeng.core.worlddata.WorldData;
import appeng.hooks.TickHandler; import appeng.hooks.TickHandler;
import appeng.me.pathfinding.IPathItem; import appeng.me.pathfinding.IPathItem;
@@ -216,7 +218,7 @@ public class GridNode implements IGridNode, IPathItem
this.compressedData |= ( 1 << ( dir.ordinal() + 8 ) ); this.compressedData |= ( 1 << ( dir.ordinal() + 8 ) );
} }
this.FindConnections(); this.findConnections();
this.getInternalGrid(); this.getInternalGrid();
} }
@@ -393,7 +395,7 @@ public class GridNode implements IGridNode, IPathItem
return this.usedChannels; return this.usedChannels;
} }
private void FindConnections() private void findConnections()
{ {
if( !this.gridProxy.isWorldAccessible() ) if( !this.gridProxy.isWorldAccessible() )
{ {
@@ -455,11 +457,18 @@ public class GridNode implements IGridNode, IPathItem
// construct a new connection between these two nodes. // construct a new connection between these two nodes.
try 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 ) catch( final FailedConnectionException e )
{ {
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) ); AELog.debug( e );
return; return;
} }
@@ -482,11 +491,19 @@ public class GridNode implements IGridNode, IPathItem
// construct a new connection between these two nodes. // construct a new connection between these two nodes.
try 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 ) catch( final FailedConnectionException e )
{ {
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) ); AELog.debug( e );
return; return;
} }
+2 -1
View File
@@ -489,7 +489,8 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( ais.getItem() == whatToCraft.getItem() && ( !ais.getItem().getHasSubtypes() || ais.getItemDamage() == whatToCraft.getItemDamage() ) ) if( ais.getItem() == whatToCraft.getItem() && ( !ais.getItem().getHasSubtypes() || ais.getItemDamage() == whatToCraft.getItemDamage() ) )
{ {
// TODO: check if OK // TODO: check if OK
if( details.isValidItemForSlot( slotIndex, ais.createItemStack(), world ) ) // TODO: this is slightly hacky, but fine as long as we only deal with itemstacks
if( details.isValidItemForSlot( slotIndex, ais.asItemStackRepresentation(), world ) )
{ {
return this.craftableItems.get( ais ); return this.craftableItems.get( ais );
} }
+22 -18
View File
@@ -311,35 +311,32 @@ public class EnergyGridCache implements IEnergyGrid
final double newPower = node.extractAEPower( req, mode, PowerMultiplier.ONE ); final double newPower = node.extractAEPower( req, mode, PowerMultiplier.ONE );
extractedPower += newPower; extractedPower += newPower;
if( newPower < req ) if( newPower < req && mode == Actionable.MODULATE )
{ {
it.remove(); it.remove();
} }
} }
// got more then we wanted? final double result = Math.min( extractedPower, amt );
if( extractedPower > amt )
{
this.localStorage.addCurrentAEPower( extractedPower - amt );
this.globalAvailablePower -= amt;
this.tickDrainPerTick += amt; if( mode == Actionable.MODULATE )
return amt; {
if( extractedPower > amt )
{
this.localStorage.addCurrentAEPower( extractedPower - amt );
}
this.globalAvailablePower -= result;
this.tickDrainPerTick += result;
} }
// go less or the correct amount? return result;
this.globalAvailablePower -= extractedPower;
this.tickDrainPerTick += extractedPower;
return extractedPower;
} }
@Override @Override
public double injectProviderPower( double amt, final Actionable mode ) public double injectProviderPower( double amt, final Actionable mode )
{ {
if( mode == Actionable.MODULATE ) final double originalAmount = amt;
{
this.tickInjectionPerTick += amt;
}
final Iterator<IAEPowerStorage> it = this.requesters.iterator(); final Iterator<IAEPowerStorage> it = this.requesters.iterator();
@@ -348,13 +345,20 @@ public class EnergyGridCache implements IEnergyGrid
final IAEPowerStorage node = it.next(); final IAEPowerStorage node = it.next();
amt = node.injectAEPower( amt, mode ); amt = node.injectAEPower( amt, mode );
if( amt > 0 ) if( amt > 0 && mode == Actionable.MODULATE )
{ {
it.remove(); it.remove();
} }
} }
return Math.max( 0.0, amt ); final double overflow = Math.max( 0.0, amt );
if( mode == Actionable.MODULATE )
{
this.tickInjectionPerTick += originalAmount - overflow;
}
return overflow;
} }
@Override @Override
@@ -440,7 +440,6 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
this.lastTime = 0; this.lastTime = 0;
this.elapsedTime = 0; this.elapsedTime = 0;
this.isComplete = true; this.isComplete = true;
} }
private void updateCPU() private void updateCPU()
@@ -38,6 +38,7 @@ import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode; import appeng.api.networking.IGridNode;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
import appeng.api.util.WorldCoord; import appeng.api.util.WorldCoord;
import appeng.core.AELog;
import appeng.me.cache.helpers.ConnectionWrapper; import appeng.me.cache.helpers.ConnectionWrapper;
import appeng.me.cluster.IAECluster; import appeng.me.cluster.IAECluster;
import appeng.tile.qnb.TileQuantumBridge; import appeng.tile.qnb.TileQuantumBridge;
@@ -161,6 +162,7 @@ public class QuantumCluster implements ILocatable, IAECluster
catch( final FailedConnectionException e ) catch( final FailedConnectionException e )
{ {
// :( // :(
AELog.debug( e );
} }
} }
else else
@@ -241,11 +241,11 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{ {
try try
{ {
new GridConnection( cn, sn, AEPartLocation.INTERNAL ); GridConnection.create( cn, sn, AEPartLocation.INTERNAL );
} }
catch( final FailedConnectionException e ) catch( final FailedConnectionException e )
{ {
// ekk! AELog.debug( e );
bp.removeFromWorld(); bp.removeFromWorld();
this.setCenter( null ); this.setCenter( null );
@@ -292,11 +292,11 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{ {
try try
{ {
new GridConnection( cn, sn, AEPartLocation.INTERNAL ); GridConnection.create( cn, sn, AEPartLocation.INTERNAL );
} }
catch( final FailedConnectionException e ) catch( final FailedConnectionException e )
{ {
// ekk! AELog.debug( e );
bp.removeFromWorld(); bp.removeFromWorld();
this.setSide( side, null ); this.setSide( side, null );
@@ -637,6 +637,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
catch( final FailedConnectionException e ) catch( final FailedConnectionException e )
{ {
// ekk // ekk
AELog.debug( e );
} }
} }
} }
@@ -1087,7 +1088,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
this.getFacadeContainer().readFromNBT( data ); this.getFacadeContainer().readFromNBT( data );
} }
public List getDrops( final List drops ) public List<ItemStack> getDrops( final List<ItemStack> drops )
{ {
for( final AEPartLocation s : AEPartLocation.values() ) for( final AEPartLocation s : AEPartLocation.values() )
{ {
@@ -1111,7 +1112,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
return drops; return drops;
} }
public List getNoDrops( final List drops ) public List<ItemStack> getNoDrops( final List<ItemStack> drops )
{ {
for( final AEPartLocation s : AEPartLocation.values() ) for( final AEPartLocation s : AEPartLocation.values() )
{ {
@@ -1150,12 +1151,15 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
@Override @Override
public CableBusRenderState getRenderState() 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 ) 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.setCableColor( cable.getCableColor() );
renderState.setCableType( cable.getCableConnectionType() ); renderState.setCableType( cable.getCableConnectionType() );
renderState.setCoreType( CableCoreType.fromCableType( 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 // 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 // Dense cables however also respect the adjacent cable-type since their outgoing connection
// point would look too big for other cable types // point would look too big for other cable types
BlockPos adjacentPos = this.getTile().getPos().offset( facing ); final BlockPos adjacentPos = this.getTile().getPos().offset( facing );
TileEntity adjacentTe = this.getTile().getWorld().getTileEntity( adjacentPos ); final TileEntity adjacentTe = this.getTile().getWorld().getTileEntity( adjacentPos );
if( adjacentTe instanceof IGridHost ) if( adjacentTe instanceof IGridHost )
{ {
if( !( adjacentTe instanceof IPartHost ) || cable.getCableConnectionType() == AECableType.DENSE_SMART || cable if( !( adjacentTe instanceof IPartHost ) || isDense )
.getCableConnectionType() == AECableType.DENSE_COVERED )
{ {
IGridHost gridHost = (IGridHost) adjacentTe; IGridHost gridHost = (IGridHost) adjacentTe;
connectionType = gridHost.getCableConnectionType( AEPartLocation.fromFacing( facing.getOpposite() ) ); connectionType = gridHost.getCableConnectionType( AEPartLocation.fromFacing( facing.getOpposite() ) );
@@ -1201,7 +1205,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// adjacent tile requires it // adjacent tile requires it
for( EnumFacing facing : EnumFacing.values() ) for( EnumFacing facing : EnumFacing.values() )
{ {
int channels = cable.getChannelsOnSide( facing ); int channels = isSmart ? cable.getChannelsOnSide( facing ) : 0;
renderState.getChannelsOnSide().put( facing, channels ); renderState.getChannelsOnSide().put( facing, channels );
} }
} }
@@ -1209,14 +1213,14 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// Determine attachments and facades // Determine attachments and facades
for( EnumFacing facing : EnumFacing.values() ) for( EnumFacing facing : EnumFacing.values() )
{ {
final FacadeRenderState facadeState = this.getFacadeRenderState( facing );
FacadeRenderState facadeState = this.getFacadeRenderState( facing );
if( facadeState != null ) if( facadeState != null )
{ {
renderState.getFacades().put( facing, facadeState ); renderState.getFacades().put( facing, facadeState );
} }
IPart part = this.getPart( facing ); final IPart part = this.getPart( facing );
if( part == null ) 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 // This will add the part's bounding boxes to the render state, which is required for facades
AEPartLocation loc = AEPartLocation.fromFacing( facing ); final AEPartLocation loc = AEPartLocation.fromFacing( facing );
IPartCollisionHelper bch = new BusCollisionHelper( renderState.getBoundingBoxes(), loc, null, true ); final IPartCollisionHelper bch = new BusCollisionHelper( renderState.getBoundingBoxes(), loc, null, true );
part.getBoxes( bch ); part.getBoxes( bch );
if( part instanceof IGridHost ) if( part instanceof IGridHost )
{ {
// Some attachments want a thicker cable than glass, account for that // Some attachments want a thicker cable than glass, account for that
IGridHost gridHost = (IGridHost) part; final IGridHost gridHost = (IGridHost) part;
AECableType desiredType = gridHost.getCableConnectionType( AEPartLocation.INTERNAL ); final AECableType desiredType = gridHost.getCableConnectionType( AEPartLocation.INTERNAL );
if( renderState.getCoreType() == CableCoreType.GLASS && ( desiredType == AECableType.SMART || desiredType == AECableType.COVERED ) ) if( renderState.getCoreType() == CableCoreType.GLASS && ( desiredType == AECableType.SMART || desiredType == AECableType.COVERED ) )
{ {
renderState.setCoreType( CableCoreType.COVERED ); renderState.setCoreType( CableCoreType.COVERED );
@@ -1254,14 +1260,16 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
private FacadeRenderState getFacadeRenderState( EnumFacing side ) private FacadeRenderState getFacadeRenderState( EnumFacing side )
{ {
// Store the "masqueraded" itemstack for the given side, if there is a facade // 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 ) if( facade != null )
{ {
ItemStack textureItem = facade.getTextureItem(); final ItemStack textureItem = facade.getTextureItem();
IBlockState blockState = facade.getBlockState(); final IBlockState blockState = facade.getBlockState();
if( blockState != null && textureItem != null ) if( blockState != null && textureItem != null )
{ {
EnumSet<EnumFacing> openFaces = this.calculateFaceOpenFaces( side ); final EnumSet<EnumFacing> openFaces = this.calculateFaceOpenFaces( side );
return new FacadeRenderState( blockState, openFaces, textureItem ); 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 EnumSet<EnumFacing> out = EnumSet.of( side, side.getOpposite() );
final IFacadePart facade = this.getFacade( side.ordinal() ); 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() ) for( final EnumFacing it : EnumFacing.values() )
{ {
if( !out.contains( it ) && this.hasAlphaDiff( blockAccess.getTileEntity( pos.offset( it ) ), side, facade ) ) 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.init.Blocks;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemBlockSpecial;
import net.minecraft.item.ItemFirework; import net.minecraft.item.ItemFirework;
import net.minecraft.item.ItemSkull; import net.minecraft.item.ItemSkull;
import net.minecraft.item.ItemStack; 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( 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 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( .getItemFromBlock( Blocks.REEDS ) ) )
Blocks.REEDS ) ) )
{ {
final EntityPlayer player = Platform.getPlayer( (WorldServer) w ); final EntityPlayer player = Platform.getPlayer( (WorldServer) w );
Platform.configurePlayer( player, side, this.getTile() ); Platform.configurePlayer( player, side, this.getTile() );
EnumHand hand = player.getActiveHand(); EnumHand hand = player.getActiveHand();
player.setHeldItem( hand, is ); 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(); maxStorage = is.getCount();
worked = true; worked = true;
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
@@ -29,7 +29,6 @@ import net.minecraft.util.math.Vec3d;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.RedstoneMode; import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.Upgrades; import appeng.api.config.Upgrades;
@@ -41,7 +40,6 @@ import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest; import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPartCollisionHelper; import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartModel; import appeng.api.parts.IPartModel;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitor;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; 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" ) ); 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 final IActionSource source;
private IMEInventory<IAEItemStack> destination = null; private int itemsToSend; // used in tickingRequest
private IAEItemStack lastItemChecked = null;
private int itemToSend; // used in tickingRequest
private boolean worked; // used in tickingRequest private boolean worked; // used in tickingRequest
@Reflected @Reflected
@@ -95,14 +91,24 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
return false; return false;
} }
final IAEItemStack out = this.destination.injectItems( try
this.lastItemChecked = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( stack ), Actionable.SIMULATE,
this.source );
if( out == null )
{ {
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 @Override
@@ -165,9 +171,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
{ {
try try
{ {
this.itemToSend = this.calculateItemsToSend(); this.itemsToSend = this.calculateItemsToSend();
this.itemToSend = Math.min( this.itemToSend,
(int) ( 0.01 + this.getProxy().getEnergy().extractAEPower( this.itemToSend, Actionable.SIMULATE, PowerMultiplier.CONFIG ) ) );
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage().getInventory( final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage().getInventory(
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); 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++ ) for( int x = 0; x < this.availableSlots(); x++ )
{ {
final IAEItemStack ais = this.getConfig().getAEStackInSlot( x ); final IAEItemStack ais = this.getConfig().getAEStackInSlot( x );
if( ais != null && this.itemToSend > 0 ) if( ais != null && itemsToSend > 0 )
{ {
Configured = true; Configured = true;
while( this.itemToSend > 0 ) while( itemsToSend > 0 )
{ {
if( this.importStuff( myAdaptor, ais, inv, energy, fzMode ) ) if( this.importStuff( myAdaptor, ais, inv, energy, fzMode ) )
{ {
@@ -192,7 +196,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
if( !Configured ) if( !Configured )
{ {
while( this.itemToSend > 0 ) while( itemsToSend > 0 )
{ {
if( this.importStuff( myAdaptor, null, inv, energy, fzMode ) ) 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 ) if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{ {
newItems = myAdaptor.removeSimilarItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), fzMode, newItems = myAdaptor.removeSimilarItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), fzMode, this );
this.configDestination( inv ) );
} }
else 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() ) if( !newItems.isEmpty() )
{ {
newItems.setCount( (int) ( Math.min( newItems.getCount(), final IAEItemStack aeStack = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( newItems );
energy.extractAEPower( newItems.getCount(), Actionable.SIMULATE, PowerMultiplier.CONFIG ) ) + 0.01 ) ); final IAEItemStack failed = Platform.poweredInsert( energy, inv, aeStack, this.source );
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 );
if( failed != null ) 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; return true;
} }
else else
{ {
this.itemsToSend -= newItems.getCount();
this.worked = true; 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 ) 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; final ItemStack itemStackToImport;
if( whatToImport == null ) if( whatToImport == null )
@@ -282,13 +280,13 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
final ItemStack simResult; final ItemStack simResult;
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{ {
simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, this.configDestination( inv ) ); simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, this );
itemAmountNotStorable = this.destination.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source ); itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
} }
else else
{ {
simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, this.configDestination( inv ) ); simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, this );
itemAmountNotStorable = this.destination.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source ); itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
} }
if( itemAmountNotStorable != null ) if( itemAmountNotStorable != null )
@@ -299,12 +297,6 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
return toSend; return toSend;
} }
private IInventoryDestination configDestination( final IMEMonitor<IAEItemStack> itemInventory )
{
this.destination = itemInventory;
return this;
}
@Override @Override
protected boolean isSleeping() protected boolean isSleeping()
{ {
@@ -19,10 +19,10 @@
package appeng.parts.misc; package appeng.parts.misc;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -36,11 +36,12 @@ import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.ticking.TickRateModulation; import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.me.GridAccessException;
import appeng.me.helpers.IGridProxyable;
import appeng.me.storage.ITickingMonitor; import appeng.me.storage.ITickingMonitor;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
@@ -51,20 +52,17 @@ import appeng.util.item.AEItemStack;
*/ */
class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor
{ {
private final Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>(); private final Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
private IActionSource mySource; private IActionSource mySource;
private final IItemHandler itemHandler; private final IItemHandler itemHandler;
private final IGridProxyable proxyable;
private final InventoryCache cache;
private ItemStack[] cachedStacks = new ItemStack[0]; ItemHandlerAdapter( IItemHandler itemHandler, IGridProxyable proxy )
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
ItemHandlerAdapter( IItemHandler itemHandler )
{ {
this.itemHandler = itemHandler; this.itemHandler = itemHandler;
this.proxyable = proxy;
this.cache = new InventoryCache( this.itemHandler );
} }
@Override @Override
@@ -91,7 +89,14 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
this.onTick(); try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
} }
return AEItemStack.fromItemStack( remaining ); return AEItemStack.fromItemStack( remaining );
@@ -167,7 +172,14 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{ {
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
this.onTick(); try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
} }
return AEItemStack.fromItemStack( gathered ); return AEItemStack.fromItemStack( gathered );
@@ -176,72 +188,10 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
return null; 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 @Override
public TickRateModulation onTick() public TickRateModulation onTick()
{ {
LinkedList<IAEItemStack> changes = new LinkedList<>(); List<IAEItemStack> changes = this.cache.update();
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 );
}
if( !changes.isEmpty() ) if( !changes.isEmpty() )
{ {
this.postDifference( changes ); 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 @Override
public void setActionSource( final IActionSource mySource ) public void setActionSource( final IActionSource mySource )
{ {
@@ -339,7 +222,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
} }
@Override @Override
public IStorageChannel getChannel() public IItemStorageChannel getChannel()
{ {
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
} }
@@ -355,4 +238,152 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{ {
this.listeners.remove( l ); 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.IStorageMonitorableAccessor;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.api.util.AECableType; import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
@@ -112,7 +111,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
private int priority = 0; private int priority = 0;
private boolean cached = false; private boolean cached = false;
private ITickingMonitor monitor = null; private ITickingMonitor monitor = null;
private MEInventoryHandler<? extends IAEStack> handler = null; private MEInventoryHandler<IAEItemStack> handler = null;
private int handlerHash = 0; private int handlerHash = 0;
private boolean wasActive = false; private boolean wasActive = false;
private byte resetCacheLogic = 0; private byte resetCacheLogic = 0;
@@ -355,22 +354,18 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
final IMEInventory<IAEItemStack> out = this.getInternalHandler(); 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<IAEItemStack> getInventoryWrapper( TileEntity target )
private IMEInventory<? extends IAEItemStack> getInventoryWrapper( TileEntity target )
{ {
EnumFacing targetSide = this.getSide().getFacing().getOpposite(); 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 ); IItemHandler handlerExt = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide );
if( handlerExt != null ) if( handlerExt != null )
{ {
return new ItemHandlerAdapter( handlerExt ); return new ItemHandlerAdapter( handlerExt, this );
} }
return null; return null;
@@ -428,7 +423,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return 0; return 0;
} }
public MEInventoryHandler getInternalHandler() public MEInventoryHandler<IAEItemStack> getInternalHandler()
{ {
if( this.cached ) if( this.cached )
{ {
@@ -452,7 +447,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
this.monitor = null; this.monitor = null;
if( target != null ) if( target != null )
{ {
IMEInventory<? extends IAEStack> inv = this.getInventoryWrapper( target ); IMEInventory<IAEItemStack> inv = this.getInventoryWrapper( target );
if( inv instanceof MEMonitorIInventory ) if( inv instanceof MEMonitorIInventory )
{ {
@@ -470,7 +465,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{ {
this.checkInterfaceVsStorageBus( target, this.getSide().getOpposite() ); 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.setBaseAccess( (AccessRestriction) this.getConfigManager().getSetting( Settings.ACCESS ) );
this.handler.setWhitelist( this.getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST ); 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 ) if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{ {
this.handler 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 else
{ {
this.handler.setPartitionList( new PrecisePriorityList( priorityList ) ); this.handler.setPartitionList( new PrecisePriorityList<IAEItemStack>( priorityList ) );
} }
if( inv instanceof IBaseMonitor ) 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 ) ) 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 ) if( out != null )
{ {
return Collections.singletonList( out ); return Collections.singletonList( out );
@@ -41,6 +41,7 @@ import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartModel; import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType; import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
import appeng.core.AELog;
import appeng.core.AppEng; import appeng.core.AppEng;
import appeng.helpers.Reflected; import appeng.helpers.Reflected;
import appeng.items.parts.PartModels; import appeng.items.parts.PartModels;
@@ -208,6 +209,7 @@ public class PartToggleBus extends PartBasicState
catch( final FailedConnectionException e ) catch( final FailedConnectionException e )
{ {
// :( // :(
AELog.debug( e );
} }
} }
else else
@@ -55,7 +55,7 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
} }
private int lastValue = 0; private int lastValue = 0;
private float opacity = -1; private int opacity = -1;
public PartP2PLight( final ItemStack is ) public PartP2PLight( final ItemStack is )
{ {
@@ -81,15 +81,21 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
{ {
super.writeToStream( data ); super.writeToStream( data );
data.writeInt( this.isOutput() ? this.lastValue : 0 ); data.writeInt( this.isOutput() ? this.lastValue : 0 );
data.writeInt( this.opacity );
} }
@Override @Override
public boolean readFromStream( final ByteBuf data ) throws IOException public boolean readFromStream( final ByteBuf data ) throws IOException
{ {
super.readFromStream( data ); super.readFromStream( data );
final int oldValue = this.lastValue;
final int oldOpacity = this.opacity;
this.lastValue = data.readInt(); this.lastValue = data.readInt();
this.opacity = data.readInt();
this.setOutput( this.lastValue > 0 ); this.setOutput( this.lastValue > 0 );
return false; return lastValue != oldValue || oldOpacity != this.opacity;
} }
private boolean doWork() private boolean doWork()
@@ -126,14 +132,15 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
@Override @Override
public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor ) public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor )
{ {
this.opacity = -1; if( this.isOutput() && pos.offset( this.getSide().getFacing() ).equals( neighbor ) )
this.doWork();
if( this.isOutput() )
{ {
this.opacity = -1;
this.getHost().markForUpdate(); this.getHost().markForUpdate();
} }
else
{
this.doWork();
}
} }
@Override @Override
@@ -168,10 +175,6 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
public void readFromNBT( final NBTTagCompound tag ) public void readFromNBT( final NBTTagCompound tag )
{ {
super.readFromNBT( tag ); super.readFromNBT( tag );
if( tag.hasKey( "opacity" ) )
{
this.opacity = tag.getFloat( "opacity" );
}
this.lastValue = tag.getInteger( "lastValue" ); this.lastValue = tag.getInteger( "lastValue" );
} }
@@ -179,7 +182,6 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
public void writeToNBT( final NBTTagCompound tag ) public void writeToNBT( final NBTTagCompound tag )
{ {
super.writeToNBT( tag ); super.writeToNBT( tag );
tag.setFloat( "opacity", this.opacity );
tag.setInteger( "lastValue", this.lastValue ); tag.setInteger( "lastValue", this.lastValue );
} }
@@ -219,7 +221,7 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
@Override @Override
public TickRateModulation tickingRequest( final IGridNode node, final int ticksSinceLastCall ) public TickRateModulation tickingRequest( final IGridNode node, final int ticksSinceLastCall )
{ {
return this.doWork() ? TickRateModulation.FASTER : TickRateModulation.SLOWER; return this.doWork() ? TickRateModulation.URGENT : TickRateModulation.SLOWER;
} }
public float getPowerDrainPerTick() public float getPowerDrainPerTick()
@@ -247,6 +247,8 @@ public class PartP2PTunnelME extends PartP2PTunnel<PartP2PTunnelME> implements I
{ {
final TileEntity start = this.getTile(); final TileEntity start = this.getTile();
final TileEntity end = me.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]", 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(), start.getPos().getX(), start.getPos().getY(), start.getPos().getZ(), end.getPos().getX(), end.getPos().getY(),
@@ -70,7 +70,7 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
private byte spin = 0; // 0-3 private byte spin = 0; // 0-3
private int clientFlags = 0; // sent as byte. private int clientFlags = 0; // sent as byte.
private float opacity = -1; private int opacity = -1;
public AbstractPartReporting( final ItemStack is ) public AbstractPartReporting( final ItemStack is )
{ {
@@ -117,18 +117,17 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
@Override @Override
public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor ) public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor )
{ {
this.opacity = -1; if( pos.offset( this.getSide().getFacing() ).equals( neighbor ) )
this.getHost().markForUpdate(); {
this.opacity = -1;
this.getHost().markForUpdate();
}
} }
@Override @Override
public void readFromNBT( final NBTTagCompound data ) public void readFromNBT( final NBTTagCompound data )
{ {
super.readFromNBT( data ); super.readFromNBT( data );
if( data.hasKey( "opacity" ) )
{
this.opacity = data.getFloat( "opacity" );
}
this.spin = data.getByte( "spin" ); this.spin = data.getByte( "spin" );
} }
@@ -136,7 +135,6 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
public void writeToNBT( final NBTTagCompound data ) public void writeToNBT( final NBTTagCompound data )
{ {
super.writeToNBT( data ); super.writeToNBT( data );
data.setFloat( "opacity", this.opacity );
data.setByte( "spin", this.getSpin() ); data.setByte( "spin", this.getSpin() );
} }
@@ -169,6 +167,7 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
} }
data.writeByte( (byte) this.getClientFlags() ); data.writeByte( (byte) this.getClientFlags() );
data.writeInt( this.opacity );
} }
@Override @Override
@@ -176,9 +175,13 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
{ {
super.readFromStream( data ); super.readFromStream( data );
final int oldFlags = this.getClientFlags(); final int oldFlags = this.getClientFlags();
final int oldOpacity = this.opacity;
this.clientFlags = data.readByte(); this.clientFlags = data.readByte();
this.opacity = data.readInt();
this.spin = (byte) ( this.getClientFlags() & 3 ); this.spin = (byte) ( this.getClientFlags() & 3 );
if( this.getClientFlags() == oldFlags ) if( this.getClientFlags() == oldFlags && this.opacity == oldOpacity )
{ {
return false; return false;
} }
@@ -19,19 +19,34 @@
package appeng.recipes.factories.recipes; 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.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException; 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.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils; import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.IRecipeFactory; import net.minecraftforge.common.crafting.IRecipeFactory;
import net.minecraftforge.common.crafting.JsonContext; 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.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" ); String type = JsonUtils.getString( json, "type" );
if( type.contains( "shaped" ) ) if( type.contains( "shaped" ) )
{ {
PartShapedCraftingFactory recipe = PartShapedCraftingFactory.factory( context, json ); return shapedFactory( 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 );
} }
else if( type.contains( "shapeless" ) ) else if( type.contains( "shapeless" ) )
{ {
PartShapelessCraftingFactory recipe = PartShapelessCraftingFactory.factory( context, json ); return shapelessFactory( context, json );
return new PartShapelessCraftingFactory( new ResourceLocation( AppEng.MOD_ID, "part_shapeless_crafting" ), recipe.getIngredients(), recipe
.getRecipeOutput() );
} }
else 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 + "'!" ); 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 + "'." );
}
}
@@ -25,7 +25,6 @@ import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder;
import java.util.Collection; import java.util.Collection;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
@@ -58,7 +57,6 @@ public class RecipeResourceCopier
private static final String FILE_PROTOCOL = "file"; private static final String FILE_PROTOCOL = "file";
private static final String CLASS_EXTENSION = ".class"; private static final String CLASS_EXTENSION = ".class";
private static final String JAR_PROTOCOL = "jar"; private static final String JAR_PROTOCOL = "jar";
private static final String UTF_8_ENCODING = "UTF-8";
/** /**
* copy source in the jar * copy source in the jar
@@ -225,9 +223,9 @@ public class RecipeResourceCopier
{ {
/* A JAR path */ /* A JAR path */
final String dirPath = dirURL.getPath(); final String dirPath = dirURL.getPath();
final String jarPath = dirPath.substring( 5, dirPath.indexOf( '!' ) ); // strip out only final String jarPath = dirPath.substring( 0, dirPath.indexOf( '!' ) ); // strip out only
// the JAR file // the JAR file
final JarFile jar = new JarFile( URLDecoder.decode( jarPath, UTF_8_ENCODING ) ); final JarFile jar = new JarFile( new File( new URI( jarPath ) ) );
try try
{ {
final Enumeration<JarEntry> entries = jar.entries(); // gives ALL entries in jar final Enumeration<JarEntry> entries = jar.entries(); // gives ALL entries in jar
@@ -27,7 +27,7 @@ public class BiomeGenStorage extends Biome
public BiomeGenStorage() 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.treesPerChunk = 0;
this.decorator.flowersPerChunk = 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.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.NextTickListEntry; import net.minecraft.world.NextTickListEntry;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -34,7 +35,6 @@ import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.definitions.IBlockDefinition;
import appeng.api.movable.IMovableHandler; import appeng.api.movable.IMovableHandler;
import appeng.api.movable.IMovableRegistry; import appeng.api.movable.IMovableRegistry;
import appeng.api.util.AEPartLocation; import appeng.api.util.AEPartLocation;
@@ -61,7 +61,6 @@ public class CachedPlane
private final World world; private final World world;
private final IMovableRegistry reg = AEApi.instance().registries().movable(); private final IMovableRegistry reg = AEApi.instance().registries().movable();
private final LinkedList<WorldCoord> updates = new LinkedList<>(); private final LinkedList<WorldCoord> updates = new LinkedList<>();
private final IBlockDefinition matrixFrame = AEApi.instance().definitions().blocks().matrixFrame();
private int verticalBits; private int verticalBits;
private final IBlockState matrixBlockState; private final IBlockState matrixBlockState;
@@ -146,11 +145,11 @@ public class CachedPlane
} }
else else
{ {
final Object[] details = this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].getDetails( tePOS.getY() ); final BlockStorageData details = new BlockStorageData();
final IBlockState blkState = (IBlockState) details[0]; this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].fillData( tePOS.getY(), details );
// don't skip air, just let the code replace it... // 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 ); w.setBlockToAir( tePOS );
} }
@@ -168,12 +167,11 @@ public class CachedPlane
} }
final long k = this.getWorld().getTotalWorldTime(); 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 ) if( list != null )
{ {
for( final Object o : list ) for( final NextTickListEntry entry : list )
{ {
final NextTickListEntry entry = (NextTickListEntry) o;
final BlockPos tePOS = entry.position; final BlockPos tePOS = entry.position;
if( tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS if( tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS
.getZ() <= maxZ ) .getZ() <= maxZ )
@@ -192,6 +190,10 @@ public class CachedPlane
try try
{ {
this.getWorld().loadedTileEntityList.remove( te ); this.getWorld().loadedTileEntityList.remove( te );
if( te instanceof ITickable )
{
this.getWorld().tickableTileEntities.remove( te );
}
} }
catch( final Exception e ) 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 ); AELog.info( "Block Copy Scale: " + this.x_size + ", " + this.y_size + ", " + this.z_size );
long startTime = System.nanoTime(); long startTime = System.nanoTime();
final BlockStorageData aD = new BlockStorageData();
final BlockStorageData bD = new BlockStorageData();
for( int x = 0; x < this.x_size; x++ ) 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 ) ) if( a.doNotSkip( src_y ) && b.doNotSkip( dst_y ) )
{ {
final Object[] aD = a.getDetails( src_y ); a.fillData( src_y, aD );
final Object[] bD = b.getDetails( dst_y ); b.fillData( dst_y, bD );
a.setBlockIDWithMetadata( src_y, bD ); a.setBlockIDWithMetadata( src_y, bD );
b.setBlockIDWithMetadata( dst_y, aD ); b.setBlockIDWithMetadata( dst_y, aD );
@@ -386,14 +390,17 @@ public class CachedPlane
return this.world; return this.world;
} }
private static class BlockStorageData
{
public IBlockState state;
public int light;
}
private class Column private class Column
{ {
private final int x; private final int x;
private final int z; private final int z;
private final Chunk c; private final Chunk c;
private final Object[] ch = { 0, 0 };
private final ExtendedBlockStorage[] storage;
private List<Integer> skipThese = null; private List<Integer> skipThese = null;
public Column( final Chunk chunk, final int x, final int z, final int chunkY, final int chunkHeight ) 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.x = x;
this.z = z; this.z = z;
this.c = chunk; this.c = chunk;
this.storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
// make sure storage exists before hand... // make sure storage exists before hand...
for( int ay = 0; ay < chunkHeight; ay++ ) for( int ay = 0; ay < chunkHeight; ay++ )
{ {
final int by = ( ay + chunkY ); final int by = ( ay + chunkY );
ExtendedBlockStorage extendedblockstorage = this.storage[by]; ExtendedBlockStorage extendedblockstorage = storage[by];
if( extendedblockstorage == null ) 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[] storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage extendedBlockStorage = this.storage[y >> 4]; final ExtendedBlockStorage extendedBlockStorage = storage[y >> 4];
extendedBlockStorage.set( this.x, y & 15, this.z, (IBlockState) blk[0] ); extendedBlockStorage.set( this.x, y & 15, this.z, data.state );
// extendedBlockStorage.setExtBlockID( x, y & 15, z, blk[0] ); extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, data.light );
extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, (Integer) blk[1] );
} }
private Object[] getDetails( final int y ) private void fillData( final int y, BlockStorageData data )
{ {
final ExtendedBlockStorage extendedblockstorage = this.storage[y >> 4]; final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
this.ch[0] = extendedblockstorage.get( this.x, y & 15, this.z ); final ExtendedBlockStorage extendedblockstorage = storage[y >> 4];
this.ch[1] = extendedblockstorage.getBlockLight( this.x, y & 15, this.z );
return this.ch; 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 ) 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() ) ) if( CachedPlane.this.reg.isBlacklisted( extendedblockstorage.get( this.x, y & 15, this.z ).getBlock() ) )
{ {
return false; return false;
@@ -19,6 +19,7 @@
package appeng.spatial; package appeng.spatial;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -54,8 +55,9 @@ public class DefaultSpatialHandler implements IMovableHandler
if( c.isLoaded() ) if( c.isLoaded() )
{ {
final IBlockState state = w.getBlockState( newPosition );
w.addTileEntity( te ); 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 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().getPlayerList().transferEntityToWorld( entity, entity.dimension,
entity.getServer().getWorld( entity.dimension ), (WorldServer) link.dim, new METeleporter( newWorld, link ) ); entity.getServer().getWorld( entity.dimension ), (WorldServer) link.dim, new METeleporter( newWorld, link ) );
} }
@@ -74,7 +74,7 @@ public class TileCraftingStorageTile extends TileCraftingTile
@Override @Override
public int getStorageBytes() public int getStorageBytes()
{ {
if( this.world == null || this.notLoaded() ) if( this.world == null || this.notLoaded() || this.isInvalid() )
{ {
return 0; return 0;
} }
@@ -143,7 +143,7 @@ public class TileCraftingTile extends AENetworkTile implements IAEMultiBlock, IP
public void updateMeta( final boolean updateFormed ) public void updateMeta( final boolean updateFormed )
{ {
if( this.world == null || this.notLoaded() ) if( this.world == null || this.notLoaded() || this.isInvalid() )
{ {
return; return;
} }
@@ -46,6 +46,7 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
private final IAEItemStack[] inv; private final IAEItemStack[] inv;
private final int size; private final int size;
private int maxStack; private int maxStack;
private boolean dirtyFlag = false;
public AppEngInternalAEInventory( final IAEAppEngInventory te, final int s ) public AppEngInternalAEInventory( final IAEAppEngInventory te, final int s )
{ {
@@ -252,8 +253,10 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
{ {
if( this.te != null && Platform.isServer() ) if( this.te != null && Platform.isServer() )
{ {
this.dirtyFlag = true;
this.te.onChangeInventory( this, slot, op, removed, inserted ); this.te.onChangeInventory( this, slot, op, removed, inserted );
this.te.saveChanges(); this.te.saveChanges();
this.dirtyFlag = false;
} }
} }
@@ -283,6 +286,9 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
@Override @Override
public void markDirty( int slot ) 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 final int[] maxStack;
private ItemStack previousStack = ItemStack.EMPTY; private ItemStack previousStack = ItemStack.EMPTY;
private IAEItemFilter filter; private IAEItemFilter filter;
private boolean dirtyFlag = false;
public AppEngInternalInventory( final IAEAppEngInventory inventory, final int size, final int maxStack, IAEItemFilter filter ) 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() ) if( this.getTileEntity() != null && this.eventsEnabled() )
{ {
this.dirtyFlag = true;
ItemStack newStack = this.getStackInSlot( slot ).copy(); ItemStack newStack = this.getStackInSlot( slot ).copy();
ItemStack oldStack = this.previousStack; ItemStack oldStack = this.previousStack;
InvOperation op = InvOperation.SET; 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().onChangeInventory( this, slot, op, oldStack, newStack );
this.getTileEntity().saveChanges(); this.getTileEntity().saveChanges();
this.previousStack = ItemStack.EMPTY; this.previousStack = ItemStack.EMPTY;
this.dirtyFlag = false;
} }
super.onContentsChanged( slot ); super.onContentsChanged( slot );
} }
@@ -158,10 +161,12 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
@Override @Override
public void markDirty( final int slot ) 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().onChangeInventory( this, slot, InvOperation.DIRTY, ItemStack.EMPTY, ItemStack.EMPTY );
this.getTileEntity().saveChanges(); this.getTileEntity().saveChanges();
this.dirtyFlag = false;
} }
} }
@@ -19,23 +19,37 @@
package appeng.tile.misc; 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.AEApi;
import appeng.api.config.AccessRestriction; import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.networking.security.IActionSource; import appeng.api.networking.security.IActionSource;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver; import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel; import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; 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; 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 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 ) CondenserItemInventory( final TileCondenser te )
{ {
@@ -49,30 +63,46 @@ class CondenserItemInventory implements IMEMonitor<IAEItemStack>
{ {
this.target.addPower( input.getStackSize() ); this.target.addPower( input.getStackSize() );
} }
return null; return null;
} }
@Override @Override
public IAEItemStack extractItems( final IAEItemStack request, final Actionable mode, final IActionSource src ) 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 @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; return out;
} }
@Override @Override
public IItemList<IAEItemStack> getStorageList() 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 @Override
public IStorageChannel getChannel() public IStorageChannel<IAEItemStack> getChannel()
{ {
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
} }
@@ -80,7 +110,7 @@ class CondenserItemInventory implements IMEMonitor<IAEItemStack>
@Override @Override
public AccessRestriction getAccess() public AccessRestriction getAccess()
{ {
return AccessRestriction.WRITE; return AccessRestriction.READ_WRITE;
} }
@Override @Override
@@ -114,14 +144,62 @@ class CondenserItemInventory implements IMEMonitor<IAEItemStack>
} }
@Override @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 @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.IConfigManagerHost;
import appeng.util.inv.InvOperation; import appeng.util.inv.InvOperation;
import appeng.util.inv.WrapperChainedItemHandler; import appeng.util.inv.WrapperChainedItemHandler;
import appeng.util.inv.WrapperFilteredItemHandler;
import appeng.util.inv.filter.AEItemFilters;
public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost, IConfigurableObject 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; public static final int BYTE_MULTIPLIER = 8;
private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 2 );
private final ConfigManager cm = new ConfigManager( this ); 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 IItemHandler inputSlot = new CondenseItemHandler();
private final IFluidHandler fluidHandler = new FluidHandler(); private final IFluidHandler fluidHandler = new FluidHandler();
private final MEHandler meHandler = new MEHandler(); 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; private double storedPower = 0;
@@ -97,7 +101,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
public double getStorage() public double getStorage()
{ {
final ItemStack is = this.inv.getStackInSlot( 1 ); final ItemStack is = this.storageSlot.getStackInSlot( 0 );
if( !is.isEmpty() ) if( !is.isEmpty() )
{ {
if( is.getItem() instanceof IStorageComponent ) if( is.getItem() instanceof IStorageComponent )
@@ -135,7 +139,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
private boolean canAddOutput( final ItemStack output ) 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 ) 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() private ItemStack getOutput()
@@ -180,7 +189,10 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
@Override @Override
public void onChangeInventory( final IItemHandler inv, final int slot, final InvOperation mc, final ItemStack removed, final ItemStack added ) 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 @Override
@@ -225,7 +237,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
{ {
if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ) if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY )
{ {
return (T) this.inputSlot; return (T) this.externalInv;
} }
else if( capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ) 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 ); private final CondenserItemInventory itemInventory = new CondenserItemInventory( TileCondenser.this );
void outputChanged( ItemStack added, ItemStack removed )
{
itemInventory.updateOutput( added, removed );
}
@Nullable @Nullable
@Override @Override
public IStorageMonitorable getInventory( IActionSource src ) public IStorageMonitorable getInventory( IActionSource src )
@@ -281,9 +281,13 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
@Nullable @Nullable
public IInscriberRecipe getTask() public IInscriberRecipe getTask()
{ {
final ItemStack plateA = this.topItemHandler.getStackInSlot( 0 ); return getTask( this.sideItemHandler.getStackInSlot( 0 ), this.topItemHandler.getStackInSlot( 0 ), this.bottomItemHandler.getStackInSlot( 0 ) );
final ItemStack plateB = this.bottomItemHandler.getStackInSlot( 0 ); }
ItemStack renamedItem = this.sideItemHandler.getStackInSlot( 0 );
@Nullable
private IInscriberRecipe getTask( final ItemStack input, final ItemStack plateA, final ItemStack plateB )
{
ItemStack renamedItem = input;
if( !plateA.isEmpty() && plateA.getCount() > 1 ) if( !plateA.isEmpty() && plateA.getCount() > 1 )
{ {
@@ -379,7 +383,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
{ {
for( final ItemStack option : recipe.getInputs() ) for( final ItemStack option : recipe.getInputs() )
{ {
if( Platform.itemComparisons().isSameItem( option, this.sideItemHandler.getStackInSlot( 0 ) ) ) if( Platform.itemComparisons().isSameItem( input, option ) )
{ {
return recipe; return recipe;
} }
@@ -606,7 +610,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
} }
for( final ItemStack optionals : AEApi.instance().registries().inscriber().getOptionals() ) for( final ItemStack optionals : AEApi.instance().registries().inscriber().getOptionals() )
{ {
if( Platform.itemComparisons().isSameItem( optionals, stack ) ) if( Platform.itemComparisons().isSameItem( stack, optionals ) )
{ {
return true; return true;
} }
@@ -83,13 +83,14 @@ public class TileCableBus extends AEBaseTile implements AEMultiTile, ICustomColl
protected boolean readFromStream( final ByteBuf data ) throws IOException protected boolean readFromStream( final ByteBuf data ) throws IOException
{ {
final boolean c = super.readFromStream( data ); final boolean c = super.readFromStream( data );
final boolean ret = this.getCableBus().readFromStream( data ); boolean ret = this.getCableBus().readFromStream( data );
final int newLV = this.getCableBus().getLightValue(); final int newLV = this.getCableBus().getLightValue();
if( newLV != this.oldLV ) if( newLV != this.oldLV )
{ {
this.oldLV = newLV; this.oldLV = newLV;
this.world.checkLight( this.pos ); this.world.checkLight( this.pos );
ret = true;
} }
this.updateTileSetting(); this.updateTileSetting();
@@ -189,7 +190,6 @@ public class TileCableBus extends AEBaseTile implements AEMultiTile, ICustomColl
{ {
this.oldLV = newLV; this.oldLV = newLV;
this.world.checkLight( this.pos ); this.world.checkLight( this.pos );
// world.updateAllLightTypes( xCoord, yCoord, zCoord );
} }
super.markForUpdate(); super.markForUpdate();
@@ -209,8 +209,7 @@ public class TileController extends AENetworkPowerTile
*/ */
private boolean checkController( final BlockPos pos ) private boolean checkController( final BlockPos pos )
{ {
final BlockPos ownPos = this.getPos(); if( this.world.getChunkProvider().getLoadedChunk( pos.getX() >> 4, pos.getZ() >> 4 ) != null )
if( this.world.getChunkProvider().getLoadedChunk( ownPos.getX() >> 4, ownPos.getZ() >> 4 ) != null )
{ {
return this.world.getTileEntity( pos ) instanceof TileController; return this.world.getTileEntity( pos ) instanceof TileController;
} }
@@ -84,7 +84,7 @@ public class TileEnergyCell extends AENetworkTile implements IAEPowerStorage
private void changePowerLevel() private void changePowerLevel()
{ {
if( this.notLoaded() ) if( this.notLoaded() || this.isInvalid() )
{ {
return; return;
} }
@@ -19,7 +19,9 @@
package appeng.tile.storage; package appeng.tile.storage;
import java.util.IdentityHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -48,10 +50,6 @@ import appeng.api.networking.ticking.TickingRequest;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor; import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IStorageChannel; import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.api.util.AECableType; import appeng.api.util.AECableType;
@@ -68,7 +66,6 @@ import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.ConfigManager; import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost; import appeng.util.IConfigManagerHost;
import appeng.util.InventoryAdaptor; import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil; import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.AdaptorItemHandler; import appeng.util.inv.AdaptorItemHandler;
import appeng.util.inv.InvOperation; import appeng.util.inv.InvOperation;
@@ -79,10 +76,13 @@ import appeng.util.inv.filter.AEItemFilters;
public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IConfigManagerHost, IGridTickable public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IConfigManagerHost, IGridTickable
{ {
private static final int NUMBER_OF_CELL_SLOTS = 6;
private static final int NUMBER_OF_UPGRADE_SLOTS = 3;
private final ConfigManager manager; private final ConfigManager manager;
private final AppEngInternalInventory inputCells = new AppEngInternalInventory( this, 6 ); private final AppEngInternalInventory inputCells = new AppEngInternalInventory( this, NUMBER_OF_CELL_SLOTS );
private final AppEngInternalInventory outputCells = new AppEngInternalInventory( this, 6 ); private final AppEngInternalInventory outputCells = new AppEngInternalInventory( this, NUMBER_OF_CELL_SLOTS );
private final IItemHandler combinedInventory = new WrapperChainedItemHandler( this.inputCells, this.outputCells ); private final IItemHandler combinedInventory = new WrapperChainedItemHandler( this.inputCells, this.outputCells );
private final IItemHandler inputCellsExt = new WrapperFilteredItemHandler( this.inputCells, AEItemFilters.INSERT_ONLY ); private final IItemHandler inputCellsExt = new WrapperFilteredItemHandler( this.inputCells, AEItemFilters.INSERT_ONLY );
@@ -92,8 +92,7 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
private final IActionSource mySrc; private final IActionSource mySrc;
private YesNo lastRedstoneState; private YesNo lastRedstoneState;
private ItemStack currentCell; private ItemStack currentCell;
private IMEInventory<IAEFluidStack> cachedFluid; private Map<IStorageChannel<?>, IMEInventory<?>> cachedInventories;
private IMEInventory<IAEItemStack> cachedItem;
public TileIOPort() public TileIOPort()
{ {
@@ -106,7 +105,7 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
this.lastRedstoneState = YesNo.UNDECIDED; this.lastRedstoneState = YesNo.UNDECIDED;
final Block ioPortBlock = AEApi.instance().definitions().blocks().iOPort().maybeBlock().get(); final Block ioPortBlock = AEApi.instance().definitions().blocks().iOPort().maybeBlock().get();
this.upgrades = new BlockUpgradeInventory( ioPortBlock, this, 3 ); this.upgrades = new BlockUpgradeInventory( ioPortBlock, this, NUMBER_OF_UPGRADE_SLOTS );
} }
@Override @Override
@@ -277,87 +276,84 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
return TickRateModulation.IDLE; return TickRateModulation.IDLE;
} }
long ItemsToMove = 256; TickRateModulation ret = TickRateModulation.SLEEP;
long itemsToMove = 256;
switch( this.getInstalledUpgrades( Upgrades.SPEED ) ) switch( this.getInstalledUpgrades( Upgrades.SPEED ) )
{ {
case 1: case 1:
ItemsToMove *= 2; itemsToMove *= 2;
break; break;
case 2: case 2:
ItemsToMove *= 4; itemsToMove *= 4;
break; break;
case 3: case 3:
ItemsToMove *= 8; itemsToMove *= 8;
break; break;
} }
try try
{ {
final IMEInventory<IAEItemStack> itemNet = this.getProxy().getStorage().getInventory(
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
final IMEInventory<IAEFluidStack> fluidNet = this.getProxy().getStorage().getInventory(
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
final IEnergySource energy = this.getProxy().getEnergy(); final IEnergySource energy = this.getProxy().getEnergy();
for( int x = 0; x < 6; x++ ) for( int x = 0; x < NUMBER_OF_CELL_SLOTS; x++ )
{ {
final ItemStack is = this.inputCells.getStackInSlot( x ); final ItemStack is = this.inputCells.getStackInSlot( x );
if( !is.isEmpty() ) if( !is.isEmpty() )
{ {
if( ItemsToMove > 0 ) boolean shouldMove = true;
for( IStorageChannel<? extends IAEStack<?>> c : AEApi.instance().storage().storageChannels() )
{ {
final IMEInventory<IAEItemStack> itemInv = this.getInv( is, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); if( itemsToMove > 0 )
final IMEInventory<IAEFluidStack> fluidInv = this.getInv( is,
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
if( this.manager.getSetting( Settings.OPERATION_MODE ) == OperationMode.EMPTY )
{ {
if( itemInv != null ) final IMEMonitor<? extends IAEStack<?>> network = this.getProxy().getStorage().getInventory( c );
final IMEInventory<?> inv = this.getInv( is, c );
if( inv == null )
{ {
ItemsToMove = this.transferContents( energy, itemInv, itemNet, ItemsToMove, continue;
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
} }
if( fluidInv != null )
if( this.manager.getSetting( Settings.OPERATION_MODE ) == OperationMode.EMPTY )
{ {
ItemsToMove = this.transferContents( energy, fluidInv, fluidNet, ItemsToMove, itemsToMove = this.transferContents( energy, inv, network, itemsToMove, c );
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ); }
} else
} {
else itemsToMove = this.transferContents( energy, network, inv, itemsToMove, c );
{ }
if( itemInv != null )
{ shouldMove &= this.shouldMove( inv );
ItemsToMove = this.transferContents( energy, itemNet, itemInv, ItemsToMove,
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); if( itemsToMove > 0 )
} {
if( fluidInv != null ) ret = TickRateModulation.IDLE;
{ }
ItemsToMove = this.transferContents( energy, fluidNet, fluidInv, ItemsToMove, else
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ); {
ret = TickRateModulation.URGENT;
} }
} }
}
if( ItemsToMove > 0 && this.shouldMove( itemInv, fluidInv ) && !this.moveSlot( x ) ) if( itemsToMove > 0 && shouldMove && this.moveSlot( x ) )
{ {
return TickRateModulation.IDLE; ret = TickRateModulation.URGENT;
}
return TickRateModulation.URGENT;
} }
else else
{ {
return TickRateModulation.URGENT; ret = TickRateModulation.URGENT;
} }
} }
} }
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
{ {
return TickRateModulation.IDLE; ret = TickRateModulation.IDLE;
} }
// nothing left to do... return ret;
return TickRateModulation.SLEEP;
} }
@Override @Override
@@ -366,23 +362,20 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
return this.upgrades.getInstalledUpgrades( u ); return this.upgrades.getInstalledUpgrades( u );
} }
private IMEInventory getInv( final ItemStack is, final IStorageChannel chan ) private IMEInventory<?> getInv( final ItemStack is, final IStorageChannel<?> chan )
{ {
if( this.currentCell != is ) if( this.currentCell != is )
{ {
this.currentCell = is; this.currentCell = is;
this.cachedFluid = AEApi.instance().registries().cell().getCellInventory( is, null, this.cachedInventories = new IdentityHashMap<>();
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
this.cachedItem = AEApi.instance().registries().cell().getCellInventory( is, null, for( IStorageChannel<? extends IAEStack<?>> c : AEApi.instance().storage().storageChannels() )
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); {
this.cachedInventories.put( c, AEApi.instance().registries().cell().getCellInventory( is, null, c ) );
}
} }
if( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) == chan ) return this.cachedInventories.get( chan );
{
return this.cachedItem;
}
return this.cachedFluid;
} }
private long transferContents( final IEnergySource energy, final IMEInventory src, final IMEInventory destination, long itemsToMove, final IStorageChannel chan ) private long transferContents( final IEnergySource energy, final IMEInventory src, final IMEInventory destination, long itemsToMove, final IStorageChannel chan )
@@ -397,6 +390,8 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
myList = src.getAvailableItems( src.getChannel().createList() ); myList = src.getAvailableItems( src.getChannel().createList() );
} }
itemsToMove *= chan.transferFactor();
boolean didStuff; boolean didStuff;
do do
@@ -429,7 +424,7 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
if( extracted != null ) if( extracted != null )
{ {
possible = extracted.getStackSize(); possible = extracted.getStackSize();
final IAEStack failed = Platform.poweredInsert( energy, destination, extracted, this.mySrc ); final IAEStack failed = chan.poweredInsert( energy, destination, extracted, this.mySrc );
if( failed != null ) if( failed != null )
{ {
@@ -451,24 +446,16 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
} }
while( itemsToMove > 0 && didStuff ); while( itemsToMove > 0 && didStuff );
return itemsToMove; return itemsToMove / chan.transferFactor();
} }
private boolean shouldMove( final IMEInventory<IAEItemStack> itemInv, final IMEInventory<IAEFluidStack> fluidInv ) private boolean shouldMove( final IMEInventory<?> inv )
{ {
final FullnessMode fm = (FullnessMode) this.manager.getSetting( Settings.FULLNESS_MODE ); final FullnessMode fm = (FullnessMode) this.manager.getSetting( Settings.FULLNESS_MODE );
if( itemInv != null && fluidInv != null ) if( inv != null )
{ {
return this.matches( fm, itemInv ) && this.matches( fm, fluidInv ); return this.matches( fm, inv );
}
else if( itemInv != null )
{
return this.matches( fm, itemInv );
}
else if( fluidInv != null )
{
return this.matches( fm, fluidInv );
} }
return true; return true;
+16 -14
View File
@@ -1174,13 +1174,13 @@ public class Platform
stored -= possible.getStackSize(); stored -= possible.getStackSize();
} }
final double availablePower = energy.extractAEPower( stored, Actionable.SIMULATE, PowerMultiplier.CONFIG ); final int energyFactor = Math.min( 1, input.getChannel().transferFactor() );
final double availablePower = energy.extractAEPower( stored / energyFactor, Actionable.SIMULATE, PowerMultiplier.CONFIG );
final long itemToAdd = Math.min( (long) ( availablePower + 0.9 ), stored ); final long itemToAdd = Math.min( (long) ( availablePower + 0.9 ), stored );
if( itemToAdd > 0 ) if( itemToAdd > 0 )
{ {
energy.extractAEPower( stored, Actionable.MODULATE, PowerMultiplier.CONFIG ); energy.extractAEPower( stored / energyFactor, Actionable.MODULATE, PowerMultiplier.CONFIG );
if( itemToAdd < input.getStackSize() ) if( itemToAdd < input.getStackSize() )
{ {
@@ -1296,11 +1296,11 @@ public class Platform
{ {
if( a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1 ) if( a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1 )
{ {
return false; return true;
} }
else if( a.getLastSecurityKey() == b.getLastSecurityKey() ) else if( a.getLastSecurityKey() == b.getLastSecurityKey() )
{ {
return false; return true;
} }
final boolean a_isSecure = isPowered( a.getGrid() ) && a.getLastSecurityKey() != -1; 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 ) ) if( AEConfig.instance().isFeatureEnabled( AEFeature.LOG_SECURITY_AUDITS ) )
{ {
AELog.info( final String locationA = a.getGridBlock().isWorldAccessible() ? a.getGridBlock().getLocation().toString() : "notInWorld";
"Audit: " + a_isSecure + " : " + b_isSecure + " @ " + a.getLastSecurityKey() + " vs " + b.getLastSecurityKey() + " & " + a final String locationB = b.getGridBlock().isWorldAccessible() ? b.getGridBlock().getLocation().toString() : "notInWorld";
.getPlayerID() + " vs " + b.getPlayerID() );
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... // can't do that son...
if( a_isSecure && b_isSecure ) if( a_isSecure && b_isSecure )
{ {
return true; return false;
} }
if( !a_isSecure && b_isSecure ) if( !a_isSecure && b_isSecure )
@@ -1329,7 +1331,7 @@ public class Platform
return checkPlayerPermissions( a.getGrid(), b.getPlayerID() ); return checkPlayerPermissions( a.getGrid(), b.getPlayerID() );
} }
return false; return true;
} }
private static boolean isPowered( final IGrid grid ) private static boolean isPowered( final IGrid grid )
@@ -1347,22 +1349,22 @@ public class Platform
{ {
if( grid == null ) if( grid == null )
{ {
return false; return true;
} }
final ISecurityGrid gs = grid.getCache( ISecurityGrid.class ); final ISecurityGrid gs = grid.getCache( ISecurityGrid.class );
if( gs == null ) if( gs == null )
{ {
return false; return true;
} }
if( !gs.isAvailable() ) 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 ) public static void configurePlayer( final EntityPlayer player, final AEPartLocation side, final TileEntity tile )
@@ -21,7 +21,6 @@ package appeng.util.helpers;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import net.minecraft.init.Items;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTBase;
@@ -95,55 +94,23 @@ public class ItemComparisonHelper
return false; return false;
} }
/*
* if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! a.getHasSubtypes() && a.itemID ==
* b.itemID ) { return (a.getItemDamage() > 0) == (b.getItemDamage() > 0); }
*/
// test damageable items.. // test damageable items..
if( a.getItem() != Items.AIR && b.getItem() != Items.AIR && a.getItem().isDamageable() && a.getItem() == b.getItem() ) if( a.getItem() == b.getItem() && a.getItem().isDamageable() )
{ {
try if( mode == FuzzyMode.IGNORE_ALL )
{ {
if( mode == FuzzyMode.IGNORE_ALL ) return true;
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
final Item ai = a.getItem();
final Item bi = b.getItem();
return ( ai.getDurabilityForDisplay( a ) > 1 ) == ( bi.getDurabilityForDisplay( b ) > 1 );
}
else
{
final Item ai = a.getItem();
final Item bi = b.getItem();
final float percentDamagedOfA = 1.0f - (float) ai.getDurabilityForDisplay( a );
final float percentDamagedOfB = 1.0f - (float) bi.getDurabilityForDisplay( b );
return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint );
}
} }
catch( final Throwable e ) else if( mode == FuzzyMode.PERCENT_99 )
{ {
if( mode == FuzzyMode.IGNORE_ALL ) return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
{ }
return true; else
} {
else if( mode == FuzzyMode.PERCENT_99 ) final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
{ final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
}
else
{
final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint ); return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint );
}
} }
} }
@@ -155,17 +122,6 @@ public class ItemComparisonHelper
return true; return true;
} }
/*
* // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return OreID == getOreID( b );
* if ( Mode != FuzzyMode.IGNORE_ALL ) { if ( a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a =
* Platform.getSharedItemStack( AEItemStack.create( a ) ); }
* if ( b.hasTagCompound() && !isShared( b.getTagCompound() ) ) { b = Platform.getSharedItemStack(
* AEItemStack.create( b ) ); }
* // test regular items with damage values and what not... if ( isShared( a.getTagCompound() ) && isShared(
* b.getTagCompound() ) && a.itemID == b.itemID ) { return ((AppEngSharedNBTTagCompound)
* a.getTagCompound()).compareFuzzyWithRegistry( (AppEngSharedNBTTagCompound) b.getTagCompound() ); } }
*/
return a.isItemEqual( b ); return a.isItemEqual( b );
} }
@@ -180,10 +136,25 @@ public class ItemComparisonHelper
{ {
return true; return true;
} }
final boolean isLeftEmpty = left == null || left.hasNoTags();
final boolean isRightEmpty = right == null || right.hasNoTags();
if( isLeftEmpty && isRightEmpty )
{
return true;
}
if( isLeftEmpty != isRightEmpty )
{
return false;
}
if( left != null ) if( left != null )
{ {
return left.equals( right ); return left.equals( right );
} }
return false; return false;
} }
} }
@@ -21,7 +21,7 @@ package appeng.util.inv;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraftforge.items.wrapper.PlayerInvWrapper; import net.minecraftforge.items.wrapper.PlayerMainInvWrapper;
import appeng.util.Platform; import appeng.util.Platform;
@@ -30,7 +30,7 @@ public class AdaptorItemHandlerPlayerInv extends AdaptorItemHandler
{ {
public AdaptorItemHandlerPlayerInv( final EntityPlayer playerInv ) 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 ); final AEFluidStack fluid = AEFluidStack.fromFluidStack( fluidStack );
// fluid.priority = i.getInteger( "Priority" );
fluid.setStackSize( i.getLong( "Cnt" ) ); fluid.setStackSize( i.getLong( "Cnt" ) );
fluid.setCountRequestable( i.getLong( "Req" ) ); fluid.setCountRequestable( i.getLong( "Req" ) );
fluid.setCraftable( i.getBoolean( "Craft" ) ); 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 public static IAEFluidStack fromPacket( final ByteBuf data ) throws IOException
{ {
final byte mask = data.readByte(); final byte mask = data.readByte();
// byte PriorityType = (byte) (mask & 0x03);
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 ); final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 ); final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0; final boolean isCraftable = ( mask & 0x40 ) > 0;
final boolean hasTagCompound = ( mask & 0x80 ) > 0; final boolean hasTagCompound = ( mask & 0x80 ) > 0;
boolean showCraftingLabel = data.readBoolean();
// don't send this... // don't send this...
final NBTTagCompound d = new NBTTagCompound(); final NBTTagCompound d = new NBTTagCompound();
@@ -139,17 +136,11 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
d.setTag( "tag", CompressedStreamTools.read( di ) ); d.setTag( "tag", CompressedStreamTools.read( di ) );
} }
// long priority = getPacketValue( PriorityType, data );
final long stackSize = getPacketValue( stackType, data ); final long stackSize = getPacketValue( stackType, data );
final long countRequestable = getPacketValue( countReqType, data ); final long countRequestable = getPacketValue( countReqType, data );
final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( d ); final FluidStack fluidStack = FluidStack.loadFluidStackFromNBT( d );
if( !showCraftingLabel )
{
showCraftingLabel = stackSize == 0;
}
if( fluidStack == null ) if( fluidStack == null )
{ {
return null; return null;
@@ -170,10 +161,6 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
{ {
return; return;
} }
// if ( priority < ((AEFluidStack) option).priority )
// priority = ((AEFluidStack) option).priority;
this.incStackSize( option.getStackSize() ); this.incStackSize( option.getStackSize() );
this.setCountRequestable( this.getCountRequestable() + option.getCountRequestable() ); this.setCountRequestable( this.getCountRequestable() + option.getCountRequestable() );
this.setCraftable( this.isCraftable() || option.isCraftable() ); this.setCraftable( this.isCraftable() || option.isCraftable() );
@@ -364,7 +351,20 @@ public final class AEFluidStack extends AEStack<IAEFluidStack> implements IAEFlu
} }
@Override @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" ); final byte[] name = this.fluid.getName().getBytes( "UTF-8" );
i.writeByte( (byte) name.length ); i.writeByte( (byte) name.length );
+67 -130
View File
@@ -19,8 +19,8 @@
package appeng.util.item; package appeng.util.item;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -106,15 +106,23 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return item; 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(); final byte mask = data.readByte();
// byte PriorityType = (byte) (mask & 0x03);
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 ); final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 ); final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0; final boolean isCraftable = ( mask & 0x40 ) > 0;
final ItemStack itemstack = ByteBufUtils.readItemStack( data ); final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) );
final long stackSize = getPacketValue( stackType, data ); final long stackSize = getPacketValue( stackType, data );
final long countRequestable = getPacketValue( countReqType, data ); final long countRequestable = getPacketValue( countReqType, data );
@@ -123,13 +131,24 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return null; return null;
} }
final AEItemStack item = AEItemStack.fromItemStack( itemstack ); final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize );
item.setStackSize( stackSize );
item.setCountRequestable( countRequestable ); item.setCountRequestable( countRequestable );
item.setCraftable( isCraftable ); item.setCraftable( isCraftable );
return item; 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 @Override
public void add( final IAEItemStack option ) public void add( final IAEItemStack option )
{ {
@@ -143,140 +162,35 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
this.setCraftable( this.isCraftable() || option.isCraftable() ); 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 @Override
public boolean fuzzyComparison( final Object st, final FuzzyMode mode ) public boolean fuzzyComparison( final Object st, final FuzzyMode mode )
{ {
if( st instanceof IAEItemStack ) if( st instanceof IAEItemStack )
{ {
final IAEItemStack o = (IAEItemStack) st; final IAEItemStack other = (IAEItemStack) st;
if( this.sameOre( o ) ) if( OreHelper.INSTANCE.sameOre( this, other ) )
{ {
return true; return true;
} }
if( o.getItem() == this.getItem() ) final ItemStack itemStack = this.getDefinition();
{ final ItemStack otherStack = other.getDefinition();
if( this.getDefinition().getItem().isDamageable() )
{
final ItemStack a = this.getDefinition();
final ItemStack b = o.getDefinition();
try return this.fuzzyItemStackComparison( itemStack, otherStack, mode );
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
final Item ai = a.getItem();
final Item bi = b.getItem();
return ( ai.getDurabilityForDisplay( a ) < 0.001f ) == ( bi.getDurabilityForDisplay( b ) < 0.001f );
}
else
{
final Item ai = a.getItem();
final Item bi = b.getItem();
final float percentDamageOfA = 1.0f - (float) ai.getDurabilityForDisplay( a );
final float percentDamageOfB = 1.0f - (float) bi.getDurabilityForDisplay( b );
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
catch( final Throwable e )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
}
else
{
final float percentDamageOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamageOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
}
return this.getItemDamage() == o.getItemDamage();
}
} }
if( st instanceof ItemStack ) if( st instanceof IAEItemStack )
{ {
final ItemStack o = (ItemStack) st; final ItemStack otherStack = (ItemStack) st;
OreHelper.INSTANCE.sameOre( this, o ); if( OreHelper.INSTANCE.sameOre( this, otherStack ) )
if( o.getItem() == this.getItem() )
{ {
if( this.getDefinition().getItem().isDamageable() ) return true;
{
final ItemStack a = this.getDefinition();
try
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
final Item ai = a.getItem();
final Item bi = o.getItem();
return ( ai.getDurabilityForDisplay( a ) < 0.001f ) == ( bi.getDurabilityForDisplay( o ) < 0.001f );
}
else
{
final Item ai = a.getItem();
final Item bi = o.getItem();
final float percentDamageOfA = 1.0f - (float) ai.getDurabilityForDisplay( a );
final float percentDamageOfB = 1.0f - (float) bi.getDurabilityForDisplay( o );
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
catch( final Throwable e )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
return ( a.getItemDamage() > 1 ) == ( o.getItemDamage() > 1 );
}
else
{
final float percentDamageOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamageOfB = (float) o.getItemDamage() / (float) o.getMaxDamage();
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
}
return this.getItemDamage() == o.getItemDamage();
} }
final ItemStack itemStack = this.getDefinition();
return this.fuzzyItemStackComparison( itemStack, otherStack, mode );
} }
return false; return false;
@@ -338,7 +252,7 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return false; return false;
} }
return this.sharedStack == ( (AEItemStack) otherStack ).sharedStack; return Objects.equals( this.sharedStack, ( (AEItemStack) otherStack ).sharedStack );
} }
@Override @Override
@@ -424,12 +338,6 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return this.oreReference; return this.oreReference;
} }
@Override
protected void writeToStream( final ByteBuf data ) throws IOException
{
ByteBufUtils.writeItemStack( data, this.getDefinition() );
}
@Override @Override
public boolean hasTagCompound() public boolean hasTagCompound()
{ {
@@ -453,4 +361,33 @@ public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemS
return this.sharedStack; return this.sharedStack;
} }
private boolean fuzzyItemStackComparison( ItemStack a, ItemStack b, FuzzyMode mode )
{
if( a.getItem() == b.getItem() )
{
if( a.getItem().isDamageable() )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
}
else
{
final float percentDamageOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamageOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( percentDamageOfA > mode.breakPoint ) == ( percentDamageOfB > mode.breakPoint );
}
}
return a.getMetadata() == b.getMetadata();
}
return false;
}
} }
@@ -31,15 +31,30 @@ import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import appeng.util.Platform;
public final class AEItemStackRegistry 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 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 ) static synchronized AESharedItemStack getRegisteredStack( final @Nonnull ItemStack itemStack )
{ {
if( itemStack.isEmpty() ) if( itemStack.isEmpty() )
@@ -51,7 +66,7 @@ public final class AEItemStackRegistry
itemStack.setCount( 1 ); itemStack.setCount( 1 );
AESharedItemStack search = new AESharedItemStack( itemStack ); AESharedItemStack search = new AESharedItemStack( itemStack );
WeakReference<AESharedItemStack> weak = REGISTRY.get( search ); WeakReference<AESharedItemStack> weak = registry().get( search );
AESharedItemStack ret = null; AESharedItemStack ret = null;
if( weak != null ) if( weak != null )
@@ -62,7 +77,7 @@ public final class AEItemStackRegistry
if( ret == null ) if( ret == null )
{ {
ret = new AESharedItemStack( itemStack.copy() ); ret = new AESharedItemStack( itemStack.copy() );
REGISTRY.put( ret, new WeakReference<>( ret ) ); registry().put( ret, new WeakReference<>( ret ) );
} }
itemStack.setCount( oldStackSize ); itemStack.setCount( oldStackSize );
@@ -56,6 +56,11 @@ final class AESharedItemStack implements Comparable<AESharedItemStack>
return this.itemDamage; return this.itemDamage;
} }
int getItemID()
{
return this.itemId;
}
@Override @Override
public int hashCode() public int hashCode()
{ {
@@ -104,7 +109,17 @@ final class AESharedItemStack implements Comparable<AESharedItemStack>
return damageValue; 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 ) private int compareNBT( final ItemStack b )
@@ -149,7 +164,7 @@ final class AESharedItemStack implements Comparable<AESharedItemStack>
} }
else else
{ {
newDef.setItemDamage( 0 ); newDef.setItemDamage( 1 );
} }
} }
else else
+2 -20
View File
@@ -19,8 +19,6 @@
package appeng.util.item; package appeng.util.item;
import java.io.IOException;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IAEStack;
@@ -144,23 +142,7 @@ public abstract class AEStack<StackType extends IAEStack<StackType>> implements
this.countRequestable -= i; this.countRequestable -= i;
} }
@Override protected byte getType( final long num )
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 )
{ {
if( num <= 255 ) if( num <= 255 )
{ {
@@ -182,7 +164,7 @@ public abstract class AEStack<StackType extends IAEStack<StackType>> implements
abstract boolean hasTagCompound(); abstract boolean hasTagCompound();
private void putPacketValue( final ByteBuf tag, final long num ) protected void putPacketValue( final ByteBuf tag, final long num )
{ {
if( num <= 255 ) if( num <= 255 )
{ {
@@ -1,10 +1,15 @@
{ {
"display": { "display": {
"icon": { "icon": {
"item": "appliedenergistics2:part", "data": 16 "item": "appliedenergistics2:part",
}, "data": 16
"title": { "translate": "achievement.ae2.GlassCable" }, },
"description": { "translate": "achievement.ae2.GlassCable.desc" } "title": {
"translate": "achievement.ae2.GlassCable"
},
"description": {
"translate": "achievement.ae2.GlassCable.desc"
}
}, },
"parent": "appliedenergistics2:main/fluix", "parent": "appliedenergistics2:main/fluix",
"criteria": { "criteria": {
@@ -13,11 +18,11 @@
"conditions": { "conditions": {
"items": [ "items": [
{ {
"type": "appliedenergistics2:part", "type": "appliedenergistics2:part",
"part": "CABLE_GLASS" "part": "CABLE_GLASS"
} }
] ]
} }
} }
} }
} }

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