Compare commits

...

40 Commits

Author SHA1 Message Date
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
104 changed files with 2433 additions and 1276 deletions
+52
View File
@@ -14,6 +14,7 @@
* [Building](#building)
* [Contribution](#contribution)
* [API](#applied-energistics-2-api)
* [CraftTweaker](#applied-energistics-2-crafttweaker)
* [Localization](#applied-energistics-2-localization)
* [Credits](#credits)
@@ -154,6 +155,57 @@ Where the __ are filled in with the correct version criteria; AE2 is available f
An example string would be `appeng:appliedenergistics2:rv2-alpha-30:dev`
## Applied Energistics 2 CraftTweaker
### Inscriber
Add a recipe. When `inscribe` is true the bottom and top inputs are not consumed.
mods.appliedenergistics2.Inscriber.addRecipe(ItemStack output, ItemStack input, boolean inscribe,
@Optional ItemStack topInput, @Optional ItemStack bottomInput );
Remove all recipes for this output stack.
mods.appliedenergistics2.Inscriber.removeRecipe(ItemStack output);
### Grindstone
Add a recipe.
mods.appliedenergistics2.Grinder.addRecipe( ItemStack output, ItemStack input, int turns,
@Optional ItemStack secondary1Output, @Optional float secondary1Chance,
@Optional ItemStack secondary2Output, @Optional float secondary2Chance);
Remove recipes for this input.
mods.appliedenergistics2.Grinder.removeRecipe(ItemStack input);
### Spatial
Whitelist a TileEntity class for Spatial IO.
mods.appliedenergistics2.Spatial.whitelistEntity( String fullEntityClassName );
### Attunement
Attune a ItemStack or ModID to a specific P2P-Tunnel type. ModID's are used as fallback when no ItemStack was found.
mods.appliedenergistics2.Attunement.attuneME( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneME( String modID );
mods.appliedenergistics2.Attunement.attuneItem( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneItem( String modID );
mods.appliedenergistics2.Attunement.attuneFluid( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneFluid( String modID );
mods.appliedenergistics2.Attunement.attuneRedstone( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneRedstone( String modID );
mods.appliedenergistics2.Attunement.attuneRF( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneRF( String modID );
mods.appliedenergistics2.Attunement.attuneIC2( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneIC2( String modID );
mods.appliedenergistics2.Attunement.attuneLight( ItemStack itemStack );
mods.appliedenergistics2.Attunement.attuneLight( String modID );
### Cannon
Add ammo types for the matter cannon.
mods.appliedenergistics2.Cannon.registerAmmo( ItemStack itemStack, double weight );
## Applied Energistics 2 Localization
### English Text
+2 -1
View File
@@ -9,7 +9,7 @@ aebasename=appliedenergistics2
#########################################################
minecraft_version=1.12.2
mcp_mappings=snapshot_20171003
forge_version=14.23.0.2491
forge_version=14.23.1.2554
#########################################################
# Installable #
@@ -24,6 +24,7 @@ tesla_version=1.0.61
ic2_version=2.8.19-ex112
top_version=1.12-1.4.18-10
cofhcore_version=1.12-4.+
crafttweaker_version=4.0.10.310
#########################################################
# Deployment #
+6
View File
@@ -58,6 +58,11 @@ repositories {
name 'tehnut'
url "http://tehnut.info/maven"
}
maven { // CraftTweaker
name 'jared maven'
url "http://maven.blamejared.com/"
}
}
configurations {
@@ -77,6 +82,7 @@ dependencies {
compileOnly "net.industrial-craft:industrialcraft-2:${ic2_version}:api"
compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api"
compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf"
compileOnly "CraftTweaker2:CraftTweaker2-API:${crafttweaker_version}"
// at runtime, use the full JEI jar
runtime "mezz.jei:jei_${minecraft_version}:${jei_version}"
@@ -28,6 +28,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.capabilities.Capability;
import appeng.api.config.TunnelType;
@@ -47,6 +48,7 @@ public interface IP2PTunnelRegistry
*/
void addNewAttunement( @Nonnull ItemStack trigger, @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.
@@ -48,6 +48,7 @@ public interface IRecipeHandlerRegistry
* @param name name of crafthandler
* @param handler class of crafthandler
*/
@Deprecated
void addNewCraftHandler( String name, Class<? extends ICraftHandler> handler );
/**
@@ -65,11 +66,13 @@ public interface IRecipeHandlerRegistry
* @return A recipe handler by name, returns null on failure.
*/
@Nullable
@Deprecated
ICraftHandler getCraftHandlerFor( String name );
/**
* @return a new recipe handler, which can be used to parse, and read recipe files.
*/
@Deprecated
IRecipeHandler createNewRecipehandler();
/**
@@ -30,7 +30,7 @@ import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RecipeException;
import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface ICraftHandler
{
@@ -29,7 +29,7 @@ import net.minecraft.item.ItemStack;
import appeng.api.exceptions.MissingIngredientException;
import appeng.api.exceptions.RegistrationException;
@Deprecated
public interface IIngredient
{
@@ -27,6 +27,7 @@ package appeng.api.recipes;
/**
* Represents the AE2 Recipe Loading/Reading Class
*/
@Deprecated
public interface IRecipeHandler
{
@@ -28,7 +28,7 @@ import java.io.BufferedReader;
import javax.annotation.Nonnull;
@Deprecated
public interface IRecipeLoader
{
/**
@@ -43,6 +43,19 @@ import appeng.api.storage.data.IItemList;
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.
*
@@ -23,6 +23,7 @@ import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
@@ -32,6 +33,7 @@ import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
@@ -164,4 +166,16 @@ public class BlockCrank extends AEBaseTileBlock
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;
}
}
@@ -23,7 +23,6 @@ import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
@@ -43,70 +42,17 @@ public abstract class AEBaseMEGui extends AEBaseGui
super( container );
}
public List<String> handleItemTooltip( final ItemStack stack, final int mouseX, final int mouseY, final List<String> currentToolTip )
{
if( !stack.isEmpty() )
{
final Slot s = this.getSlot( mouseX, mouseY );
if( s instanceof SlotME )
{
final int BigNumber = AEConfig.instance().useTerminalUseLargeFont() ? 999 : 9999;
IAEItemStack myStack = null;
try
{
final SlotME theSlotField = (SlotME) s;
myStack = theSlotField.getAEStack();
}
catch( final Throwable ignore )
{
}
if( myStack != null )
{
if( myStack.getStackSize() > BigNumber || ( myStack.getStackSize() > 1 && stack.isItemDamaged() ) )
{
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
if( myStack.getCountRequestable() > 0 )
{
final String local = ButtonToolTips.ItemsRequestable.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
}
else if( stack.getCount() > BigNumber || ( stack.getCount() > 1 && stack.isItemDamaged() ) )
{
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
}
}
return currentToolTip;
}
// Vanilla version...
// protected void drawItemStackTooltip(ItemStack stack, int x, int y)
@Override
protected void renderToolTip( final ItemStack stack, final int x, final int y )
{
final Slot s = this.getSlot( x, y );
if( s instanceof SlotME && !stack.isEmpty() )
{
final int BigNumber = AEConfig.instance().useTerminalUseLargeFont() ? 999 : 9999;
final int bigNumber = AEConfig.instance().useTerminalUseLargeFont() ? 999 : 9999;
IAEItemStack myStack = null;
final List<String> currentToolTip = this.getItemToolTip( stack );
try
{
@@ -117,33 +63,44 @@ public abstract class AEBaseMEGui extends AEBaseGui
{
}
ITooltipFlag.TooltipFlags tooltipFlag = this.mc.gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL;
if( myStack != null )
{
final List<String> currentToolTip = stack.getTooltip( this.mc.player, tooltipFlag );
if( myStack.getStackSize() > BigNumber || ( myStack.getStackSize() > 1 && stack.isItemDamaged() ) )
if( myStack.getStackSize() > bigNumber || ( myStack.getStackSize() > 1 && stack.isItemDamaged() ) )
{
currentToolTip.add( "Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() ) );
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getStackSize() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
}
if( myStack.getCountRequestable() > 0 )
{
currentToolTip.add( "Items Requestable: " + NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() ) );
final String local = ButtonToolTips.ItemsRequestable.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( myStack.getCountRequestable() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( format );
}
this.drawTooltip( x, y, currentToolTip );
this.drawHoveringText( currentToolTip, x, y, this.fontRenderer );
return;
}
else if( stack.getCount() > BigNumber )
else if( stack.getCount() > bigNumber )
{
List<String> var4 = stack.getTooltip( this.mc.player, tooltipFlag );
var4.add( "Items Stored: " + NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() ) );
this.drawTooltip( x, y, var4 );
final String local = ButtonToolTips.ItemsStored.getLocal();
final String formattedAmount = NumberFormat.getNumberInstance( Locale.US ).format( stack.getCount() );
final String format = String.format( local, formattedAmount );
currentToolTip.add( TextFormatting.GRAY + format );
this.drawHoveringText( currentToolTip, x, y, this.fontRenderer );
return;
}
}
super.renderToolTip( stack, x, y );
// super.drawItemStackTooltip( stack, x, y );
}
}
@@ -237,10 +237,11 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource
this.getScrollBar().setRange( 0, ( size + 4 ) / 5 - this.rows, 1 );
}
// Vanilla version...
protected void drawItemStackTooltip( final ItemStack stack, final int x, final int y )
@Override
protected void renderToolTip( final ItemStack stack, final int x, final int y )
{
final Slot s = this.getSlot( x, y );
if( s instanceof SlotME && stack != null )
{
IAEItemStack myStack = null;
@@ -270,7 +271,8 @@ public class GuiNetworkStatus extends AEBaseGui implements ISortSource
this.drawTooltip( x, y, currentToolTip );
}
}
// super.drawItemStackTooltip( stack, x, y );
super.renderToolTip( stack, x, y );
}
@Override
@@ -92,7 +92,7 @@ public class GuiSpatialIOPort extends AEBaseGui
}
else
{
this.fontRenderer.drawString( GuiText.SCSSize.getLocal() + ": " + GuiText.SCSSInvalid.getLocal(), 13, 93, 4210752 );
this.fontRenderer.drawString( GuiText.SCSSize.getLocal() + ": " + GuiText.SCSInvalid.getLocal(), 13, 93, 4210752 );
}
}
@@ -120,28 +120,23 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
if( s == this.middle )
{
for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() )
IItemDefinition press = AEApi.instance().definitions().materials().namePress();
if( press.isSameAs( top ) || press.isSameAs( bot ) )
{
if( Platform.itemComparisons().isSameItem( optional, is ) )
{
return false;
}
return !press.isSameAs( is );
}
boolean matches = false;
boolean found = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() )
{
final boolean matchA = ( top.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top,
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and...
( ( bot.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot,
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) );
final boolean matchB = ( bot.isEmpty() && !recipe.getTopOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( bot,
recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) ) && // and...
( ( top.isEmpty() && !recipe.getBottomOptional().isPresent() ) || ( Platform.itemComparisons().isSameItem( top,
recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) ) );
final boolean matchA = !top
.isEmpty() && ( Platform.itemComparisons().isSameItem( top, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
.itemComparisons()
.isSameItem( top, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
final boolean matchB = !bot
.isEmpty() && ( Platform.itemComparisons().isSameItem( bot, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) || Platform
.itemComparisons()
.isSameItem( bot, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) );
if( matchA || matchB )
{
@@ -150,21 +145,19 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
{
if( Platform.itemComparisons().isSameItem( is, option ) )
{
found = true;
return true;
}
}
}
}
if( matches && !found )
if( matches )
{
return false;
}
}
if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
else if( ( s == this.top && !bot.isEmpty() ) || ( s == this.bottom && !top.isEmpty() ) )
{
ItemStack otherSlot = ItemStack.EMPTY;
ItemStack otherSlot;
if( s == this.top )
{
otherSlot = this.bottom.getStack();
@@ -182,28 +175,24 @@ public class ContainerInscriber extends ContainerUpgradeable implements IProgres
}
// everything else
boolean isValid = false;
for( final IInscriberRecipe recipe : AEApi.instance().registries().inscriber().getRecipes() )
{
if( Platform.itemComparisons().isSameItem( recipe.getTopOptional().orElse( ItemStack.EMPTY ), otherSlot ) )
boolean isValid = false;
if( Platform.itemComparisons().isSameItem( otherSlot, recipe.getTopOptional().orElse( ItemStack.EMPTY ) ) )
{
isValid = Platform.itemComparisons().isSameItem( is, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) );
}
else if( Platform.itemComparisons().isSameItem( recipe.getBottomOptional().orElse( ItemStack.EMPTY ), otherSlot ) )
else if( Platform.itemComparisons().isSameItem( otherSlot, recipe.getBottomOptional().orElse( ItemStack.EMPTY ) ) )
{
isValid = Platform.itemComparisons().isSameItem( is, recipe.getTopOptional().orElse( ItemStack.EMPTY ) );
}
if( isValid )
{
break;
return true;
}
}
if( !isValid )
{
return false;
}
return false;
}
return true;
@@ -172,7 +172,7 @@ public class SlotRestrictedInput extends AppEngSlot
for( final ItemStack optional : AEApi.instance().registries().inscriber().getOptionals() )
{
if( Platform.itemComparisons().isSameItem( optional, i ) )
if( Platform.itemComparisons().isSameItem( i, optional ) )
{
return true;
}
+2
View File
@@ -189,6 +189,8 @@ public final class AppEng
AppEng.proxy.preinit();
}
IntegrationRegistry.INSTANCE.preInit();
if( versionCheckerConfig.isVersionCheckingEnabled() )
{
final VersionChecker versionChecker = new VersionChecker( versionCheckerConfig );
+1 -1
View File
@@ -59,7 +59,7 @@ public class ApiGrid implements IGridHelper
Preconditions.checkNotNull( a );
Preconditions.checkNotNull( b );
return new GridConnection( a, b, AEPartLocation.INTERNAL );
return GridConnection.create( a, b, AEPartLocation.INTERNAL );
}
}
@@ -160,6 +160,12 @@ public class ApiStorage implements IStorageHelper
private static final class FluidStorageChannel implements IFluidStorageChannel
{
@Override
public int transferFactor()
{
return 1000;
}
@Override
public IItemList<IAEFluidStack> createList()
{
@@ -195,7 +201,7 @@ public class ApiStorage implements IStorageHelper
Preconditions.checkNotNull( request );
Preconditions.checkNotNull( src );
return null;
return Platform.poweredExtraction( energy, cell, request, src );
}
@Override
@@ -206,7 +212,7 @@ public class ApiStorage implements IStorageHelper
Preconditions.checkNotNull( input );
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.debug.BlockChunkloader;
import appeng.debug.BlockCubeGenerator;
import appeng.debug.BlockEnergyGenerator;
import appeng.debug.BlockItemGen;
import appeng.debug.BlockPhantomNode;
import appeng.debug.TileChunkLoader;
import appeng.debug.TileCubeGenerator;
import appeng.debug.TileEnergyGenerator;
import appeng.debug.TileItemGen;
import appeng.debug.TilePhantomNode;
import appeng.decorative.slab.BlockSlabCommon;
@@ -236,6 +238,7 @@ public final class ApiBlocks implements IBlocks
private final IBlockDefinition chunkLoader;
private final IBlockDefinition phantomNode;
private final IBlockDefinition cubeGenerator;
private final IBlockDefinition energyGenerator;
public ApiBlocks( FeatureFactory registry, PartModels partModels )
{
@@ -526,6 +529,11 @@ public final class ApiBlocks implements IBlocks
.tileEntity( new TileEntityDefinition( TileCubeGenerator.class ) )
.useCustomItemModel()
.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 )
@@ -1014,4 +1022,9 @@ public final class ApiBlocks implements IBlocks
{
return this.cubeGenerator;
}
public IBlockDefinition energyGenerator()
{
return energyGenerator;
}
}
@@ -21,6 +21,7 @@ package appeng.core.features.registries;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -30,6 +31,8 @@ import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.oredict.OreDictionary;
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<String, TunnelType> modIdTunnels = new HashMap<>( INITIAL_CAPACITY );
private final Map<Capability<?>, TunnelType> capTunnels = new HashMap<>( INITIAL_CAPACITY );
public void configure()
{
@@ -159,6 +163,12 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
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
*/
@@ -186,6 +196,16 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
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
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( FluidRegistry.isContainer( trigger ) )
// {
// return TunnelType.FLUID;
// }
for( final ItemStack is : this.tunnels.keySet() )
// First match exact items
for( final Entry<ItemStack, TunnelType> entry : this.tunnels.entrySet() )
{
final ItemStack is = entry.getKey();
if( is.getItem() == trigger.getItem() && is.getItemDamage() == OreDictionary.WILDCARD_VALUE )
{
return this.tunnels.get( is );
return entry.getValue();
}
if( ItemStack.areItemsEqual( is, trigger ) )
{
return this.tunnels.get( is );
return entry.getValue();
}
}
// Try by ModId next
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
// Next, check if the Item you're holding supports any registered capability
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,
Efficiency,
SCSSize,
SCSSInvalid,
SCSInvalid,
InWorldCrafting,
inWorldFluix,
@@ -47,7 +47,7 @@ public enum TickRates
ItemTunnel( 5, 60 ),
LightTunnel( 5, 120 ),
LightTunnel( 5, 60 ),
OpenComputersTunnel( 1, 5 ),
@@ -41,6 +41,7 @@ import appeng.api.config.Actionable;
import appeng.api.config.SecurityPermissions;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.storage.IStorageGrid;
@@ -132,6 +133,7 @@ public class PacketJEIRecipe extends AppEngPacket
final IStorageGrid inv = grid.getCache( IStorageGrid.class );
final IEnergyGrid energy = grid.getCache( IEnergyGrid.class );
final ISecurityGrid security = grid.getCache( ISecurityGrid.class );
final ICraftingGrid crafting = grid.getCache( ICraftingGrid.class );
final IItemHandler craftMatrix = cct.getInventoryByName( "crafting" );
final IItemHandler playerInventory = cct.getInventoryByName( "player" );
@@ -179,13 +181,23 @@ public class PacketJEIRecipe extends AppEngPacket
{
request.setStackSize( 1 );
IAEItemStack out;
if( cct.useRealItems() )
{
out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() );
}
else
{
out = storage.extractItems( request, Actionable.SIMULATE, cct.getActionSource() );
// Query the crafting grid if there is a pattern providing the item
if( !crafting.getCraftingFor( request, null, 0, null ).isEmpty() )
{
out = request;
}
else
{
// Fall back using an existing item
out = storage.extractItems( request, Actionable.SIMULATE, cct.getActionSource() );
}
}
if( out != null )
@@ -363,7 +363,7 @@ public class CraftingTreeNode
if( this.howManyEmitted > 0 )
{
final IAEItemStack i = this.what.copy();
final IAEItemStack i = this.what.copy().reset();
i.setStackSize( this.howManyEmitted );
craftingCPUCluster.addEmitable( i );
}
@@ -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;
import java.util.List;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.Block;
@@ -136,19 +138,20 @@ public final class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntit
return;
}
for( final Object e : this.world.getEntitiesWithinAABBExcludingEntity( this,
new AxisAlignedBB( this.posX - 1.5, this.posY - 1.5f, this.posZ - 1.5, this.posX + 1.5, this.posY + 1.5, this.posZ + 1.5 ) ) )
final Explosion ex = new Explosion( this.world, this, this.posX, this.posY, this.posZ, 0.2f, false, false );
final AxisAlignedBB area = new AxisAlignedBB( this.posX - 1.5, this.posY - 1.5f, this.posZ - 1.5, this.posX + 1.5, this.posY + 1.5, this.posZ + 1.5 );
final List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity( this, area );
net.minecraftforge.event.ForgeEventFactory.onExplosionDetonate( this.world, ex, list, 0.2f * 2d );
for( final Entity e : list )
{
if( e instanceof Entity )
{
( (Entity) e ).attackEntityFrom( DamageSource.causeExplosionDamage( (Explosion) null ), 6 );
}
e.attackEntityFrom( DamageSource.causeExplosionDamage( ex ), 6 );
}
if( AEConfig.instance().isFeatureEnabled( AEFeature.TINY_TNT_BLOCK_DAMAGE ) )
{
this.posY -= 0.25;
final Explosion ex = new Explosion( this.world, this, this.posX, this.posY, this.posZ, 0.2f, false, false );
for( int x = (int) ( this.posX - 2 ); x <= this.posX + 2; x++ )
{
@@ -159,6 +162,7 @@ public final class EntityTinyTNTPrimed extends EntityTNTPrimed implements IEntit
final BlockPos point = new BlockPos( x, y, z );
final IBlockState state = this.world.getBlockState( point );
final Block block = state.getBlock();
if( block != null && !block.isAir( state, this.world, point ) )
{
float strength = (float) ( 2.3f - ( ( ( x + 0.5f ) - this.posX ) * ( ( x + 0.5f ) - this.posX ) + ( ( y + 0.5f ) - this.posY ) * ( ( y + 0.5f ) - this.posY ) + ( ( z + 0.5f ) - this.posZ ) * ( ( z + 0.5f ) - this.posZ ) ) );
@@ -47,13 +47,16 @@ public enum IntegrationRegistry
this.modules.add( new IntegrationNode( type.dspName, type.modID, type ) );
}
public void init()
public void preInit()
{
for( final IntegrationNode node : this.modules )
{
node.call( IntegrationStage.PRE_INIT );
}
}
public void init()
{
for( final IntegrationNode node : this.modules )
{
node.call( IntegrationStage.INIT );
@@ -19,6 +19,7 @@
package appeng.integration;
import appeng.integration.modules.crafttweaker.CTModule;
import appeng.integration.modules.ic2.IC2Module;
import appeng.integration.modules.jei.JEIModule;
import appeng.integration.modules.theoneprobe.TheOneProbeModule;
@@ -73,7 +74,16 @@ public enum IntegrationType
}
},
TESLA( IntegrationSide.BOTH, "Tesla", "tesla" );
TESLA( IntegrationSide.BOTH, "Tesla", "tesla" ),
CRAFTTWEAKER( IntegrationSide.BOTH, "CraftTweaker", "crafttweaker" )
{
@Override
public IIntegrationModule createInstance()
{
return new CTModule();
}
};
public final IntegrationSide side;
public final String dspName;
@@ -0,0 +1,28 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.abstraction;
import appeng.integration.IIntegrationModule;
public interface ICraftTweaker extends IIntegrationModule
{
}
@@ -0,0 +1,132 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import crafttweaker.api.item.IIngredient;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.config.TunnelType;
import appeng.api.features.IP2PTunnelRegistry;
@ZenClass( "mods.appliedenergistics2.Attunement" )
public class AttunementRegistry
{
private AttunementRegistry()
{
}
@ZenMethod
public static void attuneME( IIngredient itemStack )
{
attune( itemStack, TunnelType.ME );
}
@ZenMethod
public static void attuneME( String modId )
{
attune( modId, TunnelType.ME );
}
@ZenMethod
public static void attuneItem( IIngredient itemStack )
{
attune( itemStack, TunnelType.ITEM );
}
@ZenMethod
public static void attuneItem( String modId )
{
attune( modId, TunnelType.ITEM );
}
@ZenMethod
public static void attuneFluid( IIngredient itemStack )
{
attune( itemStack, TunnelType.FLUID );
}
@ZenMethod
public static void attuneFluid( String modId )
{
attune( modId, TunnelType.FLUID );
}
@ZenMethod
public static void attuneRedstone( IIngredient itemStack )
{
attune( itemStack, TunnelType.REDSTONE );
}
@ZenMethod
public static void attuneRedstone( String modId )
{
attune( modId, TunnelType.REDSTONE );
}
@ZenMethod
public static void attuneRF( IIngredient itemStack )
{
attune( itemStack, TunnelType.FE_POWER );
}
@ZenMethod
public static void attuneRF( String modId )
{
attune( modId, TunnelType.FE_POWER );
}
@ZenMethod
public static void attuneIC2( IIngredient itemStack )
{
attune( itemStack, TunnelType.IC2_POWER );
}
@ZenMethod
public static void attuneIC2( String modId )
{
attune( modId, TunnelType.IC2_POWER );
}
@ZenMethod
public static void attuneLight( IIngredient itemStack )
{
attune( itemStack, TunnelType.LIGHT );
}
@ZenMethod
public static void attuneLight( String modId )
{
attune( modId, TunnelType.LIGHT );
}
private static void attune( IIngredient itemStack, TunnelType type )
{
IP2PTunnelRegistry registry = AEApi.instance().registries().p2pTunnel();
CTModule.toStacks( itemStack ).ifPresent( c -> c.forEach( i -> registry.addNewAttunement( i, type ) ) );
}
private static void attune( String modid, TunnelType type )
{
AEApi.instance().registries().p2pTunnel().addNewAttunement( modid, type );
}
}
@@ -0,0 +1,130 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraftforge.oredict.OreDictionary;
import crafttweaker.CraftTweakerAPI;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import appeng.integration.abstraction.ICraftTweaker;
import appeng.util.Platform;
public class CTModule implements ICraftTweaker
{
static final List<IAction> MODIFICATIONS = new ArrayList<>();
@Override
public void preInit()
{
CraftTweakerAPI.registerClass( GrinderRecipes.class );
CraftTweakerAPI.registerClass( InscriberRecipes.class );
CraftTweakerAPI.registerClass( SpatialRegistry.class );
CraftTweakerAPI.registerClass( AttunementRegistry.class );
CraftTweakerAPI.registerClass( CannonRegistry.class );
}
@Override
public void postInit()
{
MODIFICATIONS.forEach( CraftTweakerAPI::apply );
}
public static ItemStack toStack( IItemStack iStack )
{
if( iStack == null )
{
return ItemStack.EMPTY;
}
else
{
return (ItemStack) iStack.getInternal();
}
}
public static List<ItemStack> toStackExpand( IItemStack iStack )
{
if( iStack == null )
{
return Collections.emptyList();
}
else
{
ItemStack is = (ItemStack) iStack.getInternal();
if( !is.isItemStackDamageable() && is.getItemDamage() == OreDictionary.WILDCARD_VALUE )
{
NonNullList<ItemStack> ret = NonNullList.create();
is.getItem().getSubItems( CreativeTabs.SEARCH, ret );
return ret.stream().map( i -> new ItemStack( i.getItem(), iStack.getAmount(), i.getItemDamage() ) ).collect( Collectors.toList() );
}
else
{
return Collections.singletonList( is );
}
}
}
public static Optional<Collection<ItemStack>> toStacks( IIngredient ingredient )
{
if( ingredient == null )
{
return Optional.empty();
}
Set<ItemStack> ret = new TreeSet<>( CTModule::compareItemStacks );
ingredient.getItems().stream().map( CTModule::toStackExpand ).forEach( ret::addAll );
if( ret.isEmpty() )
{
return Optional.empty();
}
return Optional.of( ret );
}
private static int compareItemStacks( ItemStack a, ItemStack b )
{
if( Platform.itemComparisons().isSameItem( a, b ) )
{
return 0;
}
if( a == null )
{
return -1;
}
if( b == null )
{
return 1;
}
return System.identityHashCode( a ) - System.identityHashCode( b );
}
}
@@ -0,0 +1,43 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import crafttweaker.api.item.IIngredient;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IMatterCannonAmmoRegistry;
@ZenClass( "mods.appliedenergistics2.Cannon" )
public class CannonRegistry
{
private CannonRegistry()
{
}
@ZenMethod
public static void registerAmmo( IIngredient itemStack, double weight )
{
IMatterCannonAmmoRegistry registry = AEApi.instance().registries().matterCannon();
CTModule.toStacks( itemStack ).ifPresent( c -> c.forEach( i -> registry.registerAmmo( i, weight ) ) );
}
}
@@ -0,0 +1,127 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import java.util.Collection;
import java.util.Collections;
import net.minecraft.item.ItemStack;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IGrinderRecipe;
import appeng.api.features.IGrinderRecipeBuilder;
@ZenClass( "mods.appliedenergistics2.Grinder" )
public class GrinderRecipes
{
private GrinderRecipes()
{
}
@ZenMethod
public static void addRecipe( IItemStack output, IIngredient input, int turns, @stanhebben.zenscript.annotations.Optional IItemStack secondary1Output, @stanhebben.zenscript.annotations.Optional Float secondary1Chance, @stanhebben.zenscript.annotations.Optional IItemStack secondary2Output, @stanhebben.zenscript.annotations.Optional Float secondary2Chance )
{
Collection<ItemStack> inStacks = CTModule.toStacks( input ).orElse( Collections.emptySet() );
for( ItemStack inStack : inStacks )
{
IGrinderRecipeBuilder builder = AEApi.instance().registries().grinder().builder();
builder.withInput( inStack )
.withOutput( CTModule.toStack( output ) )
.withTurns( turns );
final ItemStack s1 = CTModule.toStack( secondary1Output );
if( !s1.isEmpty() )
{
builder.withFirstOptional( s1, secondary1Chance == null ? 1.0f : secondary1Chance );
}
final ItemStack s2 = CTModule.toStack( secondary2Output );
if( !s2.isEmpty() )
{
builder.withFirstOptional( s2, secondary2Chance == null ? 1.0f : secondary2Chance );
}
CTModule.MODIFICATIONS.add( new Add( builder.build() ) );
}
}
@ZenMethod
public static void removeRecipe( IIngredient input )
{
for( ItemStack inStack : CTModule.toStacks( input ).orElse( Collections.emptySet() ) )
{
CTModule.MODIFICATIONS.add( new Remove( inStack ) );
}
}
private static class Add implements IAction
{
private final IGrinderRecipe entry;
private Add( IGrinderRecipe entry )
{
this.entry = entry;
}
@Override
public void apply()
{
AEApi.instance().registries().grinder().addRecipe( entry );
}
@Override
public String describe()
{
return "Adding Grinder Entry for " + entry.getInput().getDisplayName();
}
}
private static class Remove implements IAction
{
private final ItemStack stack;
private Remove( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
IGrinderRecipe recipe = AEApi.instance().registries().grinder().getRecipeForInput( stack );
if( recipe != null )
{
AEApi.instance().registries().grinder().removeRecipe( recipe );
}
}
@Override
public String describe()
{
return "Removing Grinder Entry for " + stack.getDisplayName();
}
}
}
@@ -0,0 +1,138 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Collectors;
import net.minecraft.item.ItemStack;
import crafttweaker.IAction;
import crafttweaker.api.item.IIngredient;
import crafttweaker.api.item.IItemStack;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.api.features.IInscriberRecipe;
import appeng.api.features.IInscriberRecipeBuilder;
import appeng.api.features.IInscriberRegistry;
import appeng.api.features.InscriberProcessType;
@ZenClass( "mods.appliedenergistics2.Inscriber" )
public class InscriberRecipes
{
private InscriberRecipes()
{
}
@ZenMethod
public static void addRecipe( IItemStack output, IIngredient input, boolean inscribe, @stanhebben.zenscript.annotations.Optional IIngredient top, @stanhebben.zenscript.annotations.Optional IIngredient bottom )
{
Optional<Collection<ItemStack>> inStacks = CTModule.toStacks( input );
if( !inStacks.isPresent() )
{
return;
}
Collection<ItemStack> topList = CTModule.toStacks( top ).orElse( Collections.singleton( ItemStack.EMPTY ) );
Collection<ItemStack> bottomList = CTModule.toStacks( bottom ).orElse( Collections.singleton( ItemStack.EMPTY ) );
for( ItemStack topStack : topList )
{
for( ItemStack bottomStack : bottomList )
{
final IInscriberRecipeBuilder builder = AEApi.instance().registries().inscriber().builder();
builder.withProcessType( inscribe ? InscriberProcessType.INSCRIBE : InscriberProcessType.PRESS )
.withOutput( CTModule.toStack( output ) )
.withInputs( inStacks.get() );
if( !topStack.isEmpty() )
{
builder.withTopOptional( topStack );
}
if( !bottomStack.isEmpty() )
{
builder.withBottomOptional( bottomStack );
}
CTModule.MODIFICATIONS.add( new Add( builder.build() ) );
}
}
}
@ZenMethod
public static void removeRecipe( IItemStack output )
{
CTModule.MODIFICATIONS.add( new Remove( (ItemStack) output.getInternal() ) );
}
private static class Add implements IAction
{
private final IInscriberRecipe entry;
private Add( IInscriberRecipe entry )
{
this.entry = entry;
}
@Override
public void apply()
{
AEApi.instance().registries().inscriber().addRecipe( entry );
}
@Override
public String describe()
{
return "Adding Inscriber Entry for " + entry.getOutput().getDisplayName();
}
}
private static class Remove implements IAction
{
private final ItemStack stack;
private Remove( ItemStack stack )
{
this.stack = stack;
}
@Override
public void apply()
{
final IInscriberRegistry inscriber = AEApi.instance().registries().inscriber();
inscriber.getRecipes()
.stream()
.filter( r -> r.getOutput().isItemEqual( this.stack ) )
.collect( Collectors.toList() )
.forEach( inscriber::removeRecipe );
}
@Override
public String describe()
{
return "Removing Inscriber Entry for " + stack.getDisplayName();
}
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.crafttweaker;
import net.minecraft.tileentity.TileEntity;
import stanhebben.zenscript.annotations.ZenClass;
import stanhebben.zenscript.annotations.ZenMethod;
import appeng.api.AEApi;
import appeng.core.AELog;
@ZenClass( "mods.appliedenergistics2.Spatial" )
public class SpatialRegistry
{
private SpatialRegistry()
{
}
@ZenMethod
public static void whitelistEntity( String entityClassName )
{
Class<? extends TileEntity> entityClass = loadClass( entityClassName );
if( entityClass != null )
{
AEApi.instance().registries().movable().whiteListTileEntity( entityClass );
}
}
@SuppressWarnings( "unchecked" )
private static Class<? extends TileEntity> loadClass( String className )
{
try
{
return (Class<? extends TileEntity>) Class.forName( className );
}
catch( Exception e )
{
AELog.warn( e, "Failed to load TileEntity class '" + className + "'" );
}
return null;
}
}
@@ -54,13 +54,12 @@ public class NetworkToolViewer implements INetworkTool, IAEAppEngInventory
@Override
public void saveChanges()
{
this.inv.markDirty( -1 );
this.inv.writeToNBT( Platform.openNbtData( this.is ), "inv" );
}
@Override
public void onChangeInventory( IItemHandler inv, int slot, InvOperation mc, ItemStack removedStack, ItemStack newStack )
{
this.inv.writeToNBT( Platform.openNbtData( this.is ), "inv" );
}
@Override
@@ -318,7 +318,7 @@ public final class ItemMaterial extends AEBaseItem implements IStorageComponent,
}
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;
}
}
@@ -211,6 +211,7 @@ public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternIt
public ItemStack getOutput( final ItemStack item )
{
ItemStack out = SIMPLE_CACHE.get( item );
if( out != null )
{
return out;
@@ -224,12 +225,9 @@ public class ItemEncodedPattern extends AEBaseItem implements ICraftingPatternIt
final ICraftingPatternDetails details = this.getPatternForItem( item, w );
if( details == null )
{
return ItemStack.EMPTY;
}
out = details != null ? details.getOutputs()[0].createItemStack() : ItemStack.EMPTY;
SIMPLE_CACHE.put( item, out = details.getCondensedOutputs()[0].createItemStack() );
SIMPLE_CACHE.put( item, out );
return out;
}
}
@@ -219,13 +219,11 @@ public class ToolNetworkTool extends AEBaseItem implements IGuiItem, IAEWrench,
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{
user.swingArm( user.getActiveHand() );
}
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{
user.swingArm( user.getActiveHand() );
}
// IToolHammer - end
@@ -277,7 +277,7 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe
final IAEItemStack firstItem = itemList.getFirstItem();
if( firstItem != null )
{
newColor = firstItem.createItemStack();
newColor = firstItem.asItemStackRepresentation();
}
}
else
@@ -324,7 +324,7 @@ public class ToolColorApplicator extends AEBasePoweredItem implements IStorageCe
list.addFirst( list.removeLast() );
}
return list.get( 0 ).createItemStack();
return list.get( 0 ).asItemStackRepresentation();
}
}
@@ -103,14 +103,13 @@ public class ToolQuartzWrench extends AEBaseItem implements IAEWrench, IToolHamm
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, BlockPos pos )
{
user.swingArm( user.getActiveHand() );
}
@Override
public void toolUsed( ItemStack item, EntityLivingBase user, Entity entity )
{
user.swingArm( user.getActiveHand() );
}
// IToolHammer - end
// TODO: BC Wrench Integration
+80 -72
View File
@@ -54,80 +54,11 @@ public class GridConnection implements IGridConnection, IPathItem
private AEPartLocation fromAtoB;
private GridNode sideB;
public GridConnection( final IGridNode aNode, final IGridNode bNode, final AEPartLocation fromAtoB ) throws FailedConnectionException
private GridConnection( final GridNode aNode, final GridNode bNode, final AEPartLocation fromAtoB )
{
final GridNode a = (GridNode) aNode;
final GridNode b = (GridNode) bNode;
if( Platform.securityCheck( a, b ) )
{
if( AEConfig.instance().isFeatureEnabled( AEFeature.LOG_SECURITY_AUDITS ) )
{
final DimensionalCoord aCoordinates = a.getGridBlock().getLocation();
final DimensionalCoord bCoordinates = b.getGridBlock().getLocation();
AELog.info( "Security audit 1 failed at [%s] belonging to player [id=%d]", aCoordinates.toString(), a.getPlayerID() );
AELog.info( "Security audit 2 failed at [%s] belonging to player [id=%d]", bCoordinates.toString(), b.getPlayerID() );
}
throw new SecurityConnectionException();
}
if( a == null || b == null )
{
throw new NullNodeConnectionException();
}
if( a.hasConnection( b ) || b.hasConnection( a ) )
{
final String aMachineClass = a.getGridBlock().getMachine().getClass().getSimpleName();
final String bMachineClass = b.getGridBlock().getMachine().getClass().getSimpleName();
final String aCoordinates = a.getGridBlock().getLocation().toString();
final String bCoordinates = b.getGridBlock().getLocation().toString();
throw new ExistingConnectionException( String.format( EXISTING_CONNECTION_MESSAGE, aMachineClass, aCoordinates, bMachineClass, bCoordinates,
fromAtoB ) );
}
this.sideA = a;
this.sideA = aNode;
this.fromAtoB = fromAtoB;
this.sideB = b;
if( b.getMyGrid() == null )
{
b.setGrid( a.getInternalGrid() );
}
else
{
if( a.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
a.beginVisit( gp );
}
else if( b.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
b.beginVisit( gp );
}
else if( this.isNetworkABetter( a, b ) )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
b.beginVisit( gp );
}
else
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
a.beginVisit( gp );
}
}
// a connection was destroyed RE-PATH!!
final IPathingGrid p = this.sideA.getInternalGrid().getCache( IPathingGrid.class );
p.repath();
this.sideA.addConnection( this );
this.sideB.addConnection( this );
this.sideB = bNode;
}
private boolean isNetworkABetter( final GridNode a, final GridNode b )
@@ -291,4 +222,81 @@ public class GridConnection implements IGridConnection, IPathItem
{
this.visitorIterationNumber = visitorIterationNumber;
}
public static GridConnection create( final IGridNode aNode, final IGridNode bNode, final AEPartLocation fromAtoB ) throws FailedConnectionException
{
if( aNode == null || bNode == null )
{
throw new NullNodeConnectionException();
}
final GridNode a = (GridNode) aNode;
final GridNode b = (GridNode) bNode;
if( a.hasConnection( b ) || b.hasConnection( a ) )
{
final String aMachineClass = a.getGridBlock().getMachine().getClass().getSimpleName();
final String bMachineClass = b.getGridBlock().getMachine().getClass().getSimpleName();
final String aCoordinates = a.getGridBlock().getLocation().toString();
final String bCoordinates = b.getGridBlock().getLocation().toString();
throw new ExistingConnectionException( String.format( EXISTING_CONNECTION_MESSAGE, aMachineClass, aCoordinates, bMachineClass, bCoordinates,
fromAtoB ) );
}
if( !Platform.securityCheck( a, b ) )
{
if( AEConfig.instance().isFeatureEnabled( AEFeature.LOG_SECURITY_AUDITS ) )
{
final DimensionalCoord aCoordinates = a.getGridBlock().getLocation();
final DimensionalCoord bCoordinates = b.getGridBlock().getLocation();
AELog.info( "Security audit 1 failed at [%s] belonging to player [id=%d]", aCoordinates.toString(), a.getPlayerID() );
AELog.info( "Security audit 2 failed at [%s] belonging to player [id=%d]", bCoordinates.toString(), b.getPlayerID() );
}
throw new SecurityConnectionException();
}
// Create the actual connection
final GridConnection connection = new GridConnection( a, b, fromAtoB );
// Update both nodes with the new connection.
if( a.getMyGrid() == null )
{
b.setGrid( a.getInternalGrid() );
}
else
{
if( a.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
aNode.beginVisit( gp );
}
else if( b.getMyGrid() == null )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
bNode.beginVisit( gp );
}
else if( connection.isNetworkABetter( a, b ) )
{
final GridPropagator gp = new GridPropagator( a.getInternalGrid() );
b.beginVisit( gp );
}
else
{
final GridPropagator gp = new GridPropagator( b.getInternalGrid() );
a.beginVisit( gp );
}
}
// a connection was destroyed RE-PATH!!
final IPathingGrid p = connection.sideA.getInternalGrid().getCache( IPathingGrid.class );
p.repath();
connection.sideA.addConnection( connection );
connection.sideB.addConnection( connection );
return connection;
}
}
+23 -6
View File
@@ -33,6 +33,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import appeng.api.exceptions.FailedConnectionException;
import appeng.api.exceptions.SecurityConnectionException;
import appeng.api.networking.GridFlags;
import appeng.api.networking.GridNotification;
import appeng.api.networking.IGrid;
@@ -50,6 +51,7 @@ import appeng.api.util.AEColor;
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.IReadOnlyCollection;
import appeng.core.AELog;
import appeng.core.worlddata.WorldData;
import appeng.hooks.TickHandler;
import appeng.me.pathfinding.IPathItem;
@@ -216,7 +218,7 @@ public class GridNode implements IGridNode, IPathItem
this.compressedData |= ( 1 << ( dir.ordinal() + 8 ) );
}
this.FindConnections();
this.findConnections();
this.getInternalGrid();
}
@@ -393,7 +395,7 @@ public class GridNode implements IGridNode, IPathItem
return this.usedChannels;
}
private void FindConnections()
private void findConnections()
{
if( !this.gridProxy.isWorldAccessible() )
{
@@ -455,11 +457,18 @@ public class GridNode implements IGridNode, IPathItem
// construct a new connection between these two nodes.
try
{
new GridConnection( node, this, f.getOpposite() );
GridConnection.create( node, this, f.getOpposite() );
}
catch( SecurityConnectionException e )
{
AELog.debug( e );
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
return;
}
catch( final FailedConnectionException e )
{
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
AELog.debug( e );
return;
}
@@ -482,11 +491,19 @@ public class GridNode implements IGridNode, IPathItem
// construct a new connection between these two nodes.
try
{
new GridConnection( node, this, f.getOpposite() );
GridConnection.create( node, this, f.getOpposite() );
}
catch( SecurityConnectionException e )
{
AELog.debug( e );
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
return;
}
catch( final FailedConnectionException e )
{
TickHandler.INSTANCE.addCallable( node.getWorld(), new MachineSecurityBreak( this ) );
AELog.debug( e );
return;
}
+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() ) )
{
// 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 );
}
+22 -18
View File
@@ -311,35 +311,32 @@ public class EnergyGridCache implements IEnergyGrid
final double newPower = node.extractAEPower( req, mode, PowerMultiplier.ONE );
extractedPower += newPower;
if( newPower < req )
if( newPower < req && mode == Actionable.MODULATE )
{
it.remove();
}
}
// got more then we wanted?
if( extractedPower > amt )
{
this.localStorage.addCurrentAEPower( extractedPower - amt );
this.globalAvailablePower -= amt;
final double result = Math.min( extractedPower, amt );
this.tickDrainPerTick += amt;
return amt;
if( mode == Actionable.MODULATE )
{
if( extractedPower > amt )
{
this.localStorage.addCurrentAEPower( extractedPower - amt );
}
this.globalAvailablePower -= result;
this.tickDrainPerTick += result;
}
// go less or the correct amount?
this.globalAvailablePower -= extractedPower;
this.tickDrainPerTick += extractedPower;
return extractedPower;
return result;
}
@Override
public double injectProviderPower( double amt, final Actionable mode )
{
if( mode == Actionable.MODULATE )
{
this.tickInjectionPerTick += amt;
}
final double originalAmount = amt;
final Iterator<IAEPowerStorage> it = this.requesters.iterator();
@@ -348,13 +345,20 @@ public class EnergyGridCache implements IEnergyGrid
final IAEPowerStorage node = it.next();
amt = node.injectAEPower( amt, mode );
if( amt > 0 )
if( amt > 0 && mode == Actionable.MODULATE )
{
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
@@ -440,7 +440,6 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
this.lastTime = 0;
this.elapsedTime = 0;
this.isComplete = true;
}
private void updateCPU()
@@ -38,6 +38,7 @@ import appeng.api.networking.IGridHost;
import appeng.api.networking.IGridNode;
import appeng.api.util.AEPartLocation;
import appeng.api.util.WorldCoord;
import appeng.core.AELog;
import appeng.me.cache.helpers.ConnectionWrapper;
import appeng.me.cluster.IAECluster;
import appeng.tile.qnb.TileQuantumBridge;
@@ -161,6 +162,7 @@ public class QuantumCluster implements ILocatable, IAECluster
catch( final FailedConnectionException e )
{
// :(
AELog.debug( e );
}
}
else
@@ -241,11 +241,11 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{
try
{
new GridConnection( cn, sn, AEPartLocation.INTERNAL );
GridConnection.create( cn, sn, AEPartLocation.INTERNAL );
}
catch( final FailedConnectionException e )
{
// ekk!
AELog.debug( e );
bp.removeFromWorld();
this.setCenter( null );
@@ -292,11 +292,11 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{
try
{
new GridConnection( cn, sn, AEPartLocation.INTERNAL );
GridConnection.create( cn, sn, AEPartLocation.INTERNAL );
}
catch( final FailedConnectionException e )
{
// ekk!
AELog.debug( e );
bp.removeFromWorld();
this.setSide( side, null );
@@ -637,6 +637,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
catch( final FailedConnectionException e )
{
// ekk
AELog.debug( e );
}
}
}
@@ -1087,7 +1088,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
this.getFacadeContainer().readFromNBT( data );
}
public List getDrops( final List drops )
public List<ItemStack> getDrops( final List<ItemStack> drops )
{
for( final AEPartLocation s : AEPartLocation.values() )
{
@@ -1111,7 +1112,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
return drops;
}
public List getNoDrops( final List drops )
public List<ItemStack> getNoDrops( final List<ItemStack> drops )
{
for( final AEPartLocation s : AEPartLocation.values() )
{
@@ -1150,12 +1151,15 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
@Override
public CableBusRenderState getRenderState()
{
PartCable cable = (PartCable) this.getCenter();
final PartCable cable = (PartCable) this.getCenter();
CableBusRenderState renderState = new CableBusRenderState();
final CableBusRenderState renderState = new CableBusRenderState();
if( cable != null )
{
final boolean isSmart = cable.getCableConnectionType() == AECableType.SMART || cable.getCableConnectionType() == AECableType.DENSE_SMART;
final boolean isDense = cable.getCableConnectionType() == AECableType.DENSE_COVERED || cable.getCableConnectionType() == AECableType.DENSE_SMART;
renderState.setCableColor( cable.getCableColor() );
renderState.setCableType( cable.getCableConnectionType() );
renderState.setCoreType( CableCoreType.fromCableType( cable.getCableConnectionType() ) );
@@ -1175,12 +1179,12 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// Only use the incoming cable-type of the adjacent block, if it's not a cable bus itself
// Dense cables however also respect the adjacent cable-type since their outgoing connection
// point would look too big for other cable types
BlockPos adjacentPos = this.getTile().getPos().offset( facing );
TileEntity adjacentTe = this.getTile().getWorld().getTileEntity( adjacentPos );
final BlockPos adjacentPos = this.getTile().getPos().offset( facing );
final TileEntity adjacentTe = this.getTile().getWorld().getTileEntity( adjacentPos );
if( adjacentTe instanceof IGridHost )
{
if( !( adjacentTe instanceof IPartHost ) || cable.getCableConnectionType() == AECableType.DENSE_SMART || cable
.getCableConnectionType() == AECableType.DENSE_COVERED )
if( !( adjacentTe instanceof IPartHost ) || isDense )
{
IGridHost gridHost = (IGridHost) adjacentTe;
connectionType = gridHost.getCableConnectionType( AEPartLocation.fromFacing( facing.getOpposite() ) );
@@ -1201,7 +1205,7 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// adjacent tile requires it
for( EnumFacing facing : EnumFacing.values() )
{
int channels = cable.getChannelsOnSide( facing );
int channels = isSmart ? cable.getChannelsOnSide( facing ) : 0;
renderState.getChannelsOnSide().put( facing, channels );
}
}
@@ -1209,14 +1213,14 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
// Determine attachments and facades
for( EnumFacing facing : EnumFacing.values() )
{
final FacadeRenderState facadeState = this.getFacadeRenderState( facing );
FacadeRenderState facadeState = this.getFacadeRenderState( facing );
if( facadeState != null )
{
renderState.getFacades().put( facing, facadeState );
}
IPart part = this.getPart( facing );
final IPart part = this.getPart( facing );
if( part == null )
{
@@ -1224,15 +1228,17 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
}
// This will add the part's bounding boxes to the render state, which is required for facades
AEPartLocation loc = AEPartLocation.fromFacing( facing );
IPartCollisionHelper bch = new BusCollisionHelper( renderState.getBoundingBoxes(), loc, null, true );
final AEPartLocation loc = AEPartLocation.fromFacing( facing );
final IPartCollisionHelper bch = new BusCollisionHelper( renderState.getBoundingBoxes(), loc, null, true );
part.getBoxes( bch );
if( part instanceof IGridHost )
{
// Some attachments want a thicker cable than glass, account for that
IGridHost gridHost = (IGridHost) part;
AECableType desiredType = gridHost.getCableConnectionType( AEPartLocation.INTERNAL );
final IGridHost gridHost = (IGridHost) part;
final AECableType desiredType = gridHost.getCableConnectionType( AEPartLocation.INTERNAL );
if( renderState.getCoreType() == CableCoreType.GLASS && ( desiredType == AECableType.SMART || desiredType == AECableType.COVERED ) )
{
renderState.setCoreType( CableCoreType.COVERED );
@@ -1254,14 +1260,16 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
private FacadeRenderState getFacadeRenderState( EnumFacing side )
{
// Store the "masqueraded" itemstack for the given side, if there is a facade
IFacadePart facade = this.getFacade( side.ordinal() );
final IFacadePart facade = this.getFacade( side.ordinal() );
if( facade != null )
{
ItemStack textureItem = facade.getTextureItem();
IBlockState blockState = facade.getBlockState();
final ItemStack textureItem = facade.getTextureItem();
final IBlockState blockState = facade.getBlockState();
if( blockState != null && textureItem != null )
{
EnumSet<EnumFacing> openFaces = this.calculateFaceOpenFaces( side );
final EnumSet<EnumFacing> openFaces = this.calculateFaceOpenFaces( side );
return new FacadeRenderState( blockState, openFaces, textureItem );
}
}
@@ -1273,9 +1281,9 @@ public class CableBusContainer extends CableBusStorage implements AEMultiTile, I
{
final EnumSet<EnumFacing> out = EnumSet.of( side, side.getOpposite() );
final IFacadePart facade = this.getFacade( side.ordinal() );
final IBlockAccess blockAccess = this.getTile().getWorld();
final BlockPos pos = this.getTile().getPos();
IBlockAccess blockAccess = this.getTile().getWorld();
BlockPos pos = this.getTile().getPos();
for( final EnumFacing it : EnumFacing.values() )
{
if( !out.contains( it ) && this.hasAlphaDiff( blockAccess.getTileEntity( pos.offset( it ) ), side, facade ) )
@@ -29,7 +29,6 @@ import net.minecraft.util.math.Vec3d;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings;
import appeng.api.config.Upgrades;
@@ -41,7 +40,6 @@ import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPartCollisionHelper;
import appeng.api.parts.IPartModel;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
@@ -72,9 +70,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/import_bus_has_channel" ) );
private final IActionSource source;
private IMEInventory<IAEItemStack> destination = null;
private IAEItemStack lastItemChecked = null;
private int itemToSend; // used in tickingRequest
private int itemsToSend; // used in tickingRequest
private boolean worked; // used in tickingRequest
@Reflected
@@ -95,14 +91,24 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
return false;
}
final IAEItemStack out = this.destination.injectItems(
this.lastItemChecked = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( stack ), Actionable.SIMULATE,
this.source );
if( out == null )
try
{
return true;
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage().getInventory(
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
final IAEItemStack out = inv.injectItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( stack ),
Actionable.SIMULATE,
this.source );
if( out == null )
{
return true;
}
return out.getStackSize() != stack.getCount();
}
catch( GridAccessException ex )
{
return false;
}
return out.getStackSize() != stack.getCount();
}
@Override
@@ -165,9 +171,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
{
try
{
this.itemToSend = this.calculateItemsToSend();
this.itemToSend = Math.min( this.itemToSend,
(int) ( 0.01 + this.getProxy().getEnergy().extractAEPower( this.itemToSend, Actionable.SIMULATE, PowerMultiplier.CONFIG ) ) );
this.itemsToSend = this.calculateItemsToSend();
final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage().getInventory(
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
@@ -177,10 +181,10 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
for( int x = 0; x < this.availableSlots(); x++ )
{
final IAEItemStack ais = this.getConfig().getAEStackInSlot( x );
if( ais != null && this.itemToSend > 0 )
if( ais != null && itemsToSend > 0 )
{
Configured = true;
while( this.itemToSend > 0 )
while( itemsToSend > 0 )
{
if( this.importStuff( myAdaptor, ais, inv, energy, fzMode ) )
{
@@ -192,7 +196,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
if( !Configured )
{
while( this.itemToSend > 0 )
while( itemsToSend > 0 )
{
if( this.importStuff( myAdaptor, null, inv, energy, fzMode ) )
{
@@ -221,38 +225,32 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{
newItems = myAdaptor.removeSimilarItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), fzMode,
this.configDestination( inv ) );
newItems = myAdaptor.removeSimilarItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), fzMode, this );
}
else
{
newItems = myAdaptor.removeItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), this.configDestination( inv ) );
newItems = myAdaptor.removeItems( toSend, whatToImport == null ? ItemStack.EMPTY : whatToImport.getDefinition(), this );
}
if( !newItems.isEmpty() )
{
newItems.setCount( (int) ( Math.min( newItems.getCount(),
energy.extractAEPower( newItems.getCount(), Actionable.SIMULATE, PowerMultiplier.CONFIG ) ) + 0.01 ) );
this.itemToSend -= newItems.getCount();
if( this.lastItemChecked == null || !this.lastItemChecked.isSameType( newItems ) )
{
this.lastItemChecked = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( newItems );
}
else
{
this.lastItemChecked.setStackSize( newItems.getCount() );
}
final IAEItemStack failed = Platform.poweredInsert( energy, this.destination, this.lastItemChecked, this.source );
final IAEItemStack aeStack = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( newItems );
final IAEItemStack failed = Platform.poweredInsert( energy, inv, aeStack, this.source );
if( failed != null )
{
myAdaptor.addItems( failed.createItemStack() );
// try unpowered insert, better be a bit lenient then void items
final IAEItemStack spill = inv.injectItems( failed, Actionable.MODULATE, this.source );
if( spill != null )
{
// last resort try to put it back .. lets hope it's a chest type of thing
myAdaptor.addItems( spill.createItemStack() );
}
return true;
}
else
{
this.itemsToSend -= newItems.getCount();
this.worked = true;
}
}
@@ -266,7 +264,7 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
private int calculateMaximumAmountToImport( final InventoryAdaptor myAdaptor, final IAEItemStack whatToImport, final IMEMonitor<IAEItemStack> inv, final FuzzyMode fzMode )
{
final int toSend = Math.min( this.itemToSend, 64 );
final int toSend = Math.min( this.itemsToSend, 64 );
final ItemStack itemStackToImport;
if( whatToImport == null )
@@ -282,13 +280,13 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
final ItemStack simResult;
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{
simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, this.configDestination( inv ) );
itemAmountNotStorable = this.destination.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
simResult = myAdaptor.simulateSimilarRemove( toSend, itemStackToImport, fzMode, this );
itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
}
else
{
simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, this.configDestination( inv ) );
itemAmountNotStorable = this.destination.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
simResult = myAdaptor.simulateRemove( toSend, itemStackToImport, this );
itemAmountNotStorable = inv.injectItems( AEItemStack.fromItemStack( simResult ), Actionable.SIMULATE, this.source );
}
if( itemAmountNotStorable != null )
@@ -299,12 +297,6 @@ public class PartImportBus extends PartSharedItemBus implements IInventoryDestin
return toSend;
}
private IInventoryDestination configDestination( final IMEMonitor<IAEItemStack> itemInventory )
{
this.destination = itemInventory;
return this;
}
@Override
protected boolean isSleeping()
{
@@ -19,10 +19,10 @@
package appeng.parts.misc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -36,11 +36,12 @@ import appeng.api.networking.storage.IBaseMonitor;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.core.AELog;
import appeng.me.GridAccessException;
import appeng.me.helpers.IGridProxyable;
import appeng.me.storage.ITickingMonitor;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
@@ -51,20 +52,17 @@ import appeng.util.item.AEItemStack;
*/
class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor
{
private final Map<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new HashMap<>();
private IActionSource mySource;
private final IItemHandler itemHandler;
private final IGridProxyable proxyable;
private final InventoryCache cache;
private ItemStack[] cachedStacks = new ItemStack[0];
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
ItemHandlerAdapter( IItemHandler itemHandler )
ItemHandlerAdapter( IItemHandler itemHandler, IGridProxyable proxy )
{
this.itemHandler = itemHandler;
this.proxyable = proxy;
this.cache = new InventoryCache( this.itemHandler );
}
@Override
@@ -91,7 +89,14 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
if( type == Actionable.MODULATE )
{
this.onTick();
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
return AEItemStack.fromItemStack( remaining );
@@ -167,7 +172,14 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{
if( mode == Actionable.MODULATE )
{
this.onTick();
try
{
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
}
catch( GridAccessException ex )
{
// meh
}
}
return AEItemStack.fromItemStack( gathered );
@@ -176,72 +188,10 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
return null;
}
private ItemStack getItemStackInCachedSlot( int pos )
{
if( pos > this.cachedStacks.length )
{
return ItemStack.EMPTY;
}
if( this.cachedStacks[pos] == null )
{
return ItemStack.EMPTY;
}
return this.cachedStacks[pos];
}
@Override
public TickRateModulation onTick()
{
LinkedList<IAEItemStack> changes = new LinkedList<>();
int slots = this.itemHandler.getSlots();
// Make room for new slots
if( slots > this.cachedStacks.length )
{
this.cachedStacks = Arrays.copyOf( this.cachedStacks, slots );
this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots );
}
for( int slot = 0; slot < slots; slot++ )
{
// Save the old stuff
ItemStack oldIS = this.getItemStackInCachedSlot( slot );
IAEItemStack oldAeIS = this.cachedAeStacks[slot];
ItemStack newIS = this.itemHandler.getStackInSlot( slot );
if( this.isDifferent( newIS, oldIS ) )
{
this.addItemChange( slot, oldAeIS, newIS, changes );
}
else if( !newIS.isEmpty() && !oldIS.isEmpty() )
{
this.addPossibleStackSizeChange( slot, oldAeIS, newIS, changes );
}
}
// Handle cases where the number of slots actually is lower now than before
if( slots < this.cachedStacks.length )
{
for( int slot = slots; slot < this.cachedStacks.length; slot++ )
{
IAEItemStack aeStack = this.cachedAeStacks[slot];
if( aeStack != null )
{
IAEItemStack a = aeStack.copy();
a.setStackSize( -a.getStackSize() );
changes.add( a );
}
}
// Reduce the cache size
this.cachedStacks = Arrays.copyOf( this.cachedStacks, slots );
this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots );
}
List<IAEItemStack> changes = this.cache.update();
if( !changes.isEmpty() )
{
this.postDifference( changes );
@@ -253,73 +203,6 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
}
private void addItemChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
// Completely different item
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = AEItemStack.fromItemStack( newIS );
// If we had a stack previously in this slot, notify the newtork about its disappearance
if( oldAeIS != null )
{
oldAeIS.setStackSize( -oldAeIS.getStackSize() );
changes.add( oldAeIS );
}
// Notify the network about the new stack. Note that this is null if newIS was null
if( this.cachedAeStacks[slot] != null )
{
changes.add( this.cachedAeStacks[slot] );
}
}
private void addPossibleStackSizeChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
// Still the same item, but amount might have changed
long diff = newIS.getCount() - oldAeIS.getStackSize();
if( diff != 0 )
{
IAEItemStack stack = oldAeIS.copy();
stack.setStackSize( newIS.getCount() );
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = stack;
final IAEItemStack a = stack.copy();
a.setStackSize( diff );
changes.add( a );
}
}
private boolean isDifferent( final ItemStack a, final ItemStack b )
{
if( a == b && b.isEmpty() )
{
return false;
}
return a.isEmpty() || b.isEmpty() || !Platform.itemComparisons().isSameItem( a, b );
}
private void postDifference( Iterable<IAEItemStack> a )
{
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while( i.hasNext() )
{
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) )
{
key.postChange( this, a, this.mySource );
}
else
{
i.remove();
}
}
}
@Override
public void setActionSource( final IActionSource mySource )
{
@@ -339,7 +222,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
}
@Override
public IStorageChannel getChannel()
public IItemStorageChannel getChannel()
{
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
}
@@ -355,4 +238,152 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
{
this.listeners.remove( l );
}
private void postDifference( Iterable<IAEItemStack> a )
{
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while( i.hasNext() )
{
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) )
{
key.postChange( this, a, this.mySource );
}
else
{
i.remove();
}
}
}
private static class InventoryCache
{
private ItemStack[] cachedStacks = new ItemStack[0];
private IAEItemStack[] cachedAeStacks = new IAEItemStack[0];
private final IItemHandler itemHandler;
public InventoryCache( IItemHandler itemHandler )
{
this.itemHandler = itemHandler;
}
public List<IAEItemStack> update()
{
List<IAEItemStack> changes = new ArrayList<>();
int slots = this.itemHandler.getSlots();
// Make room for new slots
if( slots > this.cachedStacks.length )
{
this.cachedStacks = Arrays.copyOf( this.cachedStacks, slots );
this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots );
}
for( int slot = 0; slot < slots; slot++ )
{
// Save the old stuff
ItemStack oldIS = this.getItemStackInCachedSlot( slot );
IAEItemStack oldAeIS = this.cachedAeStacks[slot];
ItemStack newIS = this.itemHandler.getStackInSlot( slot );
if( isDifferent( newIS, oldIS ) )
{
this.addItemChange( slot, oldAeIS, newIS, changes );
}
else if( !newIS.isEmpty() && !oldIS.isEmpty() )
{
this.addPossibleStackSizeChange( slot, oldAeIS, newIS, changes );
}
}
// Handle cases where the number of slots actually is lower now than before
if( slots < this.cachedStacks.length )
{
for( int slot = slots; slot < this.cachedStacks.length; slot++ )
{
IAEItemStack aeStack = this.cachedAeStacks[slot];
if( aeStack != null )
{
IAEItemStack a = aeStack.copy();
a.setStackSize( -a.getStackSize() );
changes.add( a );
}
}
// Reduce the cache size
this.cachedStacks = Arrays.copyOf( this.cachedStacks, slots );
this.cachedAeStacks = Arrays.copyOf( this.cachedAeStacks, slots );
}
return changes;
}
private void addPossibleStackSizeChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
// Still the same item, but amount might have changed
long diff = newIS.getCount() - oldAeIS.getStackSize();
if( diff != 0 )
{
IAEItemStack stack = oldAeIS.copy();
stack.setStackSize( newIS.getCount() );
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = stack;
final IAEItemStack a = stack.copy();
a.setStackSize( diff );
changes.add( a );
}
}
private ItemStack getItemStackInCachedSlot( int pos )
{
if( pos > this.cachedStacks.length )
{
return ItemStack.EMPTY;
}
if( this.cachedStacks[pos] == null )
{
return ItemStack.EMPTY;
}
return this.cachedStacks[pos];
}
private void addItemChange( int slot, IAEItemStack oldAeIS, ItemStack newIS, List<IAEItemStack> changes )
{
// Completely different item
this.cachedStacks[slot] = newIS;
this.cachedAeStacks[slot] = AEItemStack.fromItemStack( newIS );
// If we had a stack previously in this slot, notify the newtork about its disappearance
if( oldAeIS != null )
{
oldAeIS.setStackSize( -oldAeIS.getStackSize() );
changes.add( oldAeIS );
}
// Notify the network about the new stack. Note that this is null if newIS was null
if( this.cachedAeStacks[slot] != null )
{
changes.add( this.cachedAeStacks[slot] );
}
}
private static boolean isDifferent( final ItemStack a, final ItemStack b )
{
if( a == b && b.isEmpty() )
{
return false;
}
return a.isEmpty() || b.isEmpty() || !Platform.itemComparisons().isSameItem( a, b );
}
}
}
@@ -66,7 +66,6 @@ import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
@@ -112,7 +111,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
private int priority = 0;
private boolean cached = false;
private ITickingMonitor monitor = null;
private MEInventoryHandler<? extends IAEStack> handler = null;
private MEInventoryHandler<IAEItemStack> handler = null;
private int handlerHash = 0;
private boolean wasActive = false;
private byte resetCacheLogic = 0;
@@ -355,22 +354,18 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
final IMEInventory<IAEItemStack> out = this.getInternalHandler();
if( this.monitor != null )
if( in != out )
{
this.monitor.onTick();
IItemList<IAEItemStack> after = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
if( out != null )
{
after = out.getAvailableItems( after );
}
Platform.postListChanges( before, after, this, this.mySrc );
}
IItemList<IAEItemStack> after = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
if( out != null )
{
after = out.getAvailableItems( after );
}
Platform.postListChanges( before, after, this, this.mySrc );
}
@SuppressWarnings( "unchecked" )
private IMEInventory<? extends IAEItemStack> getInventoryWrapper( TileEntity target )
private IMEInventory<IAEItemStack> getInventoryWrapper( TileEntity target )
{
EnumFacing targetSide = this.getSide().getFacing().getOpposite();
@@ -397,7 +392,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
IItemHandler handlerExt = target.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, targetSide );
if( handlerExt != null )
{
return new ItemHandlerAdapter( handlerExt );
return new ItemHandlerAdapter( handlerExt, this );
}
return null;
@@ -428,7 +423,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
return 0;
}
public MEInventoryHandler getInternalHandler()
public MEInventoryHandler<IAEItemStack> getInternalHandler()
{
if( this.cached )
{
@@ -452,7 +447,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
this.monitor = null;
if( target != null )
{
IMEInventory<? extends IAEStack> inv = this.getInventoryWrapper( target );
IMEInventory<IAEItemStack> inv = this.getInventoryWrapper( target );
if( inv instanceof MEMonitorIInventory )
{
@@ -470,7 +465,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{
this.checkInterfaceVsStorageBus( target, this.getSide().getOpposite() );
this.handler = new MEInventoryHandler( inv, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
this.handler = new MEInventoryHandler<IAEItemStack>( inv, AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
this.handler.setBaseAccess( (AccessRestriction) this.getConfigManager().getSetting( Settings.ACCESS ) );
this.handler.setWhitelist( this.getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST );
@@ -491,16 +486,17 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
{
this.handler
.setPartitionList( new FuzzyPriorityList( priorityList, (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ) ) );
.setPartitionList( new FuzzyPriorityList<IAEItemStack>( priorityList, (FuzzyMode) this.getConfigManager()
.getSetting( Settings.FUZZY_MODE ) ) );
}
else
{
this.handler.setPartitionList( new PrecisePriorityList( priorityList ) );
this.handler.setPartitionList( new PrecisePriorityList<IAEItemStack>( priorityList ) );
}
if( inv instanceof IBaseMonitor )
{
( (IBaseMonitor) inv ).addListener( this, this.handler );
( (IBaseMonitor<IAEItemStack>) inv ).addListener( this, this.handler );
}
}
}
@@ -570,7 +566,7 @@ public class PartStorageBus extends PartUpgradeable implements IGridTickable, IC
{
if( channel == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{
final IMEInventoryHandler out = this.getProxy().isActive() ? this.getInternalHandler() : null;
final IMEInventoryHandler<IAEItemStack> out = this.getProxy().isActive() ? this.getInternalHandler() : null;
if( out != null )
{
return Collections.singletonList( out );
@@ -41,6 +41,7 @@ import appeng.api.parts.IPartHost;
import appeng.api.parts.IPartModel;
import appeng.api.util.AECableType;
import appeng.api.util.AEPartLocation;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.helpers.Reflected;
import appeng.items.parts.PartModels;
@@ -208,6 +209,7 @@ public class PartToggleBus extends PartBasicState
catch( final FailedConnectionException e )
{
// :(
AELog.debug( e );
}
}
else
@@ -55,7 +55,7 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
}
private int lastValue = 0;
private float opacity = -1;
private int opacity = -1;
public PartP2PLight( final ItemStack is )
{
@@ -81,15 +81,21 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
{
super.writeToStream( data );
data.writeInt( this.isOutput() ? this.lastValue : 0 );
data.writeInt( this.opacity );
}
@Override
public boolean readFromStream( final ByteBuf data ) throws IOException
{
super.readFromStream( data );
final int oldValue = this.lastValue;
final int oldOpacity = this.opacity;
this.lastValue = data.readInt();
this.opacity = data.readInt();
this.setOutput( this.lastValue > 0 );
return false;
return lastValue != oldValue || oldOpacity != this.opacity;
}
private boolean doWork()
@@ -126,14 +132,15 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
@Override
public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor )
{
this.opacity = -1;
this.doWork();
if( this.isOutput() )
if( this.isOutput() && pos.offset( this.getSide().getFacing() ).equals( neighbor ) )
{
this.opacity = -1;
this.getHost().markForUpdate();
}
else
{
this.doWork();
}
}
@Override
@@ -168,10 +175,6 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
public void readFromNBT( final NBTTagCompound tag )
{
super.readFromNBT( tag );
if( tag.hasKey( "opacity" ) )
{
this.opacity = tag.getFloat( "opacity" );
}
this.lastValue = tag.getInteger( "lastValue" );
}
@@ -179,7 +182,6 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
public void writeToNBT( final NBTTagCompound tag )
{
super.writeToNBT( tag );
tag.setFloat( "opacity", this.opacity );
tag.setInteger( "lastValue", this.lastValue );
}
@@ -219,7 +221,7 @@ public class PartP2PLight extends PartP2PTunnel<PartP2PLight> implements IGridTi
@Override
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()
@@ -247,6 +247,8 @@ public class PartP2PTunnelME extends PartP2PTunnel<PartP2PTunnelME> implements I
{
final TileEntity start = this.getTile();
final TileEntity end = me.getTile();
AELog.debug( e );
AELog.warn( "Failed to establish a ME P2P Tunnel between the tunnels at [x=%d, y=%d, z=%d] and [x=%d, y=%d, z=%d]",
start.getPos().getX(), start.getPos().getY(), start.getPos().getZ(), end.getPos().getX(), end.getPos().getY(),
@@ -70,7 +70,7 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
private byte spin = 0; // 0-3
private int clientFlags = 0; // sent as byte.
private float opacity = -1;
private int opacity = -1;
public AbstractPartReporting( final ItemStack is )
{
@@ -117,18 +117,17 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
@Override
public void onNeighborChanged( IBlockAccess w, BlockPos pos, BlockPos neighbor )
{
this.opacity = -1;
this.getHost().markForUpdate();
if( pos.offset( this.getSide().getFacing() ).equals( neighbor ) )
{
this.opacity = -1;
this.getHost().markForUpdate();
}
}
@Override
public void readFromNBT( final NBTTagCompound data )
{
super.readFromNBT( data );
if( data.hasKey( "opacity" ) )
{
this.opacity = data.getFloat( "opacity" );
}
this.spin = data.getByte( "spin" );
}
@@ -136,7 +135,6 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
public void writeToNBT( final NBTTagCompound data )
{
super.writeToNBT( data );
data.setFloat( "opacity", this.opacity );
data.setByte( "spin", this.getSpin() );
}
@@ -169,6 +167,7 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
}
data.writeByte( (byte) this.getClientFlags() );
data.writeInt( this.opacity );
}
@Override
@@ -176,9 +175,13 @@ public abstract class AbstractPartReporting extends AEBasePart implements IPartM
{
super.readFromStream( data );
final int oldFlags = this.getClientFlags();
final int oldOpacity = this.opacity;
this.clientFlags = data.readByte();
this.opacity = data.readInt();
this.spin = (byte) ( this.getClientFlags() & 3 );
if( this.getClientFlags() == oldFlags )
if( this.getClientFlags() == oldFlags && this.opacity == oldOpacity )
{
return false;
}
@@ -19,19 +19,34 @@
package appeng.recipes.factories.recipes;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.IRecipeFactory;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapedOreRecipe;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import appeng.api.AEApi;
import appeng.api.recipes.ResolverResult;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.recipes.helpers.PartShapedCraftingFactory;
import appeng.recipes.helpers.PartShapelessCraftingFactory;
/**
@@ -45,25 +60,148 @@ public class PartRecipeFactory implements IRecipeFactory
String type = JsonUtils.getString( json, "type" );
if( type.contains( "shaped" ) )
{
PartShapedCraftingFactory recipe = PartShapedCraftingFactory.factory( context, json );
CraftingHelper.ShapedPrimer primer = new CraftingHelper.ShapedPrimer();
primer.width = recipe.getWidth();
primer.height = recipe.getHeight();
primer.mirrored = JsonUtils.getBoolean( json, "mirrored", true );
primer.input = recipe.getIngredients();
return new PartShapedCraftingFactory( new ResourceLocation( AppEng.MOD_ID, "part_shaped_crafting" ), recipe.getRecipeOutput(), primer );
return shapedFactory( context, json );
}
else if( type.contains( "shapeless" ) )
{
PartShapelessCraftingFactory recipe = PartShapelessCraftingFactory.factory( context, json );
return new PartShapelessCraftingFactory( new ResourceLocation( AppEng.MOD_ID, "part_shapeless_crafting" ), recipe.getIngredients(), recipe
.getRecipeOutput() );
return shapelessFactory( context, json );
}
else
{
throw new JsonSyntaxException( "Applied Energistics 2 was given a custom recipe that it does not know how to handle!\n" + "Type should either be '" + AppEng.MOD_ID + ":shapeless' or '" + AppEng.MOD_ID + ":shaped', got '" + type + "'!" );
}
}
public static ItemStack getResult( JsonObject json, JsonContext context )
{
JsonObject resultObject = JsonUtils.getJsonObject( json, "result" );
if( resultObject.has( "part" ) )
{
return getPart( resultObject );
}
else if( resultObject.has( "item" ) )
{
return CraftingHelper.getItemStack( resultObject, context );
}
else
{
throw new JsonSyntaxException( "Result has no 'part' or 'item' property." );
}
}
private static ItemStack getPart( JsonObject resultObject )
{
String ingredient = JsonUtils.getString( resultObject, "part" );
Object result = AEApi.instance().registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
return new ItemStack( item, JsonUtils.getInt( resultObject, "count", 1 ), resolverResult.damageValue, resolverResult.compound );
}
else
{
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\n" + "Was looking for : '" + ingredient + "'." );
}
}
// Copied from ShapedOreRecipe.java, modified a bit.
private static ShapedOreRecipe shapedFactory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
Map<Character, Ingredient> ingMap = Maps.newHashMap();
for( Map.Entry<String, JsonElement> entry : JsonUtils.getJsonObject( json, "key" ).entrySet() )
{
if( entry.getKey().length() != 1 )
{
throw new JsonSyntaxException( "Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only)." );
}
if( " ".equals( entry.getKey() ) )
{
throw new JsonSyntaxException( "Invalid key entry: ' ' is a reserved symbol." );
}
ingMap.put( entry.getKey().toCharArray()[0], CraftingHelper.getIngredient( entry.getValue(), context ) );
}
ingMap.put( ' ', net.minecraft.item.crafting.Ingredient.EMPTY );
JsonArray patternJ = JsonUtils.getJsonArray( json, "pattern" );
if( patternJ.size() == 0 )
{
throw new JsonSyntaxException( "Invalid pattern: empty pattern not allowed" );
}
String[] pattern = new String[patternJ.size()];
for( int x = 0; x < pattern.length; ++x )
{
String line = JsonUtils.getString( patternJ.get( x ), "pattern[" + x + "]" );
if( x > 0 && pattern[0].length() != line.length() )
{
throw new JsonSyntaxException( "Invalid pattern: each row must be the same width" );
}
pattern[x] = line;
}
CraftingHelper.ShapedPrimer primer = new CraftingHelper.ShapedPrimer();
primer.width = pattern[0].length();
primer.height = pattern.length;
primer.mirrored = JsonUtils.getBoolean( json, "mirrored", true );
primer.input = NonNullList.withSize( primer.width * primer.height, net.minecraft.item.crafting.Ingredient.EMPTY );
Set<Character> keys = Sets.newHashSet( ingMap.keySet() );
keys.remove( ' ' );
int x = 0;
for( String line : pattern )
{
for( char chr : line.toCharArray() )
{
net.minecraft.item.crafting.Ingredient ing = ingMap.get( chr );
if( ing == null )
{
throw new JsonSyntaxException( "Pattern references symbol '" + chr + "' but it's not defined in the key" );
}
primer.input.set( x++, ing );
keys.remove( chr );
}
}
if( !keys.isEmpty() )
{
throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + keys );
}
return new ShapedOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), getResult( json, context ), primer );
}
// Copied from ShapelessOreRecipe.java, modified a bit.
private static ShapelessOreRecipe shapelessFactory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
NonNullList<Ingredient> ings = NonNullList.create();
for( JsonElement ele : JsonUtils.getJsonArray( json, "ingredients" ) )
{
ings.add( CraftingHelper.getIngredient( ele, context ) );
}
if( ings.isEmpty() )
{
throw new JsonParseException( "No ingredients for shapeless recipe" );
}
return new ShapelessOreRecipe( group.isEmpty() ? null : new ResourceLocation( group ), ings, getResult( json, context ) );
}
}
@@ -1,153 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.recipes.helpers;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapedOreRecipe;
import appeng.api.recipes.ResolverResult;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.core.AppEng;
/**
* @author GuntherDW
*/
public class PartShapedCraftingFactory extends ShapedOreRecipe
{
public PartShapedCraftingFactory( ResourceLocation group, @Nonnull ItemStack result, CraftingHelper.ShapedPrimer primer )
{
super( group, result, primer );
}
// Copied from ShapedOreRecipe.java, modified a bit.
public static PartShapedCraftingFactory factory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
Map<Character, Ingredient> ingMap = Maps.newHashMap();
for( Map.Entry<String, JsonElement> entry : JsonUtils.getJsonObject( json, "key" ).entrySet() )
{
if( entry.getKey().length() != 1 )
{
throw new JsonSyntaxException( "Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only)." );
}
if( " ".equals( entry.getKey() ) )
{
throw new JsonSyntaxException( "Invalid key entry: ' ' is a reserved symbol." );
}
ingMap.put( entry.getKey().toCharArray()[0], CraftingHelper.getIngredient( entry.getValue(), context ) );
}
ingMap.put( ' ', net.minecraft.item.crafting.Ingredient.EMPTY );
JsonArray patternJ = JsonUtils.getJsonArray( json, "pattern" );
if( patternJ.size() == 0 )
{
throw new JsonSyntaxException( "Invalid pattern: empty pattern not allowed" );
}
String[] pattern = new String[patternJ.size()];
for( int x = 0; x < pattern.length; ++x )
{
String line = JsonUtils.getString( patternJ.get( x ), "pattern[" + x + "]" );
if( x > 0 && pattern[0].length() != line.length() )
{
throw new JsonSyntaxException( "Invalid pattern: each row must be the same width" );
}
pattern[x] = line;
}
CraftingHelper.ShapedPrimer primer = new CraftingHelper.ShapedPrimer();
primer.width = pattern[0].length();
primer.height = pattern.length;
primer.mirrored = JsonUtils.getBoolean( json, "mirrored", true );
primer.input = NonNullList.withSize( primer.width * primer.height, net.minecraft.item.crafting.Ingredient.EMPTY );
Set<Character> keys = Sets.newHashSet( ingMap.keySet() );
keys.remove( ' ' );
int x = 0;
for( String line : pattern )
{
for( char chr : line.toCharArray() )
{
net.minecraft.item.crafting.Ingredient ing = ingMap.get( chr );
if( ing == null )
{
throw new JsonSyntaxException( "Pattern references symbol '" + chr + "' but it's not defined in the key" );
}
primer.input.set( x++, ing );
keys.remove( chr );
}
}
if( !keys.isEmpty() )
{
throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + keys );
}
JsonObject resultObject = (JsonObject) json.get( "result" );
int count = JsonUtils.getInt( resultObject, "count", 1 );
String ingredient = resultObject.get( "part" ).getAsString();
Object result = (Object) Api.INSTANCE.registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
ItemStack itemStack = new ItemStack( item, count, resolverResult.damageValue, resolverResult.compound );
return new PartShapedCraftingFactory( group.isEmpty() ? null : new ResourceLocation( group ), itemStack, primer );
}
// Should never reach this part unless mangled JSON or bug in AE.
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\nWas looking for : '" + ingredient + "'." );
}
}
@@ -1,96 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2017, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.recipes.helpers;
import javax.annotation.Nonnull;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.common.crafting.JsonContext;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import appeng.api.recipes.ResolverResult;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.core.AppEng;
/**
* @author GuntherDW
*/
public class PartShapelessCraftingFactory extends ShapelessOreRecipe
{
public PartShapelessCraftingFactory( ResourceLocation group, NonNullList<Ingredient> input, @Nonnull ItemStack result )
{
super( group, input, result );
}
// Copied from ShapelessOreRecipe.java, modified a bit.
public static PartShapelessCraftingFactory factory( JsonContext context, JsonObject json )
{
String group = JsonUtils.getString( json, "group", "" );
NonNullList<Ingredient> ings = NonNullList.create();
for( JsonElement ele : JsonUtils.getJsonArray( json, "ingredients" ) )
{
ings.add( CraftingHelper.getIngredient( ele, context ) );
}
if( ings.isEmpty() )
{
throw new JsonParseException( "No ingredients for shapeless recipe" );
}
JsonObject resultObject = (JsonObject) json.get( "result" );
int count = JsonUtils.getInt( resultObject, "count", 1 );
String ingredient = resultObject.get( "part" ).getAsString();
Object result = (Object) Api.INSTANCE.registries().recipes().resolveItem( AppEng.MOD_ID, ingredient );
if( result instanceof ResolverResult )
{
ResolverResult resolverResult = (ResolverResult) result;
Item item = Item.getByNameOrId( AppEng.MOD_ID + ":" + resolverResult.itemName );
if( item == null )
{
AELog.warn( "item was null for " + resolverResult.itemName + " ( " + ingredient + " )!" );
throw new JsonSyntaxException( "Got a null item for " + resolverResult.itemName + " ( " + ingredient + " ). This should never happen!" );
}
ItemStack itemStack = new ItemStack( item, count, resolverResult.damageValue, resolverResult.compound );
return new PartShapelessCraftingFactory( group.isEmpty() ? null : new ResourceLocation( group ), ings, itemStack );
}
throw new JsonSyntaxException( "Couldn't find the resulting item in AE. This means AE was provided a recipe that it shouldn't be handling.\n" + "Was looking for : '" + ingredient + "'." );
}
}
@@ -25,7 +25,6 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
@@ -58,7 +57,6 @@ public class RecipeResourceCopier
private static final String FILE_PROTOCOL = "file";
private static final String CLASS_EXTENSION = ".class";
private static final String JAR_PROTOCOL = "jar";
private static final String UTF_8_ENCODING = "UTF-8";
/**
* copy source in the jar
@@ -225,9 +223,9 @@ public class RecipeResourceCopier
{
/* A JAR path */
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
final JarFile jar = new JarFile( URLDecoder.decode( jarPath, UTF_8_ENCODING ) );
final JarFile jar = new JarFile( new File( new URI( jarPath ) ) );
try
{
final Enumeration<JarEntry> entries = jar.entries(); // gives ALL entries in jar
@@ -27,7 +27,7 @@ public class BiomeGenStorage extends Biome
public BiomeGenStorage()
{
super( new BiomeProperties( "Storage Cell" ).setRainDisabled().setTemperature( -100 ) );
super( new BiomeProperties( "Storage Cell" ).setBaseBiome( "void" ).setRainDisabled().setTemperature( -100 ) );
this.decorator.treesPerChunk = 0;
this.decorator.flowersPerChunk = 0;
+39 -30
View File
@@ -27,6 +27,7 @@ import java.util.Map.Entry;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.NextTickListEntry;
import net.minecraft.world.World;
@@ -34,7 +35,6 @@ import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import appeng.api.AEApi;
import appeng.api.definitions.IBlockDefinition;
import appeng.api.movable.IMovableHandler;
import appeng.api.movable.IMovableRegistry;
import appeng.api.util.AEPartLocation;
@@ -61,7 +61,6 @@ public class CachedPlane
private final World world;
private final IMovableRegistry reg = AEApi.instance().registries().movable();
private final LinkedList<WorldCoord> updates = new LinkedList<>();
private final IBlockDefinition matrixFrame = AEApi.instance().definitions().blocks().matrixFrame();
private int verticalBits;
private final IBlockState matrixBlockState;
@@ -146,11 +145,11 @@ public class CachedPlane
}
else
{
final Object[] details = this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].getDetails( tePOS.getY() );
final IBlockState blkState = (IBlockState) details[0];
final BlockStorageData details = new BlockStorageData();
this.myColumns[tePOS.getX() - minX][tePOS.getZ() - minZ].fillData( tePOS.getY(), details );
// don't skip air, just let the code replace it...
if( blkState != null && blkState.getBlock() == Platform.AIR_BLOCK && blkState.getMaterial().isReplaceable() )
if( details.state != null && details.state.getBlock() == Platform.AIR_BLOCK && details.state.getMaterial().isReplaceable() )
{
w.setBlockToAir( tePOS );
}
@@ -168,12 +167,11 @@ public class CachedPlane
}
final long k = this.getWorld().getTotalWorldTime();
final List list = this.getWorld().getPendingBlockUpdates( c, false );
final List<NextTickListEntry> list = this.getWorld().getPendingBlockUpdates( c, false );
if( list != null )
{
for( final Object o : list )
for( final NextTickListEntry entry : list )
{
final NextTickListEntry entry = (NextTickListEntry) o;
final BlockPos tePOS = entry.position;
if( tePOS.getX() >= minX && tePOS.getX() <= maxX && tePOS.getY() >= minY && tePOS.getY() <= maxY && tePOS.getZ() >= minZ && tePOS
.getZ() <= maxZ )
@@ -192,6 +190,10 @@ public class CachedPlane
try
{
this.getWorld().loadedTileEntityList.remove( te );
if( te instanceof ITickable )
{
this.getWorld().tickableTileEntities.remove( te );
}
}
catch( final Exception e )
{
@@ -215,6 +217,8 @@ public class CachedPlane
AELog.info( "Block Copy Scale: " + this.x_size + ", " + this.y_size + ", " + this.z_size );
long startTime = System.nanoTime();
final BlockStorageData aD = new BlockStorageData();
final BlockStorageData bD = new BlockStorageData();
for( int x = 0; x < this.x_size; x++ )
{
@@ -230,8 +234,8 @@ public class CachedPlane
if( a.doNotSkip( src_y ) && b.doNotSkip( dst_y ) )
{
final Object[] aD = a.getDetails( src_y );
final Object[] bD = b.getDetails( dst_y );
a.fillData( src_y, aD );
b.fillData( dst_y, bD );
a.setBlockIDWithMetadata( src_y, bD );
b.setBlockIDWithMetadata( dst_y, aD );
@@ -386,14 +390,17 @@ public class CachedPlane
return this.world;
}
private static class BlockStorageData
{
public IBlockState state;
public int light;
}
private class Column
{
private final int x;
private final int z;
private final Chunk c;
private final Object[] ch = { 0, 0 };
private final ExtendedBlockStorage[] storage;
private List<Integer> skipThese = null;
public Column( final Chunk chunk, final int x, final int z, final int chunkY, final int chunkHeight )
@@ -401,44 +408,46 @@ public class CachedPlane
this.x = x;
this.z = z;
this.c = chunk;
this.storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
// make sure storage exists before hand...
for( int ay = 0; ay < chunkHeight; ay++ )
{
final int by = ( ay + chunkY );
ExtendedBlockStorage extendedblockstorage = this.storage[by];
ExtendedBlockStorage extendedblockstorage = storage[by];
if( extendedblockstorage == null )
{
extendedblockstorage = this.storage[by] = new ExtendedBlockStorage( by << 4, !this.c.getWorld().provider.hasSkyLight() );
extendedblockstorage = storage[by] = new ExtendedBlockStorage( by << 4, this.c.getWorld().provider.hasSkyLight() );
}
}
}
private void setBlockIDWithMetadata( final int y, final Object[] blk )
private void setBlockIDWithMetadata( final int y, BlockStorageData data )
{
if( blk[0] == CachedPlane.this.matrixBlockState )
if( data.state == CachedPlane.this.matrixBlockState )
{
blk[0] = Platform.AIR_BLOCK.getDefaultState();
data.state = Platform.AIR_BLOCK.getDefaultState();
}
final ExtendedBlockStorage extendedBlockStorage = this.storage[y >> 4];
extendedBlockStorage.set( this.x, y & 15, this.z, (IBlockState) blk[0] );
// extendedBlockStorage.setExtBlockID( x, y & 15, z, blk[0] );
extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, (Integer) blk[1] );
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage extendedBlockStorage = storage[y >> 4];
extendedBlockStorage.set( this.x, y & 15, this.z, data.state );
extendedBlockStorage.setBlockLight( this.x, y & 15, this.z, data.light );
}
private Object[] getDetails( final int y )
private void fillData( final int y, BlockStorageData data )
{
final ExtendedBlockStorage extendedblockstorage = this.storage[y >> 4];
this.ch[0] = extendedblockstorage.get( this.x, y & 15, this.z );
this.ch[1] = extendedblockstorage.getBlockLight( this.x, y & 15, this.z );
return this.ch;
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage extendedblockstorage = storage[y >> 4];
data.state = extendedblockstorage.get( this.x, y & 15, this.z );
data.light = extendedblockstorage.getBlockLight( this.x, y & 15, this.z );
}
private boolean doNotSkip( final int y )
{
final ExtendedBlockStorage extendedblockstorage = this.storage[y >> 4];
final ExtendedBlockStorage[] storage = this.c.getBlockStorageArray();
final ExtendedBlockStorage extendedblockstorage = storage[y >> 4];
if( CachedPlane.this.reg.isBlacklisted( extendedblockstorage.get( this.x, y & 15, this.z ).getBlock() ) )
{
return false;
@@ -19,6 +19,7 @@
package appeng.spatial;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@@ -54,8 +55,9 @@ public class DefaultSpatialHandler implements IMovableHandler
if( c.isLoaded() )
{
final IBlockState state = w.getBlockState( newPosition );
w.addTileEntity( te );
w.notifyBlockUpdate( newPosition, w.getBlockState( newPosition ), w.getBlockState( newPosition ), 0 );
w.notifyBlockUpdate( newPosition, state, state, 1 );
}
}
}
@@ -122,6 +122,11 @@ public class StorageHelper
}
else
{
// really remove from world, forge only marks it as removed
final boolean wasDead = entity.isDead;
oldWorld.removeEntityDangerously( entity );
entity.isDead = wasDead;
entity.getServer().getPlayerList().transferEntityToWorld( entity, entity.dimension,
entity.getServer().getWorld( entity.dimension ), (WorldServer) link.dim, new METeleporter( newWorld, link ) );
}
@@ -74,7 +74,7 @@ public class TileCraftingStorageTile extends TileCraftingTile
@Override
public int getStorageBytes()
{
if( this.world == null || this.notLoaded() )
if( this.world == null || this.notLoaded() || this.isInvalid() )
{
return 0;
}
@@ -143,7 +143,7 @@ public class TileCraftingTile extends AENetworkTile implements IAEMultiBlock, IP
public void updateMeta( final boolean updateFormed )
{
if( this.world == null || this.notLoaded() )
if( this.world == null || this.notLoaded() || this.isInvalid() )
{
return;
}
@@ -46,6 +46,7 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
private final IAEItemStack[] inv;
private final int size;
private int maxStack;
private boolean dirtyFlag = false;
public AppEngInternalAEInventory( final IAEAppEngInventory te, final int s )
{
@@ -252,8 +253,10 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
{
if( this.te != null && Platform.isServer() )
{
this.dirtyFlag = true;
this.te.onChangeInventory( this, slot, op, removed, inserted );
this.te.saveChanges();
this.dirtyFlag = false;
}
}
@@ -283,6 +286,9 @@ public class AppEngInternalAEInventory implements IInternalItemHandler, Iterable
@Override
public void markDirty( int slot )
{
this.fireOnChangeInventory( slot, InvOperation.DIRTY, ItemStack.EMPTY, ItemStack.EMPTY );
if( !this.dirtyFlag )
{
this.fireOnChangeInventory( slot, InvOperation.DIRTY, ItemStack.EMPTY, ItemStack.EMPTY );
}
}
}
@@ -43,6 +43,7 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
private final int[] maxStack;
private ItemStack previousStack = ItemStack.EMPTY;
private IAEItemFilter filter;
private boolean dirtyFlag = false;
public AppEngInternalInventory( final IAEAppEngInventory inventory, final int size, final int maxStack, IAEItemFilter filter )
{
@@ -118,6 +119,7 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
{
if( this.getTileEntity() != null && this.eventsEnabled() )
{
this.dirtyFlag = true;
ItemStack newStack = this.getStackInSlot( slot ).copy();
ItemStack oldStack = this.previousStack;
InvOperation op = InvOperation.SET;
@@ -141,6 +143,7 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
this.getTileEntity().onChangeInventory( this, slot, op, oldStack, newStack );
this.getTileEntity().saveChanges();
this.previousStack = ItemStack.EMPTY;
this.dirtyFlag = false;
}
super.onContentsChanged( slot );
}
@@ -158,10 +161,12 @@ public class AppEngInternalInventory extends ItemStackHandler implements IIntern
@Override
public void markDirty( final int slot )
{
if( this.getTileEntity() != null && this.eventsEnabled() )
if( this.getTileEntity() != null && this.eventsEnabled() && !this.dirtyFlag )
{
this.dirtyFlag = true;
this.getTileEntity().onChangeInventory( this, slot, InvOperation.DIRTY, ItemStack.EMPTY, ItemStack.EMPTY );
this.getTileEntity().saveChanges();
this.dirtyFlag = false;
}
}
@@ -281,9 +281,13 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
@Nullable
public IInscriberRecipe getTask()
{
final ItemStack plateA = this.topItemHandler.getStackInSlot( 0 );
final ItemStack plateB = this.bottomItemHandler.getStackInSlot( 0 );
ItemStack renamedItem = this.sideItemHandler.getStackInSlot( 0 );
return getTask( this.sideItemHandler.getStackInSlot( 0 ), this.topItemHandler.getStackInSlot( 0 ), this.bottomItemHandler.getStackInSlot( 0 ) );
}
@Nullable
private IInscriberRecipe getTask( final ItemStack input, final ItemStack plateA, final ItemStack plateB )
{
ItemStack renamedItem = input;
if( !plateA.isEmpty() && plateA.getCount() > 1 )
{
@@ -379,7 +383,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
{
for( final ItemStack option : recipe.getInputs() )
{
if( Platform.itemComparisons().isSameItem( option, this.sideItemHandler.getStackInSlot( 0 ) ) )
if( Platform.itemComparisons().isSameItem( input, option ) )
{
return recipe;
}
@@ -606,7 +610,7 @@ public class TileInscriber extends AENetworkPowerTile implements IGridTickable,
}
for( final ItemStack optionals : AEApi.instance().registries().inscriber().getOptionals() )
{
if( Platform.itemComparisons().isSameItem( optionals, stack ) )
if( Platform.itemComparisons().isSameItem( stack, optionals ) )
{
return true;
}
@@ -83,13 +83,14 @@ public class TileCableBus extends AEBaseTile implements AEMultiTile, ICustomColl
protected boolean readFromStream( final ByteBuf data ) throws IOException
{
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();
if( newLV != this.oldLV )
{
this.oldLV = newLV;
this.world.checkLight( this.pos );
ret = true;
}
this.updateTileSetting();
@@ -189,7 +190,6 @@ public class TileCableBus extends AEBaseTile implements AEMultiTile, ICustomColl
{
this.oldLV = newLV;
this.world.checkLight( this.pos );
// world.updateAllLightTypes( xCoord, yCoord, zCoord );
}
super.markForUpdate();
@@ -209,8 +209,7 @@ public class TileController extends AENetworkPowerTile
*/
private boolean checkController( final BlockPos pos )
{
final BlockPos ownPos = this.getPos();
if( this.world.getChunkProvider().getLoadedChunk( ownPos.getX() >> 4, ownPos.getZ() >> 4 ) != null )
if( this.world.getChunkProvider().getLoadedChunk( pos.getX() >> 4, pos.getZ() >> 4 ) != null )
{
return this.world.getTileEntity( pos ) instanceof TileController;
}
@@ -84,7 +84,7 @@ public class TileEnergyCell extends AENetworkTile implements IAEPowerStorage
private void changePowerLevel()
{
if( this.notLoaded() )
if( this.notLoaded() || this.isInvalid() )
{
return;
}
@@ -19,7 +19,9 @@
package appeng.tile.storage;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
@@ -48,10 +50,6 @@ import appeng.api.networking.ticking.TickingRequest;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor;
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.IItemList;
import appeng.api.util.AECableType;
@@ -68,7 +66,6 @@ import appeng.tile.inventory.AppEngInternalInventory;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.AdaptorItemHandler;
import appeng.util.inv.InvOperation;
@@ -79,10 +76,13 @@ import appeng.util.inv.filter.AEItemFilters;
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 AppEngInternalInventory inputCells = new AppEngInternalInventory( this, 6 );
private final AppEngInternalInventory outputCells = new AppEngInternalInventory( this, 6 );
private final AppEngInternalInventory inputCells = new AppEngInternalInventory( this, NUMBER_OF_CELL_SLOTS );
private final AppEngInternalInventory outputCells = new AppEngInternalInventory( this, NUMBER_OF_CELL_SLOTS );
private final IItemHandler combinedInventory = new WrapperChainedItemHandler( this.inputCells, this.outputCells );
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 YesNo lastRedstoneState;
private ItemStack currentCell;
private IMEInventory<IAEFluidStack> cachedFluid;
private IMEInventory<IAEItemStack> cachedItem;
private Map<IStorageChannel<?>, IMEInventory<?>> cachedInventories;
public TileIOPort()
{
@@ -106,7 +105,7 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
this.lastRedstoneState = YesNo.UNDECIDED;
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
@@ -277,87 +276,84 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
return TickRateModulation.IDLE;
}
long ItemsToMove = 256;
TickRateModulation ret = TickRateModulation.SLEEP;
long itemsToMove = 256;
switch( this.getInstalledUpgrades( Upgrades.SPEED ) )
{
case 1:
ItemsToMove *= 2;
itemsToMove *= 2;
break;
case 2:
ItemsToMove *= 4;
itemsToMove *= 4;
break;
case 3:
ItemsToMove *= 8;
itemsToMove *= 8;
break;
}
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();
for( int x = 0; x < 6; x++ )
for( int x = 0; x < NUMBER_OF_CELL_SLOTS; x++ )
{
final ItemStack is = this.inputCells.getStackInSlot( x );
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 ) );
final IMEInventory<IAEFluidStack> fluidInv = this.getInv( is,
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
if( this.manager.getSetting( Settings.OPERATION_MODE ) == OperationMode.EMPTY )
if( itemsToMove > 0 )
{
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,
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
continue;
}
if( fluidInv != null )
if( this.manager.getSetting( Settings.OPERATION_MODE ) == OperationMode.EMPTY )
{
ItemsToMove = this.transferContents( energy, fluidInv, fluidNet, ItemsToMove,
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
}
}
else
{
if( itemInv != null )
{
ItemsToMove = this.transferContents( energy, itemNet, itemInv, ItemsToMove,
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
}
if( fluidInv != null )
{
ItemsToMove = this.transferContents( energy, fluidNet, fluidInv, ItemsToMove,
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
itemsToMove = this.transferContents( energy, inv, network, itemsToMove, c );
}
else
{
itemsToMove = this.transferContents( energy, network, inv, itemsToMove, c );
}
shouldMove &= this.shouldMove( inv );
if( itemsToMove > 0 )
{
ret = TickRateModulation.IDLE;
}
else
{
ret = TickRateModulation.URGENT;
}
}
}
if( ItemsToMove > 0 && this.shouldMove( itemInv, fluidInv ) && !this.moveSlot( x ) )
{
return TickRateModulation.IDLE;
}
return TickRateModulation.URGENT;
if( itemsToMove > 0 && shouldMove && this.moveSlot( x ) )
{
ret = TickRateModulation.URGENT;
}
else
{
return TickRateModulation.URGENT;
ret = TickRateModulation.URGENT;
}
}
}
}
catch( final GridAccessException e )
{
return TickRateModulation.IDLE;
ret = TickRateModulation.IDLE;
}
// nothing left to do...
return TickRateModulation.SLEEP;
return ret;
}
@Override
@@ -366,23 +362,20 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
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 )
{
this.currentCell = is;
this.cachedFluid = AEApi.instance().registries().cell().getCellInventory( is, null,
AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
this.cachedItem = AEApi.instance().registries().cell().getCellInventory( is, null,
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
this.cachedInventories = new IdentityHashMap<>();
for( IStorageChannel<? extends IAEStack<?>> c : AEApi.instance().storage().storageChannels() )
{
this.cachedInventories.put( c, AEApi.instance().registries().cell().getCellInventory( is, null, c ) );
}
}
if( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) == chan )
{
return this.cachedItem;
}
return this.cachedFluid;
return this.cachedInventories.get( 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() );
}
itemsToMove *= chan.transferFactor();
boolean didStuff;
do
@@ -429,7 +424,7 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
if( extracted != null )
{
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 )
{
@@ -451,24 +446,16 @@ public class TileIOPort extends AENetworkInvTile implements IUpgradeableHost, IC
}
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 );
if( itemInv != null && fluidInv != null )
if( inv != null )
{
return this.matches( fm, itemInv ) && this.matches( fm, fluidInv );
}
else if( itemInv != null )
{
return this.matches( fm, itemInv );
}
else if( fluidInv != null )
{
return this.matches( fm, fluidInv );
return this.matches( fm, inv );
}
return true;
+16 -14
View File
@@ -1174,13 +1174,13 @@ public class Platform
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 );
if( itemToAdd > 0 )
{
energy.extractAEPower( stored, Actionable.MODULATE, PowerMultiplier.CONFIG );
energy.extractAEPower( stored / energyFactor, Actionable.MODULATE, PowerMultiplier.CONFIG );
if( itemToAdd < input.getStackSize() )
{
@@ -1296,11 +1296,11 @@ public class Platform
{
if( a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1 )
{
return false;
return true;
}
else if( a.getLastSecurityKey() == b.getLastSecurityKey() )
{
return false;
return true;
}
final boolean a_isSecure = isPowered( a.getGrid() ) && a.getLastSecurityKey() != -1;
@@ -1308,15 +1308,17 @@ public class Platform
if( AEConfig.instance().isFeatureEnabled( AEFeature.LOG_SECURITY_AUDITS ) )
{
AELog.info(
"Audit: " + a_isSecure + " : " + b_isSecure + " @ " + a.getLastSecurityKey() + " vs " + b.getLastSecurityKey() + " & " + a
.getPlayerID() + " vs " + b.getPlayerID() );
final String locationA = a.getGridBlock().isWorldAccessible() ? a.getGridBlock().getLocation().toString() : "notInWorld";
final String locationB = b.getGridBlock().isWorldAccessible() ? b.getGridBlock().getLocation().toString() : "notInWorld";
AELog.info( "Audit: Node A [isSecure=%b, key=%d, playerID=%d, location={%s}] vs Node B[isSecure=%b, key=%d, playerID=%d, location={%s}]",
a_isSecure, a.getLastSecurityKey(), a.getPlayerID(), locationA, b_isSecure, b.getLastSecurityKey(), b.getPlayerID(), locationB );
}
// can't do that son...
if( a_isSecure && b_isSecure )
{
return true;
return false;
}
if( !a_isSecure && b_isSecure )
@@ -1329,7 +1331,7 @@ public class Platform
return checkPlayerPermissions( a.getGrid(), b.getPlayerID() );
}
return false;
return true;
}
private static boolean isPowered( final IGrid grid )
@@ -1347,22 +1349,22 @@ public class Platform
{
if( grid == null )
{
return false;
return true;
}
final ISecurityGrid gs = grid.getCache( ISecurityGrid.class );
if( gs == null )
{
return false;
return true;
}
if( !gs.isAvailable() )
{
return false;
return true;
}
return !gs.hasPermission( playerID, SecurityPermissions.BUILD );
return gs.hasPermission( playerID, SecurityPermissions.BUILD );
}
public static void configurePlayer( final EntityPlayer player, final AEPartLocation side, final TileEntity tile )
@@ -180,10 +180,25 @@ public class ItemComparisonHelper
{
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 )
{
return left.equals( right );
}
return false;
}
}
@@ -164,7 +164,7 @@ final class AESharedItemStack implements Comparable<AESharedItemStack>
}
else
{
newDef.setItemDamage( 0 );
newDef.setItemDamage( 1 );
}
}
else
@@ -110,7 +110,7 @@
<body>
<div id="content">
<div id="header">
<h1>Custom Recipes</h1>
<h1>Custom Recipes [DEPRECATED]</h1>
</div>
<div id="body">
@@ -1,3 +1,9 @@
##########################################################
# DEPRECATED #
# Until vanilla/Forge JSON is capable of supporting most #
# of our use cases use CraftTweaker for custom recipes #
##########################################################
# Crash on Issues
crash=false
@@ -1,3 +1,9 @@
##########################################################
# DEPRECATED #
# Until vanilla/Forge JSON is capable of supporting most #
# of our use cases use CraftTweaker for custom recipes #
##########################################################
# Forge Ore Dictionary
# logWood, slabWood, stairWood, treeSapling, treeLeaves,
# oreGold, oreIron, oreLapis, oreDiamond, oreRedstone, oreEmerald, oreQuartz, oreCoal,
@@ -0,0 +1,7 @@
{
"variants": {
"normal": {
"model": "appliedenergistics2:debug/energy_gen"
}
}
}
@@ -42,20 +42,20 @@ tile.appliedenergistics2.sky_stone_small_brick.name=Малый кирпич не
tile.appliedenergistics2.sky_stone_chest.name=Сундук из небесного камня
tile.appliedenergistics2.smooth_sky_stone_chest.name=Сундук из блока небесного камня
tile.appliedenergistics2.sky_compass.name=Метеоритный компас
tile.appliedenergistics2.crafting_monitor.name=Монитор создания
tile.appliedenergistics2.crafting_storage_1k.name=1К хранилище создания
tile.appliedenergistics2.crafting_storage_4k.name=4К хранилище создания
tile.appliedenergistics2.crafting_storage_16k.name=16К хранилище создания
tile.appliedenergistics2.crafting_storage_64k.name=64К хранилище создания
tile.appliedenergistics2.crafting_accelerator.name=Блок обработки создания
tile.appliedenergistics2.crafting_unit.name=Блок создания
tile.appliedenergistics2.crafting_monitor.name=Монитор крафта
tile.appliedenergistics2.crafting_storage_1k.name=1К хранилище крафта
tile.appliedenergistics2.crafting_storage_4k.name=4К хранилище крафта
tile.appliedenergistics2.crafting_storage_16k.name=16К хранилище крафта
tile.appliedenergistics2.crafting_storage_64k.name=64К хранилище крафта
tile.appliedenergistics2.crafting_accelerator.name=Блок обработки крафта
tile.appliedenergistics2.crafting_unit.name=Блок крафта
tile.appliedenergistics2.molecular_assembler.name=Молекулярный сборщик
// Stairs
tile.appliedenergistics2.fluix_stairs.name=Изменчивые ступеньки
tile.appliedenergistics2.quartz_stairs.name=Ступеньки из резного истинного кварца
tile.appliedenergistics2.chiseled_quartz_stairs.name=Ступеньки из колонны истинного кварца
tile.appliedenergistics2.quartz_pillar_stairs.name=Ступеньки из истинного кварца
tile.appliedenergistics2.quartz_stairs.name=Ступеньки из истинного кварца
tile.appliedenergistics2.chiseled_quartz_stairs.name=Ступеньки из резного истинного кварца
tile.appliedenergistics2.quartz_pillar_stairs.name=Ступеньки из колонны истинного кварца
tile.appliedenergistics2.smooth_sky_stone_stairs.name=Ступеньки из блока небесного камня
tile.appliedenergistics2.sky_stone_brick_stairs.name=Ступеньки из кирпича небесного камня
tile.appliedenergistics2.sky_stone_small_brick_stairs.name=Ступеньки из малого кирпича небесного камня
@@ -73,14 +73,14 @@ tile.appliedenergistics2.sky_stone_slab.name=Плита из небесного
// Chat Messages
chat.appliedenergistics2.ChestCannotReadStorageCell=МЭ сундук не может прочитать ячейку хранения.
chat.appliedenergistics2.SettingCleared=Настройки сброшены.
chat.appliedenergistics2.SettingCleared=Карта памяти очищена.
chat.appliedenergistics2.OutOfRange=Беспроводная сеть вне зоны действия.
chat.appliedenergistics2.InvalidMachine=Неподходящий механизм.
chat.appliedenergistics2.LoadedSettings=Настройки успешно загружены.
chat.appliedenergistics2.DeviceNotPowered=Устройству недостаточно энергии.
chat.appliedenergistics2.DeviceNotWirelessTerminal=Устройство не беспроводной терминал.
chat.appliedenergistics2.DeviceNotWirelessTerminal=Это не беспроводной терминал.
chat.appliedenergistics2.DeviceNotLinked=Устройство не соединено.
chat.appliedenergistics2.StationCanNotBeLocated=Станция не может быть найдена.
chat.appliedenergistics2.StationCanNotBeLocated=Станция не найдена.
chat.appliedenergistics2.MachineNotPowered=Устройство без питания.
chat.appliedenergistics2.CommunicationError=Ошибка связи с сетью.
chat.appliedenergistics2.SavedSettings=Настройки успешно сохранены.
@@ -93,7 +93,7 @@ itemGroup.appliedenergistics2=Applied Energistics 2
itemGroup.appliedenergistics2.facades=Applied Energistics 2: Фасады
// GUI
gui.appliedenergistics2.CraftingTerminal=Терминал создания
gui.appliedenergistics2.CraftingTerminal=Терминал крафта
gui.appliedenergistics2.METunnel=МЭ
gui.appliedenergistics2.ItemTunnel=Предмет
gui.appliedenergistics2.FluidTunnel=Жидкость
@@ -106,17 +106,19 @@ gui.appliedenergistics2.PressureTunnel=Давление
gui.appliedenergistics2.security.extract.name=Забирать
gui.appliedenergistics2.security.inject.name=Класть
gui.appliedenergistics2.security.craft.name=Создавать
gui.appliedenergistics2.security.craft.name=Крафтить
gui.appliedenergistics2.security.build.name=Строить
gui.appliedenergistics2.security.security.name=Безопасность
gui.appliedenergistics2.security.extract.tip=Пользователю разрешено забирать предметы из хранилища.
gui.appliedenergistics2.security.inject.tip=Пользователю разрешено класть предметы в хранилище.
gui.appliedenergistics2.security.craft.tip=Пользователь может инициировать новое создание.
gui.appliedenergistics2.security.craft.tip=Пользователь может инициировать новый крафт.
gui.appliedenergistics2.security.build.tip=Пользователь может изменять физическую конфигурацию сети и менять настройки.
gui.appliedenergistics2.security.security.tip=Пользователь может работать с терминалом безопасности и настраивать его в сети.
gui.appliedenergistics2.Efficiency=Эффективность
gui.appliedenergistics2.SCSSize=SCS размер
gui.appliedenergistics2.SCSInvalid=SCS неправльный
gui.appliedenergistics2.RequiredPower=Требуется энергии
gui.appliedenergistics2.StoredPower=Накопленная энергия
gui.appliedenergistics2.MaxPower=Макс. энергия
@@ -168,81 +170,82 @@ gui.appliedenergistics2.Blank=Чистый
gui.appliedenergistics2.Unlinked=Не связанный
gui.appliedenergistics2.Linked=Связанный
gui.appliedenergistics2.StoredSize=Хранящиеся количество
gui.appliedenergistics2.CellId=id ячейки
gui.appliedenergistics2.SkyChest=Сундук из небесного камня
gui.appliedenergistics2.PatternTerminal=Терминал шаблонов
gui.appliedenergistics2.CraftingPattern=Создание шаблонов
gui.appliedenergistics2.CraftingPattern=Шаблон крафта
gui.appliedenergistics2.MolecularAssembler=Молекулярный сборщик
gui.appliedenergistics2.ProcessingPattern=Обработка шаблона
gui.appliedenergistics2.Crafts=Создаёт
gui.appliedenergistics2.And=и
gui.appliedenergistics2.Creates=Делает
gui.appliedenergistics2.With=из
gui.appliedenergistics2.Substitute=Использовать замену:
gui.appliedenergistics2.Substitute=Использовать замещение:
gui.appliedenergistics2.Yes=Да
gui.appliedenergistics2.No=Нет
gui.appliedenergistics2.InWorldCrafting=AE2 в мировом создании
gui.appliedenergistics2.inWorldFluix=Бросьте 1 заряженный истинный кварц + 1 кварц Нижнего мира + пыль красного камня в воду рядом друг с другом и немного подождите, чтобы получить 2 изменчивых кристалла.
gui.appliedenergistics2.inWorldPurification=Бросьте любое семя кристалла, сделанное из пыли кристалла и песок в лужу воды,; чтобы ускорить процесс добавьте ускорители роста кристаллов.
gui.appliedenergistics2.inWorldPurificationNether=Бросьте семя кварца Нижнего мира, которое делается из пыли кварца Нижнего мира, вместе с песком в лужу; чтобы ускорить процесс добавьте ускорители роста кристаллов.
gui.appliedenergistics2.inWorldPurificationFluix=Бросьте изменчивое семя, сделанное из изменчивой пыли, и песок в лужу; чтобы ускорить процесс добавьте ускорители роста кристаллов.
gui.appliedenergistics2.inWorldSingularity=Чтобы сделать, бросьте 1 сингулярность и 1 пыль Края и сделайте взрыв рядом с предметами.
gui.appliedenergistics2.ChargedQuartz=Заряженный истинный кварц создаётся с помощью установки не заряженного истинного кварца в зарядник, который подключен к питанию.
gui.appliedenergistics2.ChargedQuartzFind=Заряженный истинный кварц может быть найден в мире реже, чем истинный кварц, он выглядит как обычный истинный кварц, за исключением того, что он сверкает.
gui.appliedenergistics2.InWorldCrafting=AE2 в Мировом Крафте
gui.appliedenergistics2.inWorldFluix=Бросьте 1 заряженный истинный кварц + 1 кварц Нижнего мира + 1 пыль красного камня в воду и немного подождите, чтобы получить 2 изменчивых кристалла.
gui.appliedenergistics2.inWorldPurificationCertus=Бросьте любое семя кристалла, сделанное из пыли кристалла и песка в воду. Чтобы ускорить процесс, добавьте ускорители роста кристаллов.
gui.appliedenergistics2.inWorldPurificationNether=Бросьте семя кварца Нижнего мира, которое делается из пыли кварца Нижнего мира и песка в воду. Чтобы ускорить процесс, добавьте ускорители роста кристаллов.
gui.appliedenergistics2.inWorldPurificationFluix=Бросьте изменчивое семя, сделанное из изменчивой пыли и песка в воду. Чтобы ускорить процесс, добавьте ускорители роста кристаллов.
gui.appliedenergistics2.inWorldSingularity=Чтобы сделать запутанную сингулярность, бросьте 1 сингулярность и 1 пыль Края, а затем взорвите рядом с предметами что-нибудь.
gui.appliedenergistics2.ChargedQuartz=Заряженный истинный кварц создаётся при установке обычного истинного кварца в зарядник, подключенный к питанию.
gui.appliedenergistics2.ChargedQuartzFind=Заряженный истинный кварц встречается мире реже, чем истинный кварц. Выглядит как обычный истинный кварц, за исключением того, что он сверкает.
gui.appliedenergistics2.NoSecondOutput=Нет вторичного выхода
gui.appliedenergistics2.OfSecondOutput=Шанс вторичного выхода: %1$d%%
gui.appliedenergistics2.MultipleOutputs=%1$d%% вторичного, %2$d%% третичного выхода.
gui.appliedenergistics2.SelectAmount=Выбрать количество
gui.appliedenergistics2.CopyMode=Режим копирования
gui.appliedenergistics2.CopyModeDesc=Контролирует очищено ли содержимое панели конфигурации, когда ячейка была убрана.
gui.appliedenergistics2.CopyModeDesc=Контролирует, очищено ли содержимое панели конфигурации, если ячейка была убрана.
gui.appliedenergistics2.Next=Далее
gui.appliedenergistics2.Lumen=Люмен
gui.appliedenergistics2.Empty=Пустой
gui.appliedenergistics2.Stored=Хранится
gui.appliedenergistics2.Cancel=Отмена
gui.appliedenergistics2.ETAFormat=HH:mm:ss
gui.appliedenergistics2.Crafting=Создание
gui.appliedenergistics2.Crafting=Крафт
gui.appliedenergistics2.Scheduled=Запланировано
gui.appliedenergistics2.CraftingStatus=Статус создания
gui.appliedenergistics2.CraftingStatus=Статус крафта
gui.appliedenergistics2.FromStorage=Доступно
gui.appliedenergistics2.ToCraft=Необходимо создать
gui.appliedenergistics2.CraftingPlan=План создания
gui.appliedenergistics2.Automatic=Любой
gui.appliedenergistics2.ToCraft=Необходимо скрафтить
gui.appliedenergistics2.CraftingPlan=План крафта
gui.appliedenergistics2.Automatic=Автоматически
gui.appliedenergistics2.Start=Старт
gui.appliedenergistics2.Missing=Не хватает
gui.appliedenergistics2.Bytes=Хранилище
gui.appliedenergistics2.Simulation=Моделирование
gui.appliedenergistics2.CoProcessors=Сопроцессоры
gui.appliedenergistics2.CraftingCPU=ЦП создания
gui.appliedenergistics2.NoCraftingCPUs=Нет доступных ЦП создания
gui.appliedenergistics2.CalculatingWait=Вычисление, пожалуйста подождите...
gui.appliedenergistics2.CraftingCPU=ЦП крафта
gui.appliedenergistics2.NoCraftingCPUs=Нет доступных ЦП крафта
gui.appliedenergistics2.CalculatingWait=Вычисление. Пожалуйста, подождите...
gui.appliedenergistics2.Clean=Очистка
gui.appliedenergistics2.InvalidPattern=Неверный шаблон
gui.appliedenergistics2.InvalidPattern=Неправильный шаблон
gui.appliedenergistics2.Range=Дальность
gui.appliedenergistics2.TransparentFacades=Прозрачные фасады
gui.appliedenergistics2.TransparentFacadesHint=Контролирует видимость фасадов, когда сетевой инструмент находится на панели инструментов.
gui.appliedenergistics2.CPUs=ЦП
gui.appliedenergistics2.NoCraftingJobs=Нет активных заданий создания
gui.appliedenergistics2.NoCraftingJobs=Нет активных задач крафта
gui.appliedenergistics2.FacadeCrafting=Создание фасадов
gui.appliedenergistics2.inWorldCraftingPresses=С помощью метеоритного компаса можно отыскать метеориты, внутри которых можно найти прессы для высекателя
gui.appliedenergistics2.Included=Принимать,
gui.appliedenergistics2.Excluded=Не принимать,
gui.appliedenergistics2.inWorldCraftingPresses=С помощью метеоритного компаса можно отыскать метеориты, внутри которых можно найти прессы для высекателя.
gui.appliedenergistics2.Included=Принимать
gui.appliedenergistics2.Excluded=Не принимать
gui.appliedenergistics2.Partitioned=Размечена
gui.appliedenergistics2.Precise=точная
gui.appliedenergistics2.Fuzzy=нечёткая
gui.appliedenergistics2.Precise=Точная
gui.appliedenergistics2.Fuzzy=Неточная
gui.appliedenergistics2.SmallFontCraft=Сделать
gui.appliedenergistics2.LargeFontCraft=+
gui.appliedenergistics2.Nothing=Ничего
// GUI Tooltips
gui.tooltips.appliedenergistics2.Stash=Хранить предметы
gui.tooltips.appliedenergistics2.StashDesc=Возвращает предметы на сетку создания, в сетевое хранилище.
gui.tooltips.appliedenergistics2.StashDesc=Возвращает предметы на сетку крафта, в сетевое хранилище.
gui.tooltips.appliedenergistics2.Substitutions=Ore-Dict замещения
gui.tooltips.appliedenergistics2.SubstitutionsDescEnabled=Позволяет заменить вводимые компоненты.
gui.tooltips.appliedenergistics2.SubstitutionsDescDisabled=Запрещает заменить вводимые компоненты.
gui.tooltips.appliedenergistics2.SubstitutionsDescEnabled=Позволяет замещать вводимые компоненты.
gui.tooltips.appliedenergistics2.SubstitutionsDescDisabled=Запрещает замещать вводимые компоненты.
gui.tooltips.appliedenergistics2.SubstitutionsOn=Замещения включены
gui.tooltips.appliedenergistics2.SubstitutionsOff=Замещения выключены
gui.tooltips.appliedenergistics2.Encode=Закодировать шаблон
gui.tooltips.appliedenergistics2.EncodeDescription=Напишите введённый шаблон к текущему закодированному шаблону, или к доступному чистому шаблону.
gui.tooltips.appliedenergistics2.EncodeDescription=Запишите введённый шаблон на текущий закодированный шаблон, или на доступный чистый шаблон.
gui.tooltips.appliedenergistics2.FuzzyMode=Нечёткое сравнение
gui.tooltips.appliedenergistics2.FZPercent_25=Разделять урон с 25%
gui.tooltips.appliedenergistics2.FZPercent_50=Разделять урон с 50%
@@ -262,14 +265,14 @@ gui.tooltips.appliedenergistics2.RedstoneMode=Режим красного кам
gui.tooltips.appliedenergistics2.OperationMode=Режим работы
gui.tooltips.appliedenergistics2.NumberOfItems=Количество предметов
gui.tooltips.appliedenergistics2.ItemName=Имя предмета
gui.tooltips.appliedenergistics2.PowerUnits=Энергетические единицы
gui.tooltips.appliedenergistics2.PowerUnits=Единицы энергии
gui.tooltips.appliedenergistics2.IOMode=Режим ввода\вывода
gui.tooltips.appliedenergistics2.CondenserOutput=МЭ конденсатор - Выход
gui.tooltips.appliedenergistics2.PartitionStorage=Раздел хранения
gui.tooltips.appliedenergistics2.Clear=Очистить
gui.tooltips.appliedenergistics2.TrashController=Удаление по нажатию Shift/Пробел.
gui.tooltips.appliedenergistics2.InterfaceBlockingMode=Блокирующий режим
gui.tooltips.appliedenergistics2.InterfaceCraftingMode=Режим создания
gui.tooltips.appliedenergistics2.InterfaceCraftingMode=Режим крафта
gui.tooltips.appliedenergistics2.Trash=Уничтожить предметы
gui.tooltips.appliedenergistics2.MatterBalls=Конденсировать в шары материи\n%s за предмет
gui.tooltips.appliedenergistics2.Singularity=Конденсировать в сингулярности\n%s за предмет
@@ -286,6 +289,10 @@ gui.tooltips.appliedenergistics2.SearchMode_Auto=Автоматический п
gui.tooltips.appliedenergistics2.SearchMode_Standard=Обычный поиск
gui.tooltips.appliedenergistics2.SearchMode_JEIAuto=Автоматический JEI-синхронизированный поиск
gui.tooltips.appliedenergistics2.SearchMode_JEIStandard=Стандартный JEI-синхронизированный поиск
gui.tooltips.appliedenergistics2.SearchMode_AutoKeep=Авто поиск
gui.tooltips.appliedenergistics2.SearchMode_StandardKeep=Стандартный поиск
gui.tooltips.appliedenergistics2.SearchMode_JEIAutoKeep=JEI синхронизированный авто поиск
gui.tooltips.appliedenergistics2.SearchMode_JEIStandardKeep=JEI синхронизированный стандартный поиск
gui.tooltips.appliedenergistics2.SearchMode=Режим поля поиска
gui.tooltips.appliedenergistics2.PartitionStorageHint=Настраивает раздел на основе текущих хранящихся предметах.
gui.tooltips.appliedenergistics2.ClearSettings=Очистить настройки
@@ -295,9 +302,9 @@ gui.tooltips.appliedenergistics2.MoveWhenWorkIsDone=Сдвигать к выхо
gui.tooltips.appliedenergistics2.MoveWhenFull=Сдвигать к выходу, когда полный.
gui.tooltips.appliedenergistics2.Disabled=Отключено
gui.tooltips.appliedenergistics2.Enable=Включено
gui.tooltips.appliedenergistics2.Blocking=Не проталкивать предметы создания, если инвентарь содержит предметы.
gui.tooltips.appliedenergistics2.Blocking=Не проталкивать предметы крафта, если инвентарь содержит предметы.
gui.tooltips.appliedenergistics2.NonBlocking=Игнорировать содержимое целевого инвентаря.
gui.tooltips.appliedenergistics2.Craft=Режим создания
gui.tooltips.appliedenergistics2.Craft=Режим крафта
gui.tooltips.appliedenergistics2.CraftOnly=Не использовать хранящиеся предметы, только создавать предметы во время экспорта.
gui.tooltips.appliedenergistics2.CraftEither=Использовать хранящиеся предметы или создавать предметы во время экспорта.
gui.tooltips.appliedenergistics2.LevelType=Тип уровня
@@ -310,9 +317,9 @@ gui.tooltips.appliedenergistics2.TerminalStyle_Full=Полноэкранный
gui.tooltips.appliedenergistics2.TerminalStyle_Tall=Высокий отцентрированный терминал
gui.tooltips.appliedenergistics2.TerminalStyle_Small=Маленький отцентрированный терминал
gui.tooltips.appliedenergistics2.DoesntDespawn=Этот предмет не будет исчезать.
gui.tooltips.appliedenergistics2.EmitterMode=Режим излучатель создания
gui.tooltips.appliedenergistics2.CraftViaRedstone=Излучать сигнал красного камня для создания вещи.
gui.tooltips.appliedenergistics2.EmitWhenCrafting=Излучать сигнал красного камня при создании вещи.
gui.tooltips.appliedenergistics2.EmitterMode=Режим излучателя крафта
gui.tooltips.appliedenergistics2.CraftViaRedstone=Излучать сигнал красного камня для крафта вещи.
gui.tooltips.appliedenergistics2.EmitWhenCrafting=Излучать сигнал красного камня при крафте вещи.
gui.tooltips.appliedenergistics2.ReportInaccessibleItems=Сообщать о недоступных вещах
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=Да: Предметы, которые не могут быть извлечены, будут видны.
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=Нет: Только извлекаемые предметы будут видны.
@@ -321,8 +328,11 @@ gui.tooltips.appliedenergistics2.BlockPlacementYes=Блоки будут раз
gui.tooltips.appliedenergistics2.BlockPlacementNo=Блоки будут выпадать в виде предметов.
gui.tooltips.appliedenergistics2.SchedulingMode=Режим планирования
gui.tooltips.appliedenergistics2.SchedulingModeDefault=Экспорт первого предмета, пока сеть не пуста, затем других.
gui.tooltips.appliedenergistics2.SchedulingModeRoundRobin=Экспорт с использованием кругового режима.
gui.tooltips.appliedenergistics2.SchedulingModeRoundRobin=Экспорт с использованием повторяющегося по кругу режима.
gui.tooltips.appliedenergistics2.SchedulingModeRandom=Экспорт предметов в случайном порядке.
gui.tooltips.appliedenergistics2.FilterMode=Режим фильтрованого поиска
gui.tooltips.appliedenergistics2.FilterModeKeep=Восстановить предыдущий фильтр поиска.
gui.tooltips.appliedenergistics2.FilterModeClear=Очищать при каждом открытии.
gui.tooltips.appliedenergistics2.ItemsStored=Хранящиеся предметы: %s
gui.tooltips.appliedenergistics2.ItemsRequestable=Запрашиваемые предметы: %s
@@ -351,7 +361,7 @@ gui.appliedenergistics2.Black=Чёрный
gui.appliedenergistics2.Fluix=Изменчивый
// Waila
waila.appliedenergistics2.Crafting=Создание
waila.appliedenergistics2.Crafting=Крафт
waila.appliedenergistics2.DeviceOnline=Устройство включено
waila.appliedenergistics2.DeviceOffline=Устройство выключено
waila.appliedenergistics2.DeviceMissingChannel=У устройства отсутствует канал
@@ -365,6 +375,22 @@ waila.appliedenergistics2.P2PInputOneOutput=Связанный (Сторона
waila.appliedenergistics2.P2PInputManyOutputs=Связанный (Сторона ввода) - %d выводов
waila.appliedenergistics2.P2POutput=Связанный (Сторона вывода)
// TheOneProbe
theoneprobe.appliedenergistics2.crafting=Создается: %1$s
theoneprobe.appliedenergistics2.device_online=Устройство включено
theoneprobe.appliedenergistics2.device_offline=Устройство выключено
theoneprobe.appliedenergistics2.device_missing_channel=У устройства нет канала.
theoneprobe.appliedenergistics2.locked=Заблокировано
theoneprobe.appliedenergistics2.unlocked=Разблокировано
theoneprobe.appliedenergistics2.showing=Показывает
theoneprobe.appliedenergistics2.contains=Содержит
theoneprobe.appliedenergistics2.channels=Каналы: %1$d из %2$d
theoneprobe.appliedenergistics2.p2p_unlinked=Не связанный
theoneprobe.appliedenergistics2.p2p_input_one_output=Связанный (сторона ввода)
theoneprobe.appliedenergistics2.p2p_input_many_outputs=Связанный (сторона ввода) - %d выводов
theoneprobe.appliedenergistics2.p2p_output=Связанный (Сторона вывода)
theoneprobe.appliedenergistics2.stored_energy=%1$d / %2$d
// Items
item.appliedenergistics2.storage_cell_1k.name=1К МЭ ячейка хранения
item.appliedenergistics2.storage_cell_4k.name=4К МЭ ячейка хранения
@@ -432,18 +458,19 @@ item.appliedenergistics2.material.silicon_press.name=Кремниевый пре
item.appliedenergistics2.material.silicon_print.name=Отпечатанный кремний
item.appliedenergistics2.material.name_press.name=Именующий пресс для высекателя
item.appliedenergistics2.material.sky_dust.name=Пыль небесного камня
item.appliedenergistics2.material.card_crafting.name=Карта создания
item.appliedenergistics2.material.card_crafting.name=Карта крафта
item.appliedenergistics2.multi_part.annihilation_plane.name=МЭ плоскость истребления
item.appliedenergistics2.multi_part.identity_annihilation_plane.name=МЭ личная плоскость истребления
item.appliedenergistics2.multi_part.identity_annihilation_plane.name=МЭ id плоскость истребления
item.appliedenergistics2.multi_part.cable_anchor.name=Кабельный якорь
item.appliedenergistics2.multi_part.cable_covered.name=МЭ закрытый кабель
item.appliedenergistics2.multi_part.cable_glass.name=МЭ стеклянный кабель
item.appliedenergistics2.multi_part.cable_smart.name=МЭ умный кабель
item.appliedenergistics2.multi_part.cable_dense_smart.name=МЭ плотный кабель
item.appliedenergistics2.multi_part.cable_dense_covered.name=МЭ плотный закрытый кабель
item.appliedenergistics2.multi_part.cable_dense_smart.name=МЭ плотный умный кабель
item.appliedenergistics2.multi_part.storage_monitor.name=МЭ монитор хранения
item.appliedenergistics2.multi_part.conversion_monitor.name=МЭ монитор преобразования
item.appliedenergistics2.multi_part.crafting_terminal.name=МЭ терминал создания
item.appliedenergistics2.multi_part.crafting_terminal.name=МЭ терминал крафта
item.appliedenergistics2.multi_part.semi_dark_monitor.name=Осветительная панель
item.appliedenergistics2.multi_part.monitor.name=Яркая осветительная панель
item.appliedenergistics2.multi_part.dark_monitor.name=Тёмная осветительная панель
@@ -459,7 +486,7 @@ item.appliedenergistics2.multi_part.storage_bus.name=МЭ шина хранен
item.appliedenergistics2.multi_part.terminal.name=МЭ терминал
item.appliedenergistics2.multi_part.inverted_toggle_bus.name=МЭ инвертированная шина переключения
item.appliedenergistics2.multi_part.toggle_bus.name=МЭ шина переключения
item.appliedenergistics2.multi_part.crafting_monitor.name=МЭ монитор создания
item.appliedenergistics2.multi_part.crafting_monitor.name=МЭ монитор крафта
item.appliedenergistics2.multi_part.interface_terminal.name=МЭ терминал интерфейсов
item.appliedenergistics2.multi_part.invalid_type.name=Отключенный предмет
@@ -487,75 +514,77 @@ item.appliedenergistics2.paint_ball.name=Шар с краской
item.appliedenergistics2.portable_cell.name=Переносная ячейка
item.appliedenergistics2.network_tool.name=Сетевой инструмент
item.appliedenergistics2.charged_staff.name=Заряженный посох
item.appliedenergistics2.entropy_manipulator.name=Манипулятор энтропии
item.appliedenergistics2.entropy_manipulator.name=Манипулятор энтропией
item.appliedenergistics2.matter_cannon.name=Материальная пушка
item.appliedenergistics2.memory_card.name=Карта памяти
item.appliedenergistics2.color_applicator.name=Аппликатор цвета
item.appliedenergistics2.wireless_terminal.name=Беспроводной терминал
item.appliedenergistics2.biometric_card.name=Биометрическая карта
item.appliedenergistics2.debug_card.name=Разраб.отладочная карта
item.appliedenergistics2.debug_replicator_card.name=Разраб.карта-репликатор
item.appliedenergistics2.debug_card.name=Отладочная карта разработчика
item.appliedenergistics2.debug_replicator_card.name=Карта-репликатор разработчика
// Commands
commands.ae2.usage=Команды предоставляемые Applied Energistics 2 - используйте /ae2 list для списка и /ae2 help _____ для помощи с командой.
commands.ae2.permissions=Вы не имеете соответствующих прав для запуска этой команды.
commands.ae2.ChunkLogger=Переключает загрузку и разгрузку чанков в журнал сервера. ( Оператор )
commands.ae2.ChunkLoggerOn=Chunk Logging теперь включён
commands.ae2.ChunkLoggerOff=Chunk Logging теперь выключен
commands.ae2.Supporters=Отображает список жертвователей AE2
commands.ae2.ChunkLogger=Переключает загрузку и разгрузку чанков в журнал сервера. (OP)
commands.ae2.ChunkLoggerOn=Логирование чанков включено
commands.ae2.ChunkLoggerOff=Логирование чанков выключено
commands.ae2.Supporters=Отображает список поддержавших AE2
// Achievements
achievement.ae2.Compass=Охотник на метеориты
achievement.ae2.Compass.desc=Сделайте метеоритный компас
achievement.ae2.Presses=Неизвестная технология
achievement.ae2.Presses.desc=Найдите вычислительный пресс
achievement.ae2.SpatialIO=Пространственное координирование
achievement.ae2.SpatialIO.desc=Сделайте пространственный порт ввода\вывода
achievement.ae2.SpatialIOExplorer=Чтобы смело идти
achievement.ae2.SpatialIOExplorer.desc=Храните вещи в пространственной ячейки хранения
achievement.ae2.StorageCell=Лучше, чем сундуки
achievement.ae2.StorageCell.desc=Сделайте ячейку хранения
achievement.ae2.IOPort=Перемешка ячеек хранения
achievement.ae2.IOPort.desc=Сделайте порт ввода\вывода
achievement.ae2.CraftingTerminal=Большой верстак
achievement.ae2.CraftingTerminal.desc=Сделайте терминал создания
achievement.ae2.PatternTerminal=Маэстро создания
achievement.ae2.PatternTerminal.desc=Сделайте терминал шаблонов
achievement.ae2.ChargedQuartz=Шок
achievement.ae2.ChargedQuartz.desc=Найдите заряженный кварц
achievement.ae2.Fluix=Неестественные
achievement.ae2.Fluix.desc=Сделайте изменчивые кристаллы
achievement.ae2.Charger=Изменчивое производство
achievement.ae2.Charger.desc=Сделайте зарядник
achievement.ae2.CrystalGrowthAccelerator=Ускоритель - ещё мягко сказано
achievement.ae2.CrystalGrowthAccelerator.desc=Сделайте ускоритель роста кристаллов
achievement.ae2.GlassCable=Изменчивое энергетическое соединение
achievement.ae2.GlassCable.desc=Сделайте МЭ стеклянный кабель
achievement.ae2.Networking1=Сетевое подмастерье
achievement.ae2.Networking1.desc=Достигните 8 каналов, подключая устройства к сети.
achievement.ae2.Controller=Коммутатор сети
achievement.ae2.Controller.desc=Сделайте контроллер
achievement.ae2.Networking2=Сетевой инженер
achievement.ae2.Networking2.desc=Достигните 128 каналов, подключая устройства к сети.
achievement.ae2.Networking3=Сетевой администратор
achievement.ae2.Networking3.desc=Достигните 2048 каналов, подключая устройства к сети.
achievement.ae2.P2P=Сеть точка-точка
achievement.ae2.P2P.desc=Сделайте туннель точка-точка
achievement.ae2.Recursive=Рекурсивная сеть
achievement.ae2.Recursive.desc=Поставьте интерфейс на шину хранения.
achievement.ae2.CraftingCPU=Создание следующего поколения
achievement.ae2.CraftingCPU.desc=Сделайте блок создания
achievement.ae2.Facade=Сетевая эстетика
achievement.ae2.Facade.desc=Сделайте кабельный фасад
achievement.ae2.NetworkTool=Диагностика сети
achievement.ae2.NetworkTool.desc=Сделайте сетевой инструмент
achievement.ae2.PortableCell=Кочевник с хранилищем
achievement.ae2.PortableCell.desc=Сделайте переносную ячейку
achievement.ae2.StorageBus=Безграничный потенциал
achievement.ae2.StorageBus.desc=Сделайте шину хранения
achievement.ae2.QNB=Квантовое туннелирование
achievement.ae2.QNB.desc=Сделайте квантовое соединение
achievement.ae2.Root=Applied Energistics! Падите ниц!
achievement.ae2.Root.desc=Когда сундука уже не хватает...
achievement.ae2.Compass=Охотник за метеоритами!
achievement.ae2.Compass.desc=Сделайте метеоритный компас!
achievement.ae2.Presses=Неведомая технология!
achievement.ae2.Presses.desc=Найдите вычислительный пресс!
achievement.ae2.SpatialIO=Пространственное координирование!
achievement.ae2.SpatialIO.desc=Сделайте пространственный порт ввода\вывода!
achievement.ae2.SpatialIOExplorer=Чтобы смело идти...
achievement.ae2.SpatialIOExplorer.desc=Храните вещи в пространственной ячейке хранения!
achievement.ae2.StorageCell=Лучше, чем сундуки!
achievement.ae2.StorageCell.desc=Сделайте ячейку хранения!
achievement.ae2.IOPort=Перемешка ячеек хранения!
achievement.ae2.IOPort.desc=Сделайте порт ввода\вывода!
achievement.ae2.CraftingTerminal=(Очень) Большой верстак!
achievement.ae2.CraftingTerminal.desc=Сделайте терминал крафта!
achievement.ae2.PatternTerminal=Маэстро крафта!
achievement.ae2.PatternTerminal.desc=Сделайте терминал шаблонов!
achievement.ae2.ChargedQuartz=Шок! Сенсация!
achievement.ae2.ChargedQuartz.desc=Найдите заряженный кварц!
achievement.ae2.Fluix=Неестественно!
achievement.ae2.Fluix.desc=Сделайте изменчивые кристаллы!
achievement.ae2.Charger=Изменчивое производство!
achievement.ae2.Charger.desc=Сделайте зарядник!
achievement.ae2.CrystalGrowthAccelerator=Ускоритель - ещё мягко сказано!
achievement.ae2.CrystalGrowthAccelerator.desc=Сделайте ускоритель роста кристаллов!
achievement.ae2.GlassCable=Изменчивое энергетическое соединение!
achievement.ae2.GlassCable.desc=Сделайте МЭ стеклянный кабель!
achievement.ae2.Networking1=Сетевое подмастерье!
achievement.ae2.Networking1.desc=Достигните 8 каналов, подключая устройства к сети!
achievement.ae2.Controller=Коммутатор сети!
achievement.ae2.Controller.desc=Сделайте контроллер!
achievement.ae2.Networking2=Сетевой инженер!
achievement.ae2.Networking2.desc=Достигните 128 каналов, подключая устройства к сети!
achievement.ae2.Networking3=Сетевой администратор!
achievement.ae2.Networking3.desc=Достигните 2048 каналов, подключая устройства к сети!
achievement.ae2.P2P=Сеть Р2Р!
achievement.ae2.P2P.desc=Сделайте туннель Р2Р!
achievement.ae2.Recursive=Рекурсивная сеть!
achievement.ae2.Recursive.desc=Поставьте интерфейс на шину хранения!
achievement.ae2.CraftingCPU=Некст-ген крафтинг!
achievement.ae2.CraftingCPU.desc=Сделайте блок крафта!
achievement.ae2.Facade=Сетевая эстетика!
achievement.ae2.Facade.desc=Сделайте кабельный фасад!
achievement.ae2.NetworkTool=Диагностика сети!
achievement.ae2.NetworkTool.desc=Сделайте сетевой инструмент!
achievement.ae2.PortableCell=Кочевник с хранилищем!
achievement.ae2.PortableCell.desc=Сделайте переносную ячейку!
achievement.ae2.StorageBus=Безграничный потенциал!
achievement.ae2.StorageBus.desc=Сделайте шину хранения!
achievement.ae2.QNB=Квантовое туннелирование!
achievement.ae2.QNB.desc=Сделайте квантовое соединение!
// Stats
stat.ae2.ItemsInserted=Предметов добавлено в МЭ хранилище
@@ -1,79 +1,108 @@
tile.appliedenergistics2.BlockCableBus.name=AE2線纜和(或)總線
tile.appliedenergistics2.BlockCellWorkbench.name=元件工作臺
tile.appliedenergistics2.BlockCharger.name=充能器
tile.appliedenergistics2.BlockChest.name=ME箱子
tile.appliedenergistics2.BlockCondenser.name=物質聚合器
tile.appliedenergistics2.BlockController.name=ME控制
// 方塊
tile.appliedenergistics2.cable_bus.name=ae2線纜和/或總線
tile.appliedenergistics2.cell_workbench.name=元件工作臺
tile.appliedenergistics2.charger.name=充能器
tile.appliedenergistics2.chest.name=me箱子
tile.appliedenergistics2.condenser.name=物質聚合
tile.appliedenergistics2.controller.name=ME控制器
tile.appliedenergistics2.crank.name=木質曲柄
tile.appliedenergistics2.BlockCreativeEnergyCell.name=創造型能源元件
tile.appliedenergistics2.BlockDenseEnergyCell.name=致密型能源元件
tile.appliedenergistics2.BlockEnergyCell.name=能源元件
tile.appliedenergistics2.BlockDrive.name=ME驅動器
tile.appliedenergistics2.BlockEnergyAcceptor.name=能源接收器
tile.appliedenergistics2.creative_energy_cell.name=創造型能源元件
tile.appliedenergistics2.dense_energy_cell.name=致密型能源元件
tile.appliedenergistics2.energy_cell.name=能源元件
tile.appliedenergistics2.drive.name=me驅動器
tile.appliedenergistics2.energy_acceptor.name=能源接收器
tile.appliedenergistics2.grindstone.name=石英磨具
tile.appliedenergistics2.BlockMatrixFrame.name=矩陣框架
tile.appliedenergistics2.BlockIOPort.name=ME-IO端口
tile.appliedenergistics2.BlockInscriber.name=壓印器
tile.appliedenergistics2.BlockInterface.name=ME接口
tile.appliedenergistics2.BlockQuantumLinkChamber.name=ME量子鏈接倉
tile.appliedenergistics2.BlockQuantumRing.name=ME量子環
tile.appliedenergistics2.fluix_block.name=福魯伊克斯
tile.appliedenergistics2.quartz_block.name=賽特斯石英
tile.appliedenergistics2.chiseled_quartz_block.name=鏨制賽特斯石英
tile.appliedenergistics2.matrix_frame.name=矩陣框架
tile.appliedenergistics2.io_port.name=ME-IO端口
tile.appliedenergistics2.inscriber.name=壓印器
tile.appliedenergistics2.interface.name=me接口
tile.appliedenergistics2.quantum_link_chamber.name=ME量子鏈接倉
tile.appliedenergistics2.quantum_ring.name=me量子環
tile.appliedenergistics2.fluix_block.name=福魯伊克斯
tile.appliedenergistics2.quartz_block.name=賽特斯石英
tile.appliedenergistics2.chiseled_quartz_block.name=鏨制賽特斯石英
tile.appliedenergistics2.quartz_glass.name=石英玻璃
tile.appliedenergistics2.quartz_vibrant_glass.name=聚能石英玻璃
tile.appliedenergistics2.quartz_pillar.name=賽特斯豎紋石英塊
tile.appliedenergistics2.quartz_fixture.name=充能石英火把
tile.appliedenergistics2.light_detector.name=光亮感應器
tile.appliedenergistics2.BlockSpatialIOPort.name=空間IO端口
tile.appliedenergistics2.BlockSpatialPylon.name=空間塔
tile.appliedenergistics2.BlockTinyTNT.name=迷你TNT
tile.appliedenergistics2.BlockVibrationChamber.name=諧振倉
tile.appliedenergistics2.BlockWireless.name=ME無線訪問點
tile.appliedenergistics2.quartz_ore.name=賽特斯石英礦
tile.appliedenergistics2.charged_quartz_ore.name=充能賽特斯石英礦
tile.appliedenergistics2.BlockSecurity.name=ME安全終端
tile.appliedenergistics2.BlockQuartzGrowthAccelerator.name=晶體催生器
tile.appliedenergistics2.sky_stone_block.name=隕石
tile.appliedenergistics2.smooth_sky_stone_block.name=隕石塊
tile.appliedenergistics2.sky_stone_brick.name=隕石
tile.appliedenergistics2.sky_stone_small_brick.name=隕石磚
tile.appliedenergistics2.sky_stone_chest.name=隕石箱子
tile.appliedenergistics2.smooth_sky_stone_chest.name=隕石塊箱子
tile.appliedenergistics2.spatial_io_port.name=空間IO端口
tile.appliedenergistics2.spatial_pylon.name=空間塔
tile.appliedenergistics2.tiny_tnt.name=迷你TNT
tile.appliedenergistics2.vibration_chamber.name=諧振倉
tile.appliedenergistics2.wireless_access_point.name=ME無線訪問點
tile.appliedenergistics2.quartz_ore.name=賽特斯石英礦
tile.appliedenergistics2.charged_quartz_ore.name=充能賽特斯石英礦
tile.appliedenergistics2.security_station.name=me安全終端
tile.appliedenergistics2.quartz_growth_accelerator.name=晶體催生器
tile.appliedenergistics2.sky_stone_block.name=隕石
tile.appliedenergistics2.smooth_sky_stone_block.name=平滑隕石塊
tile.appliedenergistics2.sky_stone_brick.name=隕石磚
tile.appliedenergistics2.sky_stone_small_brick.name=隕石
tile.appliedenergistics2.sky_stone_chest.name=隕石箱子
tile.appliedenergistics2.smooth_sky_stone_chest.name=平滑隕石塊箱子
tile.appliedenergistics2.sky_compass.name=隕石羅盤
tile.appliedenergistics2.BlockCraftingMonitor.name=合成監控器
tile.appliedenergistics2.BlockCraftingStorage.name=1k合成存儲器
tile.appliedenergistics2.BlockCraftingStorage4k.name=4k合成存儲器
tile.appliedenergistics2.BlockCraftingStorage16k.name=16k合成存儲器
tile.appliedenergistics2.BlockCraftingStorage64k.name=64k合成存儲器
tile.appliedenergistics2.BlockCraftingAccelerator.name=合成并行處理器
tile.appliedenergistics2.BlockCraftingUnit.name=合成處理器
tile.appliedenergistics2.BlockMolecularAssembler.name=分子集成室
tile.appliedenergistics2.crafting_monitor.name=合成監控器
tile.appliedenergistics2.crafting_storage.name=1k合成存儲器
tile.appliedenergistics2.crafting_storage_4k.name=4k合成存儲器
tile.appliedenergistics2.crafting_storage_16k.name=16k合成存儲器
tile.appliedenergistics2.crafting_storage_64k.name=64k合成存儲器
tile.appliedenergistics2.crafting_accelerator.name=合成并行處理器
tile.appliedenergistics2.crafting_unit.name=合成處理器
tile.appliedenergistics2.molecular_assembler.name=分子集成室
chat.appliedenergistics2.ChestCannotReadStorageCell=ME箱子無法讀取存儲元件.
chat.appliedenergistics2.SettingCleared=設置已清除.
chat.appliedenergistics2.OutOfRange=超出無線信號范圍.
chat.appliedenergistics2.InvalidMachine=無效機器.
chat.appliedenergistics2.LoadedSettings=成功載入設定.
chat.appliedenergistics2.DeviceNotPowered=設備供能不足.
chat.appliedenergistics2.MachineNotPowered=機器未供能.
chat.appliedenergistics2.CommunicationError=網絡交互錯誤.
chat.appliedenergistics2.SavedSettings=成功保存設定.
chat.appliedenergistics2.AmmoDepleted=彈藥告罄.
chat.appliedenergistics2.isNowLocked=監控器已鎖定.
chat.appliedenergistics2.isNowUnlocked=監控器已解鎖.
// 階梯
tile.appliedenergistics2.fluix_stairs.name=福魯伊克斯階梯
tile.appliedenergistics2.quartz_stairs.name=賽特斯石英階梯
tile.appliedenergistics2.chiseled_quartz_stairs.name=鏨制賽特斯石英階梯
tile.appliedenergistics2.quartz_pillar_stairs.name=賽特斯豎紋石英階梯
tile.appliedenergistics2.smooth_sky_stone_stairs.name=平滑隕石塊階梯
tile.appliedenergistics2.sky_stone_brick_stairs.name=隕石磚階梯
tile.appliedenergistics2.sky_stone_small_brick_stairs.name=隕石細磚階梯
tile.appliedenergistics2.sky_stone_stairs.name=隕石磚階梯
// 半磚
tile.appliedenergistics2.chiseled_quartz_slab.name=鏨制賽特斯石英半磚
tile.appliedenergistics2.fluix_slab.name=魯伊克斯半磚
tile.appliedenergistics2.quartz_pillar_slab.name=賽特斯豎紋石英半磚
tile.appliedenergistics2.quartz_slab.name=賽特斯石英半磚
tile.appliedenergistics2.smooth_sky_stone_slab.name=平滑隕石塊半磚
tile.appliedenergistics2.sky_stone_brick_slab.name=隕石磚半磚
tile.appliedenergistics2.sky_stone_small_brick_slab.name=隕石細磚半磚
tile.appliedenergistics2.sky_stone_slab.name=隕石磚半磚
// 聊天欄信息
chat.appliedenergistics2.ChestCannotReadStorageCell=ME箱子無法讀取存儲元件。
chat.appliedenergistics2.SettingCleared=設置已清除。
chat.appliedenergistics2.OutOfRange=超出無線信號範圍。
chat.appliedenergistics2.InvalidMachine=無效機器。
chat.appliedenergistics2.LoadedSettings=成功載入設定。
chat.appliedenergistics2.DeviceNotPowered=設備供能不足。
chat.appliedenergistics2.DeviceNotWirelessTerminal=設備不是無線終端。
chat.appliedenergistics2.DeviceNotLinked=設備未鏈接。
chat.appliedenergistics2.StationCanNotBelocated=終端無法定位。
chat.appliedenergistics2.MachineNotPowered=機器未供能。
chat.appliedenergistics2.CommunicationError=網絡交互錯誤。
chat.appliedenergistics2.SavedSettings=成功保存設定。
chat.appliedenergistics2.AmmoDepleted=彈藥耗盡。
chat.appliedenergistics2.isNowLocked=監控器已鎖定。
chat.appliedenergistics2.isNowUnlocked=監控器已解鎖。
// 創造模式標籤
itemGroup.appliedenergistics2=應用能源2
itemGroup.appliedenergistics2.facades=應用能源2-偽裝板
// GUI
gui.appliedenergistics2.CraftingTerminal=合成終端
gui.appliedenergistics2.METunnel=ME
gui.appliedenergistics2.ItemTunnel=物品
gui.appliedenergistics2.FluidTunnel=
gui.appliedenergistics2.FluidTunnel=
gui.appliedenergistics2.RedstoneTunnel=紅石
gui.appliedenergistics2.EUTunnel=EU
gui.appliedenergistics2.FETunnel=FE
gui.appliedenergistics2.LightTunnel=光
gui.appliedenergistics2.OCTunnel=開放式電腦
gui.appliedenergistics2.PressureTunnel=壓力
gui.appliedenergistics2.security.extract.name=取出
gui.appliedenergistics2.security.inject.name=存入
@@ -81,13 +110,15 @@ gui.appliedenergistics2.security.craft.name=合成
gui.appliedenergistics2.security.build.name=構建
gui.appliedenergistics2.security.security.name=安全
gui.appliedenergistics2.security.extract.tip=允許用戶從存儲空間中移除物品.
gui.appliedenergistics2.security.inject.tip=允許用戶向存儲空間中存入新物品.
gui.appliedenergistics2.security.craft.tip=用戶可以初始化新的合成.
gui.appliedenergistics2.security.build.tip=用戶可以修改網絡的物理結構,并調整配置.
gui.appliedenergistics2.security.security.tip=用戶可以訪問修改網絡的安全終端.
gui.appliedenergistics2.security.extract.tip=允許用戶從存儲空間中移除物品
gui.appliedenergistics2.security.inject.tip=允許用戶向存儲空間中存入新物品
gui.appliedenergistics2.security.craft.tip=用戶可以初始化新的合成
gui.appliedenergistics2.security.build.tip=用戶可以修改網絡的物理結構并調整配置
gui.appliedenergistics2.security.security.tip=用戶可以訪問修改網絡的安全終端
gui.appliedenergistics2.Efficiency=效率
gui.appliedenergistics2.SCSSize=SCS大小
gui.appliedenergistics2.SCSInvalid=無效
gui.appliedenergistics2.RequiredPower=所需能源
gui.appliedenergistics2.StoredPower=現存能源
gui.appliedenergistics2.MaxPower=最大能源
@@ -126,18 +157,20 @@ gui.appliedenergistics2.StoredEnergy=已存儲能源
gui.appliedenergistics2.StoredItems=已存儲物品
gui.appliedenergistics2.Terminal=終端
gui.appliedenergistics2.InterfaceTerminal=接口終端
gui.appliedenergistics2.InterfaceTerminalHint=在接口終端上顯示或隱藏。
gui.appliedenergistics2.FormationPlane=輸出面板
gui.appliedenergistics2.VibrationChamber=諧振倉
gui.appliedenergistics2.NetworkDetails=網絡信息
gui.appliedenergistics2.StorageCells=ME存儲元件
gui.appliedenergistics2.IOBuses=ME輸入/輸出總線
gui.appliedenergistics2.Stores=Stores
gui.appliedenergistics2.Stores=儲藏
gui.appliedenergistics2.BytesUsed=字節已使用
gui.appliedenergistics2.Types=類型
gui.appliedenergistics2.Blank=空白
gui.appliedenergistics2.Unlinked=未鏈接
gui.appliedenergistics2.Linked=已鏈接
gui.appliedenergistics2.StoredSize=存儲空間大小
gui.appliedenergistics2.CellId=元件ID
gui.appliedenergistics2.SkyChest=隕石箱子
gui.appliedenergistics2.PatternTerminal=樣板終端
gui.appliedenergistics2.CraftingPattern=合成樣板
@@ -147,23 +180,29 @@ gui.appliedenergistics2.Crafts=合成
gui.appliedenergistics2.And=與
gui.appliedenergistics2.Creates=創造
gui.appliedenergistics2.With=使用
gui.appliedenergistics2.Substitute=使用替代:
gui.appliedenergistics2.Yes=是
gui.appliedenergistics2.No=否
gui.appliedenergistics2.InWorldCrafting=AE2在世界中的合成
gui.appliedenergistics2.inWorldFluix=將1個充能賽特斯石英水晶,1個下界石英和1個紅石,相繼扔進同一格水里,并等待一會兒.
gui.appliedenergistics2.inWorldPurificationCertus=用賽特斯石英粉和沙子制作賽特斯石英種子,并扔進水里;使用晶體催生器可以讓這個過程變得更快.
gui.appliedenergistics2.inWorldPurificationNether=用下界石英粉和沙子制作下界石英種子,并扔進水里;使用晶體催生器可以讓這個過程變得更快.
gui.appliedenergistics2.inWorldPurificationFluix=用福魯伊克斯粉和沙子制作福魯伊克斯種子,并扔進水里;使用晶體催生器可以讓這個過程變得更快.
gui.appliedenergistics2.inWorldSingularity=將1個奇點和一個末影珍珠粉仍在地上,并用爆炸性物品引爆.
gui.appliedenergistics2.ChargedQuartz=將未充能賽特斯石英插入充能器充能后,可以得到充能賽特斯石英.
gui.appliedenergistics2.OfSecondOutput=%1$d%% 的幾率得到副產物.
gui.appliedenergistics2.NoSecondOutput=無副產物.
gui.appliedenergistics2.inWorldFluix=將1個充能賽特斯石英水晶,1個地獄石英和1個紅石,相繼扔進同一格水里,并等待一會兒
gui.appliedenergistics2.inWorldPurificationCertus=用賽特斯石英粉和沙子制作賽特斯石英種子,并扔進水里;使用晶體催生器可以讓這個過程變得更快
gui.appliedenergistics2.inWorldPurificationNether=用地獄石英粉和沙子制作地獄石英種子,并扔進水里;使用晶體催生器可以讓這個過程變得更快
gui.appliedenergistics2.inWorldPurificationFluix=用福魯伊克斯粉和沙子制作福魯伊克斯種子,并扔進水里;使用晶體催生器可以讓這個過程變得更快
gui.appliedenergistics2.inWorldSingularity=將1個奇點和一個終界珍珠粉仍在地上,并用爆炸性物品引爆
gui.appliedenergistics2.ChargedQuartz=將未充能賽特斯石英插入充能器充能后,可以得到充能賽特斯石英
gui.appliedenergistics2.ChargedQuartzFind=充能賽特斯石英在世界上很少能找到,它看起來類似於正常的賽特斯石英,除了閃閃發光。
gui.appliedenergistics2.NoSecondOutput=無副產物
gui.appliedenergistics2.OfSecondOutput=%1$d%%的幾率得到副產物。
gui.appliedenergistics2.MultipleOutputs=%1$d%%的幾率得到第一副產物,%2$d%%的幾率得到第二副產物。
gui.appliedenergistics2.SelectAmount=選擇數量
gui.appliedenergistics2.CopyMode=復制模式
gui.appliedenergistics2.CopyModeDesc=控制當取出存儲元件時,是否清空配置格.
gui.appliedenergistics2.CopyMode=複製模式
gui.appliedenergistics2.CopyModeDesc=控制當取出存儲元件時,是否清空配置格
gui.appliedenergistics2.Next=下一頁
gui.appliedenergistics2.Lumen=光通
gui.appliedenergistics2.Empty=空
gui.appliedenergistics2.Stored=現存
gui.appliedenergistics2.Cancel=取消
gui.appliedenergistics2.ETAFormat=小時:分鐘:秒
gui.appliedenergistics2.Crafting=正在合成
gui.appliedenergistics2.Scheduled=計劃合成
gui.appliedenergistics2.CraftingStatus=合成狀態
@@ -177,15 +216,32 @@ gui.appliedenergistics2.Bytes=可存儲
gui.appliedenergistics2.Simulation=Simulation
gui.appliedenergistics2.CoProcessors=并行處理器
gui.appliedenergistics2.CraftingCPU=合成CPU
gui.appliedenergistics2.NoCraftingCPUs=沒有可用的合成CPU...
gui.appliedenergistics2.CalculatingWait=正在計算,請等待...
gui.appliedenergistics2.NoCraftingCPUs=沒有可用的合成CPU……
gui.appliedenergistics2.CalculatingWait=正在計算請等待……
gui.appliedenergistics2.Clean=清空
gui.appliedenergistics2.InvalidPattern=無效樣板
gui.appliedenergistics2.Range=範圍
gui.appliedenergistics2.TransparentFacades=透明的外牆
gui.appliedenergistics2.TransparentFacadesHint=在網絡工具位於工具欄上時控制外觀的可見性。
gui.appliedenergistics2.CPUs=中央處理器
gui.appliedenergistics2.NoCraftingJobs=沒有合成工作啟動
gui.appliedenergistics2.FacadeCrafting=門面製作
gui.appliedenergistics2.inWorldCraftingPresses=在世界各地可以找到的隕石的中心找到壓印模板,他們可以通過使用隕石羅盤找到。
gui.appliedenergistics2.Included=包括
gui.appliedenergistics2.Excluded=排除
gui.appliedenergistics2.Partitioned=分區
gui.appliedenergistics2.Precise=精確
gui.appliedenergistics2.Fuzzy=模糊
gui.appliedenergistics2.SmallFontCraft=合成
gui.appliedenergistics2.LargeFontCraft=+
gui.appliedenergistics2.Nothing=沒有
// GUI Tooltips
gui.tooltips.appliedenergistics2.Stash=存儲物品
gui.tooltips.appliedenergistics2.StashDesc=將合成槽的物品返回網絡
gui.tooltips.appliedenergistics2.StashDesc=將合成槽的物品返回網絡
gui.tooltips.appliedenergistics2.Substitutions=礦物詞典替換
gui.tooltips.appliedenergistics2.SubstitutionsDesc=為輸入組件編輯替換選項
gui.tooltips.appliedenergistics2.SubstitutionsDesc=允許為輸入組件編輯替換選項
gui.tooltips.appliedenergistics2.SubstitutionsDescDisabled=避免為輸入組件編輯替換選項。
gui.tooltips.appliedenergistics2.SubstitutionsOn=啟用替換
gui.tooltips.appliedenergistics2.SubstitutionsOff=禁用替換
gui.tooltips.appliedenergistics2.Encode=編碼樣板
@@ -214,7 +270,7 @@ gui.tooltips.appliedenergistics2.IOMode=輸入/輸出模式
gui.tooltips.appliedenergistics2.CondenserOutput=ME聚合器-輸出
gui.tooltips.appliedenergistics2.PartitionStorage=分區存儲
gui.tooltips.appliedenergistics2.Clear=清除
gui.tooltips.appliedenergistics2.TrashController=通過按下shift或空格點擊刪除.
gui.tooltips.appliedenergistics2.TrashController=通過按下shift或空格點擊刪除
gui.tooltips.appliedenergistics2.InterfaceBlockingMode=阻擋模式
gui.tooltips.appliedenergistics2.InterfaceCraftingMode=合成模式
gui.tooltips.appliedenergistics2.Trash=銷毀物品
@@ -227,41 +283,65 @@ gui.tooltips.appliedenergistics2.AlwaysActive=總是激活
gui.tooltips.appliedenergistics2.ActiveWithoutSignal=無信號時激活
gui.tooltips.appliedenergistics2.ActiveWithSignal=有信號時激活
gui.tooltips.appliedenergistics2.ActiveOnPulse=有脈沖信號時激活
gui.tooltips.appliedenergistics2.EmitLevelsBelow=當容量標準小于等于設定限制時發出信號.
gui.tooltips.appliedenergistics2.EmitLevelAbove=當容量標準大于等于設定限制時發出信號.
gui.tooltips.appliedenergistics2.EmitLevelsBelow=當容量標準小于等于設定限制時發出信號
gui.tooltips.appliedenergistics2.EmitLevelAbove=當容量標準大于等于設定限制時發出信號
gui.tooltips.appliedenergistics2.SearchMode_Auto=自動搜索
gui.tooltips.appliedenergistics2.SearchMode_Standard=標準搜索
gui.tooltips.appliedenergistics2.SearchMode_NEIAuto=NEI自動同步
gui.tooltips.appliedenergistics2.SearchMode_NEIStandard=NEI標準同步
gui.tooltips.appliedenergistics2.SearchMode_JEIAuto=JEI自動同步
gui.tooltips.appliedenergistics2.SearchMode_JEIStandard=JEI標準同步
gui.tooltips.appliedenergistics2.SearchMode_AutoKeep=自動搜索保持
gui.tooltips.appliedenergistics2.SearchMode_StandardKeep=標準搜索保持
gui.tooltips.appliedenergistics2.SearchMode_JEIAutoKeep=JEI同步自動保持
gui.tooltips.appliedenergistics2.SearchMode_JEIStandardKeep=JEI同步標准保持
gui.tooltips.appliedenergistics2.SearchMode=搜索框模式
gui.tooltips.appliedenergistics2.PartitionStorageHint=基于當前已存儲物品進行分區編輯.
gui.tooltips.appliedenergistics2.PartitionStorageHint=基于當前已存儲物品進行分區編輯
gui.tooltips.appliedenergistics2.ClearSettings=清除配置
gui.tooltips.appliedenergistics2.Craftable=可合成
gui.tooltips.appliedenergistics2.MoveWhenEmpty=當元件為空時移動至輸出口.
gui.tooltips.appliedenergistics2.MoveWhenWorkIsDone=當工序完成移動至輸出口.
gui.tooltips.appliedenergistics2.MoveWhenFull=當元件裝滿時移動至輸出口.
gui.tooltips.appliedenergistics2.MoveWhenEmpty=當元件為空時移動至輸出口
gui.tooltips.appliedenergistics2.MoveWhenWorkIsDone=當工序完成移動至輸出口
gui.tooltips.appliedenergistics2.MoveWhenFull=當元件裝滿時移動至輸出口
gui.tooltips.appliedenergistics2.Disabled=禁用
gui.tooltips.appliedenergistics2.Enable=啟用
gui.tooltips.appliedenergistics2.Blocking=當物品欄內有物品時不推送合成物品.
gui.tooltips.appliedenergistics2.NonBlocking=忽略目標物品欄的內容.
gui.tooltips.appliedenergistics2.Craft=輸出時若有需要則合成物品.
gui.tooltips.appliedenergistics2.CraftOnly=不使用已存儲物品,只輸出合成物品.
gui.tooltips.appliedenergistics2.CraftEither=輸出時使用已存儲物品或合成物品.
gui.tooltips.appliedenergistics2.Blocking=當物品欄內有物品時不推送合成物品
gui.tooltips.appliedenergistics2.NonBlocking=忽略目標物品欄的內容
gui.tooltips.appliedenergistics2.Craft=輸出時若有需要則合成物品
gui.tooltips.appliedenergistics2.CraftOnly=不使用已存儲物品只輸出合成物品
gui.tooltips.appliedenergistics2.CraftEither=輸出時使用已存儲物品或合成物品
gui.tooltips.appliedenergistics2.LevelType=檢測類型
gui.tooltips.appliedenergistics2.LevelType_Energy=能源(ae)
gui.tooltips.appliedenergistics2.LevelType_Energy=能源AE
gui.tooltips.appliedenergistics2.LevelType_Item=物品
gui.tooltips.appliedenergistics2.InventoryTweaks=容器整理
gui.tooltips.appliedenergistics2.Mod=模組
gui.tooltips.appliedenergistics2.TerminalStyle=終端風格
gui.tooltips.appliedenergistics2.TerminalStyle_Full=全屏
gui.tooltips.appliedenergistics2.TerminalStyle_Tall=長
gui.tooltips.appliedenergistics2.TerminalStyle_Small=短
gui.tooltips.appliedenergistics2.DoesntDespawn=該物品不會消亡。
gui.tooltips.appliedenergistics2.EmitterMode=合成發出器模式
gui.tooltips.appliedenergistics2.CraftViaRedstone=發出紅石來合成物品。
gui.tooltips.appliedenergistics2.EmitWhenCrafting=物品正在合成時發出紅石。
gui.tooltips.appliedenergistics2.ReportInaccessibleItems=報告無法訪問的物品
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=是:無法提取的項目將會顯示。
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=否:只有可提取的項目才會顯示。
gui.tooltips.appliedenergistics2.BlockPlacement=方塊放置方式
gui.tooltips.appliedenergistics2.BlockPlacementYes=方塊將被放置為方塊。
gui.tooltips.appliedenergistics2.BlockPlacementNo=方塊將作為物品掉落。
gui.tooltips.appliedenergistics2.SchedulingMode=調度模式
gui.tooltips.appliedenergistics2.SchedulingModeDefault=導出第一個項目,直到網絡為空,然後嘗試下一個項目。
gui.tooltips.appliedenergistics2.SchedulingModeRoundRobin=使用循環模式導出。
gui.tooltips.appliedenergistics2.SchedulingModeRandom=以隨機模式導出物品。
gui.tooltips.appliedenergistics2.FilterMode=搜索過濾器模式
gui.tooltips.appliedenergistics2.FilterModeKeep=恢復以前的搜索過濾器
gui.tooltips.appliedenergistics2.FilterModeClear=清除每個開放。
gui.tooltips.appliedenergistics2.ItemsStored=存儲的物品:%s
gui.tooltips.appliedenergistics2.ItemsRequestable=可請求的物品:%s
// 單元
gui.appliedenergistics2.units.appliedenergstics=AE
gui.appliedenergistics2.units.ic2=EU
gui.appliedenergistics2.units.universalelectricity=KJ
gui.appliedenergistics2.units.rotarycraft=Watts
gui.appliedenergistics2.units.thermalexpansion=RF
gui.appliedenergistics2.units.rf=RF
// 顏色
gui.appliedenergistics2.White=白色
gui.appliedenergistics2.Orange=橙色
gui.appliedenergistics2.Magenta=品紅色
@@ -280,6 +360,8 @@ gui.appliedenergistics2.Red=紅色
gui.appliedenergistics2.Black=黑色
gui.appliedenergistics2.Fluix=Fluix默認色
// Waila
waila.appliedenergistics2.Crafting=合成中
waila.appliedenergistics2.DeviceOnline=設備開啟
waila.appliedenergistics2.DeviceOffline=設備關閉
waila.appliedenergistics2.DeviceMissingChannel=設備缺少頻道
@@ -287,155 +369,191 @@ waila.appliedenergistics2.Locked=鎖定
waila.appliedenergistics2.Unlocked=未鎖定
waila.appliedenergistics2.Showing=顯示
waila.appliedenergistics2.Contains=容納
waila.appliedenergistics2.Channels=%1$d of %2$d 頻道
waila.appliedenergistics2.Channels=%1$d/%2$d頻道
waila.appliedenergistics2.P2PUnlinked=未連接
waila.appliedenergistics2.P2PInputOneOutput=已連接(輸入端)
waila.appliedenergistics2.P2PInputManyOutputs=已連接(輸入端)-%d輸出
waila.appliedenergistics2.P2POutput=已連接(輸口端)
item.appliedenergistics2.ItemBasicStorageCell.1k.name=1k-ME存儲元件
item.appliedenergistics2.ItemBasicStorageCell.4k.name=4k-ME存儲元件
item.appliedenergistics2.ItemBasicStorageCell.16k.name=16k-ME存儲元件
item.appliedenergistics2.ItemBasicStorageCell.64k.name=64k-ME存儲元件
item.appliedenergistics2.ItemCreativeStorageCell.name=創造型ME存儲元件
item.appliedenergistics2.ItemEncodedPattern.name=已編碼樣板
item.appliedenergistics2.ItemViewCell.name=顯示元件
item.appliedenergistics2.ItemFacade.name=線纜偽裝板
// TheOneProbe
theoneprobe.appliedenergistics2.crafting=合成中:%1$s
theoneprobe.appliedenergistics2.device_online=設備開啟
theoneprobe.appliedenergistics2.device_offline=設備關閉
theoneprobe.appliedenergistics2.device_missing_channel=設備缺少頻道
theoneprobe.appliedenergistics2.locked=鎖定
theoneprobe.appliedenergistics2.unlocked=未鎖定
theoneprobe.appliedenergistics2.showing=顯示
theoneprobe.appliedenergistics2.contains=容納
theoneprobe.appliedenergistics2.channels=%1$d/%2$d頻道
theoneprobe.appliedenergistics2.p2p_unlinked=未連接
theoneprobe.appliedenergistics2.p2p_input_one_output=已連接(輸入端)
theoneprobe.appliedenergistics2.p2p_input_many_outputs=已連接(輸入端)-%d輸出
theoneprobe.appliedenergistics2.p2p_output=已連接(輸口端)
theoneprobe.appliedenergistics2.stored_energy=%1$d/%2$d
item.appliedenergistics2.ItemCrystalSeed.Certus.name=賽特斯石英種子
item.appliedenergistics2.ItemCrystalSeed.Nether.name=下界石英鐘子
item.appliedenergistics2.ItemCrystalSeed.Fluix.name=福魯伊克斯種子
item.appliedenergistics2.ItemMaterial.AdvCard.name=高級卡
item.appliedenergistics2.ItemMaterial.AnnihilationCore.name=破壞核心
item.appliedenergistics2.ItemMaterial.BasicCard.name=基礎卡
item.appliedenergistics2.ItemMaterial.BlankPattern.name=空白樣板
item.appliedenergistics2.ItemMaterial.CalcProcessor.name=運算處理器
item.appliedenergistics2.ItemMaterial.CardCapacity.name=容量卡
item.appliedenergistics2.ItemMaterial.CardFuzzy.name=模糊卡
item.appliedenergistics2.ItemMaterial.CardInverter.name=反相卡
item.appliedenergistics2.ItemMaterial.CardRedstone.name=紅石卡
item.appliedenergistics2.ItemMaterial.CardSpeed.name=加速卡
item.appliedenergistics2.ItemMaterial.Cell2SpatialPart.name=2³-空間組件
item.appliedenergistics2.ItemMaterial.Cell16SpatialPart.name=16³-空間組件
item.appliedenergistics2.ItemMaterial.Cell128SpatialPart.name=128³-空間組件
item.appliedenergistics2.ItemMaterial.Cell1kPart.name=1k-ME存儲組件
item.appliedenergistics2.ItemMaterial.Cell4kPart.name=4k-ME存儲組件
item.appliedenergistics2.ItemMaterial.Cell16kPart.name=16k-ME存儲組件
item.appliedenergistics2.ItemMaterial.Cell64kPart.name=64k-ME存儲組件
item.appliedenergistics2.ItemMaterial.CertusQuartzCrystal.name=賽特斯石英水晶
item.appliedenergistics2.ItemMaterial.CertusQuartzCrystalCharged.name=充能賽特斯石英水晶
item.appliedenergistics2.ItemMaterial.CertusQuartzDust.name=賽特斯石英粉
item.appliedenergistics2.ItemMaterial.EmptyStorageCell.name=ME存儲外殼
item.appliedenergistics2.ItemMaterial.EnderDust.name=末影粉
item.appliedenergistics2.ItemMaterial.EngProcessor.name=工程處理器
item.appliedenergistics2.ItemMaterial.Flour.name=面粉
item.appliedenergistics2.ItemMaterial.FluixCrystal.name=福魯伊克斯水晶
item.appliedenergistics2.ItemMaterial.FluixDust.name=福魯伊克斯粉
item.appliedenergistics2.ItemMaterial.FluixPearl.name=福魯伊克斯珍珠
item.appliedenergistics2.ItemMaterial.FormationCore.name=成型核心
item.appliedenergistics2.ItemMaterial.GoldDust.name=金粉
item.appliedenergistics2.ItemMaterial.IronDust.name=鐵粉
item.appliedenergistics2.ItemMaterial.LogicProcessor.name=邏輯處理器
item.appliedenergistics2.ItemMaterial.LogicProcessorAsm.name=半成品-邏輯處理器
item.appliedenergistics2.ItemMaterial.MatterBall.name=物質球
item.appliedenergistics2.ItemMaterial.NetherQuartzDust.name=下界石英粉
item.appliedenergistics2.ItemMaterial.PurifiedCertusQuartzCrystal.name=高純賽特斯石英水晶
item.appliedenergistics2.ItemMaterial.PurifiedFluixCrystal.name=高純福魯伊克斯水晶
item.appliedenergistics2.ItemMaterial.PurifiedNetherQuartzCrystal.name=高純下界石英水晶
item.appliedenergistics2.ItemMaterial.QESingularity.name=量子糾纏態奇點
item.appliedenergistics2.ItemMaterial.Silicon.name=硅
item.appliedenergistics2.ItemMaterial.Singularity.name=奇點
item.appliedenergistics2.ItemMaterial.Wireless.name=無線接收器
item.appliedenergistics2.ItemMaterial.WirelessBooster.name=無線信號增幅器
item.appliedenergistics2.ItemMaterial.WoodenGear.name=木齒輪
item.appliedenergistics2.ItemMaterial.EngProcessorPress.name=工程壓印模板
item.appliedenergistics2.ItemMaterial.CalcProcessorPress.name=運算壓印模板
item.appliedenergistics2.ItemMaterial.LogicProcessorPress.name=邏輯壓印模板
item.appliedenergistics2.ItemMaterial.EngProcessorPrint.name=工程電路板
item.appliedenergistics2.ItemMaterial.CalcProcessorPrint.name=運算電路板
item.appliedenergistics2.ItemMaterial.LogicProcessorPrint.name=邏輯電路板
item.appliedenergistics2.ItemMaterial.SiliconPress.name=硅壓印模板
item.appliedenergistics2.ItemMaterial.SiliconPrint.name=硅板
item.appliedenergistics2.ItemMaterial.NamePress.name=名稱壓印模板
item.appliedenergistics2.ItemMaterial.SkyDust.name=隕石粉
item.appliedenergistics2.ItemMaterial.CardCrafting.name=合成卡
// 物品
item.appliedenergistics2.storage_cell_1k.name=1k-ME存儲元件
item.appliedenergistics2.storage_cell_4k.name=4k-ME存儲元件
item.appliedenergistics2.storage_cell_16k.name=16k-ME存儲元件
item.appliedenergistics2.storage_cell_64k.name=64k-ME存儲元件
item.appliedenergistics2.creative_storage_cell.name=創造型ME存儲元件
item.appliedenergistics2.encoded_pattern.name=已編碼樣板
item.appliedenergistics2.view_cell.name=顯示元件
item.appliedenergistics2.facade.name=線纜偽裝板
item.appliedenergistics2.ItemPart.AnnihilationPlane.name=破壞面板
item.appliedenergistics2.ItemPart.CableAnchor.name=線纜錨
item.appliedenergistics2.ItemPart.CableCovered.name=ME包層線纜
item.appliedenergistics2.ItemPart.CableGlass.name=ME玻璃線纜
item.appliedenergistics2.ItemPart.CableSmart.name=ME智能線纜
item.appliedenergistics2.ItemPart.CableDense.name=ME致密線纜
item.appliedenergistics2.ItemPart.StorageMonitor.name=ME儲存監控器
item.appliedenergistics2.ItemPart.ConversionMonitor.name=ME交換監控器
item.appliedenergistics2.ItemPart.CraftingTerminal.name=ME合成終端
item.appliedenergistics2.ItemPart.SemiDarkMonitor.name=照明面板
item.appliedenergistics2.ItemPart.Monitor.name=亮色照明面板
item.appliedenergistics2.ItemPart.DarkMonitor.name=暗色照明面板
item.appliedenergistics2.ItemPart.ExportBus.name=ME輸出總線
item.appliedenergistics2.ItemPart.FormationPlane.name=ME成型面板
item.appliedenergistics2.ItemPart.ImportBus.name=ME輸入總線
item.appliedenergistics2.ItemPart.Interface.name=ME接口
item.appliedenergistics2.ItemPart.LevelEmitter.name=ME標準發信器
item.appliedenergistics2.ItemPart.P2PTunnel.name=P2P通道
item.appliedenergistics2.ItemPart.PatternTerminal.name=ME樣板終端
item.appliedenergistics2.ItemPart.QuartzFiber.name=石英纖維
item.appliedenergistics2.ItemPart.StorageBus.name=ME存儲總線
item.appliedenergistics2.ItemPart.Terminal.name=ME終端
item.appliedenergistics2.ItemPart.InvertedToggleBus.name=ME反相觸發總線
item.appliedenergistics2.ItemPart.ToggleBus.name=ME觸發總線
item.appliedenergistics2.ItemPart.CraftingMonitor.name=ME合成監控器
item.appliedenergistics2.ItemPart.InterfaceTerminal.name=ME接口終端
item.appliedenergistics2.crystal_seed.certus.name=賽特斯石英種子
item.appliedenergistics2.crystal_seed.nether.name=地獄石英鐘子
item.appliedenergistics2.crystal_seed.fluix.name=福魯伊克斯種子
item.appliedenergistics2.material.invalid_type.name=這個物品被禁用。
item.appliedenergistics2.material.advanced_card.name=高級卡
item.appliedenergistics2.material.annihilation_core.name=破壞核心
item.appliedenergistics2.material.basic_card.name=基礎卡
item.appliedenergistics2.material.blank_pattern.name=空白樣板
item.appliedenergistics2.material.calculation_processor.name=運算處理器
item.appliedenergistics2.material.card_capacity.name=容量卡
item.appliedenergistics2.material.card_fuzzy.name=模糊卡
item.appliedenergistics2.material.card_inverter.name=反相卡
item.appliedenergistics2.material.card_redstone.name=紅石卡
item.appliedenergistics2.material.card_speed.name=加速卡
item.appliedenergistics2.material.cell2_spatial_part.name=2³-空間組件
item.appliedenergistics2.material.cell16_spatial_part.name=16³-空間組件
item.appliedenergistics2.material.cell128_spatial_part.name=128³-空間組件
item.appliedenergistics2.material.cell1k_part.name=1k-ME存儲組件
item.appliedenergistics2.material.cell4k_part.name=4k-ME存儲組件
item.appliedenergistics2.material.cell16k_part.name=16k-ME存儲組件
item.appliedenergistics2.material.cell64k_part.name=64k-ME存儲組件
item.appliedenergistics2.material.certus_quartz_crystal.name=賽特斯石英水晶
item.appliedenergistics2.material.certus_quartz_crystal_charged.name=充能賽特斯石英水晶
item.appliedenergistics2.material.certus_quartz_dust.name=賽特斯石英粉
item.appliedenergistics2.material.empty_storage_cell.name=ME存儲外殼
item.appliedenergistics2.material.ender_dust.name=終界珍珠粉
item.appliedenergistics2.material.engineering_processor.name=工程處理器
item.appliedenergistics2.material.flour.name=麵粉
item.appliedenergistics2.material.fluix_crystal.name=福魯伊克斯水晶
item.appliedenergistics2.material.fluix_dust.name=福魯伊克斯粉
item.appliedenergistics2.material.fluix_pearl.name=福魯伊克斯珍珠
item.appliedenergistics2.material.formation_core.name=成型核心
item.appliedenergistics2.material.gold_dust.name=金粉
item.appliedenergistics2.material.iron_dust.name=鐵粉
item.appliedenergistics2.material.logic_processor.name=邏輯處理器
item.appliedenergistics2.material.logic_processor_asm.name=半成品-邏輯處理器
item.appliedenergistics2.material.matter_ball.name=物質球
item.appliedenergistics2.material.nether_quartz_dust.name=地獄石英粉
item.appliedenergistics2.material.purified_certus_quartz_crystal.name=高純賽特斯石英水晶
item.appliedenergistics2.material.purified_fluix_crystal.name=高純福魯伊克斯水晶
item.appliedenergistics2.material.purified_nether_quartz_crystal.name=高純地獄石英水晶
item.appliedenergistics2.material.quantum_entangled_singularity.name=量子糾纏態奇點
item.appliedenergistics2.material.silicon.name=矽
item.appliedenergistics2.material.singularity.name=奇點
item.appliedenergistics2.material.wireless.name=無線接收器
item.appliedenergistics2.material.wireless_booster.name=無線信號增幅器
item.appliedenergistics2.material.wooden_gear.name=木齒輪
item.appliedenergistics2.material.engineering_processor_press.name=工程壓印模板
item.appliedenergistics2.material.calculation_processor_press.name=運算壓印模板
item.appliedenergistics2.material.logic_processor_press.name=邏輯壓印模板
item.appliedenergistics2.material.engineering_processor_print.name=工程電路板
item.appliedenergistics2.material.calculation_processor_print.name=運算電路板
item.appliedenergistics2.material.logic_processor_print.name=邏輯電路板
item.appliedenergistics2.material.silicon_press.name=矽壓印模板
item.appliedenergistics2.material.silicon_print.name=矽板
item.appliedenergistics2.material.name_press.name=名稱壓印模板
item.appliedenergistics2.material.sky_dust.name=隕石粉
item.appliedenergistics2.material.card_crafting.name=合成卡
item.appliedenergistics2.ItemSpatialStorageCell.128Cubed.name=128³-空間存儲元件
item.appliedenergistics2.ItemSpatialStorageCell.16Cubed.name=16³-空間存儲元件
item.appliedenergistics2.ItemSpatialStorageCell.2Cubed.name=2³-空間存儲元件
item.appliedenergistics2.multi_part.annihilation_plane.name=破壞面板
item.appliedenergistics2.multi_part.identity_annihilation_plane.name=ME身分破壞面板
item.appliedenergistics2.multi_part.cable_anchor.name=線纜錨
item.appliedenergistics2.multi_part.cable_covered.name=ME包層線纜
item.appliedenergistics2.multi_part.cable_glass.name=ME玻璃線纜
item.appliedenergistics2.multi_part.cable_smart.name=ME智能線纜
item.appliedenergistics2.multi_part.cable_dense_covered.name=ME緻密包層線纜
item.appliedenergistics2.multi_part.cable_dense_smart.name=ME緻密智能線纜
item.appliedenergistics2.multi_part.storage_monitor.name=ME儲存監控器
item.appliedenergistics2.multi_part.conversion_monitor.name=ME交換監控器
item.appliedenergistics2.multi_part.crafting_terminal.name=ME合成終端
item.appliedenergistics2.multi_part.semi_dark_monitor.name=照明面板
item.appliedenergistics2.multi_part.monitor.name=亮色照明面板
item.appliedenergistics2.multi_part.dark_monitor.name=暗色照明面板
item.appliedenergistics2.multi_part.export_bus.name=ME輸出總線
item.appliedenergistics2.multi_part.formation_plane.name=ME成型面板
item.appliedenergistics2.multi_part.import_bus.name=ME輸入總線
item.appliedenergistics2.multi_part.interface.name=ME接口
item.appliedenergistics2.multi_part.level_emitter.name=ME標準發信器
item.appliedenergistics2.multi_part.p2p_tunnel.name=p2p通道
item.appliedenergistics2.multi_part.pattern_terminal.name=ME樣板終端
item.appliedenergistics2.multi_part.quartz_fiber.name=石英纖維
item.appliedenergistics2.multi_part.storage_bus.name=ME存儲總線
item.appliedenergistics2.multi_part.terminal.name=ME終端
item.appliedenergistics2.multi_part.inverted_toggle_bus.name=ME反相觸發總線
item.appliedenergistics2.multi_part.toggle_bus.name=ME觸發總線
item.appliedenergistics2.multi_part.crafting_monitor.name=ME合成監控器
item.appliedenergistics2.multi_part.interface_terminal.name=ME接口終端
item.appliedenergistics2.multi_part.invalid_type.name=已禁用物品
item.appliedenergistics2.ToolCertusQuartzAxe.name=賽特斯石英斧
item.appliedenergistics2.ToolCertusQuartzCuttingKnife.name=賽特斯石英切割刀
item.appliedenergistics2.ToolCertusQuartzHoe.name=賽特斯石英鋤
item.appliedenergistics2.ToolCertusQuartzPickaxe.name=賽特斯石英鎬
item.appliedenergistics2.ToolCertusQuartzSpade.name=賽特斯石英鍬
item.appliedenergistics2.ToolCertusQuartzSword.name=賽特斯石英劍
item.appliedenergistics2.ToolCertusQuartzWrench.name=賽特斯石英扳手
item.appliedenergistics2.spatial_storage_cell_128_cubed.name=128³-空間存儲元件
item.appliedenergistics2.spatial_storage_cell_16_cubed.name=16³-空間存儲元件
item.appliedenergistics2.spatial_storage_cell_2_cubed.name=2³-空間存儲元件
item.appliedenergistics2.ToolNetherQuartzAxe.name=下界石英斧
item.appliedenergistics2.ToolNetherQuartzCuttingKnife.name=下界石英切割刀
item.appliedenergistics2.ToolNetherQuartzHoe.name=下界石英鋤
item.appliedenergistics2.ToolNetherQuartzPickaxe.name=下界石英鎬
item.appliedenergistics2.ToolNetherQuartzSpade.name=下界石英
item.appliedenergistics2.ToolNetherQuartzSword.name=下界石英劍
item.appliedenergistics2.ToolNetherQuartzWrench.name=下界石英扳手
item.appliedenergistics2.certus_quartz_axe.name=賽特斯石英斧
item.appliedenergistics2.certus_quartz_cutting_knife.name=賽特斯石英切割刀
item.appliedenergistics2.certus_quartz_hoe.name=賽特斯石英鋤
item.appliedenergistics2.certus_quartz_pickaxe.name=賽特斯石英鎬
item.appliedenergistics2.certus_quartz_spade.name=賽特斯石英
item.appliedenergistics2.certus_quartz_sword.name=賽特斯石英劍
item.appliedenergistics2.certus_quartz_wrench.name=賽特斯石英扳手
item.appliedenergistics2.ItemPaintBall.name=染色球
item.appliedenergistics2.ToolPortableCell.name=便攜元件
item.appliedenergistics2.ToolNetworkTool.name=網絡工具
item.appliedenergistics2.ToolChargedStaff.name=充能手杖
item.appliedenergistics2.ToolEntropyManipulator.name=熵變機械臂
item.appliedenergistics2.ToolMassCannon.name=物質炮
item.appliedenergistics2.ToolMemoryCard.name=內存卡
item.appliedenergistics2.ToolColorApplicator.name=染色器
item.appliedenergistics2.ToolWirelessTerminal.name=無線終端
item.appliedenergistics2.ToolBiometricCard.name=身份卡
item.appliedenergistics2.nether_quartz_axe.name=地獄石英斧
item.appliedenergistics2.nether_quartz_cutting_knife.name=地獄石英切割刀
item.appliedenergistics2.nether_quartz_hoe.name=地獄石英鋤
item.appliedenergistics2.nether_quartz_pickaxe.name=地獄石英鎬
item.appliedenergistics2.nether_quartz_spade.name=地獄石英鏟
item.appliedenergistics2.nether_quartz_sword.name=地獄石英劍
item.appliedenergistics2.nether_quartz_wrench.name=地獄石英扳手
item.appliedenergistics2.ToolDebugCard.name=Dev.調試卡
item.appliedenergistics2.ToolReplicatorCard.name=Dev.復制卡
item.appliedenergistics2.paint_ball.name=染色球
item.appliedenergistics2.portable_cell.name=便攜元件
item.appliedenergistics2.network_tool.name=網絡工具
item.appliedenergistics2.charged_staff.name=充能手杖
item.appliedenergistics2.entropy_manipulator.name=熵變機械臂
item.appliedenergistics2.matter_cannon.name=物質炮
item.appliedenergistics2.memory_card.name=內存卡
item.appliedenergistics2.color_applicator.name=染色器
item.appliedenergistics2.wireless_terminal.name=無線終端
item.appliedenergistics2.biometric_card.name=身份卡
item.appliedenergistics2.debug_card.name=Dev.調試卡
item.appliedenergistics2.debug_replicator_card.name=Dev.複製卡
// 指令
commands.ae2.usage=由應用能源2提供的指令——使用/ae2 list 以獲得列表,和/ae2 help _____ 以獲取指令幫助。
commands.ae2.permissions=您沒有足夠的權限來運行此命令。
commands.ae2.ChunkLogger=切換區塊加載和卸載到伺服器日誌。(管理員)
commands.ae2.ChunkLoggerOn=區塊記錄現在開啟
commands.ae2.ChunkLoggerOff=區塊記錄現在關閉
commands.ae2.Supporters=顯示AE2支持者的列表
// 成就
achievement.ae2.Root=應用能源
achievement.ae2.Root.desc=當一個箱子是不夠的。
achievement.ae2.Compass=隕石追跡者
achievement.ae2.Compass.desc=合成一個隕石羅盤
achievement.ae2.Presses=這是什麼東西啊!?
achievement.ae2.Presses=這是什麼東西啊?
achievement.ae2.Presses.desc=找到一塊壓印模板
achievement.ae2.SpatialIO=空間操弄者
achievement.ae2.SpatialIO.desc=合成一個空間IO端口
achievement.ae2.SpatialIOExplorer=大膽地去吧!
achievement.ae2.SpatialIOExplorer=大膽地去吧
achievement.ae2.SpatialIOExplorer.desc=被儲存在空間硬碟裡
achievement.ae2.StorageCell=勝過箱子
achievement.ae2.StorageCell.desc=合成一個存儲元件
achievement.ae2.IOPort=物品操弄者
achievement.ae2.IOPort.desc=合成一個ME-IO端口
achievement.ae2.CraftingTerminal=好一個"大"桌子
achievement.ae2.CraftingTerminal=好一個「大」桌子
achievement.ae2.CraftingTerminal.desc=合成一個ME合成終端
achievement.ae2.PatternTerminal=合成大師
achievement.ae2.PatternTerminal.desc=合成一個ME樣板終端
achievement.ae2.ChargedQuartz=哇!閃耀!!
achievement.ae2.ChargedQuartz=哇閃耀!!
achievement.ae2.ChargedQuartz.desc=找到充能賽特斯石英水晶
achievement.ae2.Fluix=這不是天然的!
achievement.ae2.Fluix=這不是天然的
achievement.ae2.Fluix.desc=製作福魯伊克斯水晶
achievement.ae2.Charger=水晶量產者
achievement.ae2.Charger.desc=合成一個充能器
@@ -449,7 +567,7 @@ achievement.ae2.Controller=交通樞紐
achievement.ae2.Controller.desc=合成一個控制器
achievement.ae2.Networking2=工程師
achievement.ae2.Networking2.desc=在你的網路中連接128台可互聯機器
achievement.ae2.Networking3=萬里長"程"
achievement.ae2.Networking3=萬里長「程」
achievement.ae2.Networking3.desc=在你的網路中連接2048台可互聯機器
achievement.ae2.P2P=雙向溝通
achievement.ae2.P2P.desc=合成一個P2P通道
@@ -465,5 +583,10 @@ achievement.ae2.PortableCell=百寶袋
achievement.ae2.PortableCell.desc=合成一個便攜元件
achievement.ae2.StorageBus=無窮潛力
achievement.ae2.StorageBus.desc=合成一個存儲總線
achievement.ae2.QNB=看!牛郎和織女牽手了!
achievement.ae2.QNB=看牛郎和織女牽手了
achievement.ae2.QNB.desc=合成一個量子環
// 統計
stat.ae2.ItemsInserted=添加到ME存儲的物品
stat.ae2.ItemsExtracted=從ME存儲中提取的物品
stat.ae2.TurnedCranks=轉動曲柄
@@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "appliedenergistics2:blocks/debug/energy_gen"
}
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/certus_quartz_axe"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/certus_quartz_hoe"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/certus_quartz_pickaxe"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/certus_quartz_spade"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/certus_quartz_sword"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/charged_staff"
}
@@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "appliedenergistics2:items/debug/energy_gen"
}
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/entropy_manipulator"
}
@@ -1,6 +1,22 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/matter_cannon"
},
"display": {
"thirdperson_righthand": {
"rotation": [
0,
-90,
0
]
},
"thirdperson_lefthand": {
"rotation": [
0,
90,
0
]
}
}
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/nether_quartz_axe"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/nether_quartz_hoe"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/nether_quartz_pickaxe"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/nether_quartz_spade"
}
@@ -1,5 +1,5 @@
{
"parent": "item/generated",
"parent": "item/handheld",
"textures": {
"layer0": "appliedenergistics2:items/nether_quartz_sword"
}
@@ -0,0 +1,11 @@
{
"result": {
"item": "appliedenergistics2:sky_stone_brick"
},
"type": "forge:ore_shapeless",
"ingredients": [
{
"item": "appliedenergistics2:smooth_sky_stone_block"
}
]
}
@@ -0,0 +1,11 @@
{
"result": {
"item": "appliedenergistics2:sky_stone_small_brick"
},
"type": "forge:ore_shapeless",
"ingredients": [
{
"item": "appliedenergistics2:sky_stone_brick"
}
]
}

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