Compare commits

...

115 Commits

Author SHA1 Message Date
PrototypeTrousers 104d6fc34d Implement Interface Configuration Terminal 2022-08-12 23:01:35 -03:00
PrototypeTrousers 40caeec92f JEI Ghost items work, missing some click interactions and GUI work 2022-08-11 04:05:45 -03:00
PrototypeTrousers 119cdbc2c0 missing JEI ghost support 2022-08-11 03:19:13 -03:00
PrototypeTrousers a44c74b0d7 wip 2022-08-09 03:41:31 -03:00
PrototypeTrousers a55dbb061c fix autocrafting logic bug with container items and processing patterns
fix message reporting missing items having their values swapped
2022-08-08 19:06:50 -03:00
PrototypeTrousers 9fdf0345b3 Fix #123 2022-07-20 22:25:19 -03:00
PrototypeTrousers 346f5aeaac fix GTEU energy tax evasion
fix StackOverflow crash
2022-07-20 17:09:56 -03:00
PrototypeTrousers d4b5d0dc26 allow automation insertion "gemCertusQuartz" oredictd items into charger
Fixes #120
2022-07-13 20:11:42 -03:00
PrototypeTrousers d77838146d fix patterns "not extracting" due to acidental dragging
bump version
2022-05-30 23:28:17 -03:00
PrototypeTrousers 5b1f98b2d8 fix expanded processing pattern terminal not refreshing when placing
patterns on the encoding output slot
2022-05-30 22:28:50 -03:00
PrototypeTrousers 1c197c0f20 Fix incorrect with behavior with interfaces and storage busses
while using interfaces with crafting cards
2022-05-15 08:18:59 -03:00
PrototypeTrousers 46a1faaca2 Merge pull request #105 from Xikaro/AE2-Omnifactory
Update ru_ru.lang
2022-05-15 08:17:16 -03:00
PrototypeTrousers dd28b610e1 bump version
last minute fix
2022-05-13 15:04:34 -03:00
Xikaro aa2bb45199 Update ru_ru.lang 2022-05-13 08:18:33 +05:00
PrototypeTrousers 48146af137 Blocking mode for sub-networks 2022-05-12 19:55:38 -03:00
PrototypeTrousers 582d7f140c bump version 2022-05-09 14:18:10 -03:00
PrototypeTrousers ffdc052d99 fix last facade on off hand deleting the item on the main hand when used
fixes #101
2022-05-09 14:15:10 -03:00
PrototypeTrousers de7d6321f0 Merge pull request #102 from TechLord22/dust_texture_fix
Fix Misaligned Dust Textures
2022-05-09 14:14:49 -03:00
tech22 235eef23e3 fix misaligned dust textures 2022-05-08 14:51:16 -04:00
PrototypeTrousers c7fcdf7d8b small tweaks to the crafting amount gui
number starts selected if want to override the default of 1.
keypad enter also works to start craft
2022-04-28 22:57:22 -03:00
PrototypeTrousers 3a6ab149e4 Merge pull request #100 from GTModpackTeam/fix-japan-lang
fix ja_JP.lang
2022-04-28 22:43:30 -03:00
tier940 9337eceb82 [fix] lang record & SearchMode 2022-04-28 20:53:27 +09:00
PrototypeTrousers 35f91bf0d0 reduce packets sent while dragging items around in GUIs 2022-04-25 12:10:41 -03:00
PrototypeTrousers 6d14d082b0 hold items inplace 2022-04-25 12:09:29 -03:00
PrototypeTrousers 98ad919f1b items oredicted "crystalCertusQuartz" can go into the charger
and change to ae2 charged certus quartz
2022-04-15 15:42:35 -03:00
PrototypeTrousers fb4af262b7 Merge pull request #88 from Mr-Ao-Dragon/AE2-Omnifactory
Update zh-cn lang file.
2022-04-15 14:27:10 -03:00
PrototypeTrousers 5f774749e8 Merge pull request #94 from GTModpackTeam/add-japanese-lang
Japanese translation files
2022-04-15 14:26:58 -03:00
PrototypeTrousers 81b3ff6976 fix autocrafting with substitute crafting option enabled 2022-04-13 15:38:47 -03:00
PrototypeTrousers c8698fc2bf enable controller and smart cables registration, even with channels off 2022-04-12 17:39:20 -03:00
PrototypeTrousers be9fb6d04c try to hold hold items in place while extracting holding down shift 2022-04-11 23:51:03 -03:00
PrototypeTrousers 90ca2c7e92 Fix condenser not creating new items after item extraction without
inserting new items
reworked pattern terminal and crafting terminal search expression matching
2022-04-11 15:15:29 -03:00
PrototypeTrousers 39ac308889 wip 2022-04-11 05:13:16 -03:00
PrototypeTrousers 4d268b97a9 cache itemstack on export bus 2022-04-11 03:50:33 -03:00
PrototypeTrousers 4b6fbf68b6 Added config for auto crafting of substitutions
Change missing items information to a packet (missing localization stuff yet)
2022-04-11 02:00:31 -03:00
PrototypeTrousers a289dec832 fix crash with GTCEu 2.2 and higher 2022-04-06 14:34:37 -03:00
PrototypeTrousers a4f50ea9ef actually fixes 2022-04-04 08:25:11 -03:00
PrototypeTrousers 0e8f7c9d03 added packets for missing items report 2022-04-04 03:57:04 -03:00
PrototypeTrousers 7c0935f447 fix (?) weird substitution items on crafting tree 2022-04-04 03:20:21 -03:00
PrototypeTrousers 1e9e8d2639 more checks if "gregtech" mod is loaded 2022-03-31 21:16:14 -03:00
tier940 3455e815b8 [fix] Rename crafting_accelerator 2022-03-29 16:50:38 +09:00
tier940 a08e61b818 [fix] lang table 2022-03-29 16:39:47 +09:00
PrototypeTrousers 19c6e2ff2d support for IC2 damageable items 2022-03-27 08:52:37 -03:00
PrototypeTrousers 4f25c1551b increase internal buffer of ME Chest
Fix item amount not refreshing when inserted/extracted
2022-03-27 08:10:02 -03:00
PrototypeTrousers 3b94e9420d fix NPE with ae2fc and blocking mode 2022-03-25 23:46:52 -03:00
PrototypeTrousers f30f334a23 move nonblocking call out of method used by ae2fc coremod 2022-03-24 23:25:28 -03:00
tier940 ed702a5c73 [fix] タイポ 2022-03-18 22:20:43 +09:00
tier940 1364117374 [update] change to latest 2022-03-18 21:52:43 +09:00
tier940 ed4b864ba2 [add] Japanese lang file 2022-03-17 18:24:48 +09:00
PrototypeTrousers 706e577dab Fix container item crafting (again)
avoid making some copies
fix crash without JEI
2022-03-16 00:52:38 -03:00
PrototypeTrousers ccc8486571 check if gregtech is loaded before checking for MetaTools 2022-03-12 22:36:22 -03:00
PrototypeTrousers 3e8440644e fix autocrafting with container items 2022-03-12 22:21:04 -03:00
PrototypeTrousers 50f4e08b64 Merge remote-tracking branch 'origin/AE2-Omnifactory' into AE2-Omnifactory 2022-03-12 17:27:17 -03:00
PrototypeTrousers cfa9fa2843 invalidate cached itemstack if its gonna be used in a real insertion 2022-03-12 17:14:37 -03:00
PrototypeTrousers 47f819e021 invalidate cached itemstack if its gonna be used in a real insertion 2022-03-12 11:03:04 -03:00
MrAoDragon e67b196e19 update zh-cn lang file 2022-03-12 17:34:14 +08:00
PrototypeTrousers 6d151bb890 GTCEu blocking mode fix 2022-03-11 23:11:52 -03:00
PrototypeTrousers 3305270a71 clean-up 2022-03-11 22:04:58 -03:00
PrototypeTrousers f824bfd2e1 small optimization 2022-03-10 21:35:18 -03:00
PrototypeTrousers 036f4e1c5b heavily tweaked auto-crafting 2022-03-09 23:14:02 -03:00
PrototypeTrousers 146d3f5628 fix fluid dupe 2022-03-06 08:24:29 -03:00
PrototypeTrousers 9c821cb015 cleaning 2022-03-05 23:29:20 -03:00
PrototypeTrousers 3a83c99b1f fix container items return properly 2022-03-05 11:15:32 -03:00
PrototypeTrousers 447c6debab account for interfaces priority affecting which items are extractable 2022-03-04 22:49:55 -03:00
PrototypeTrousers 50470ae3cf version 2022-03-04 21:44:58 -03:00
PrototypeTrousers 993be652c9 delay container item return when simulating crafting tree 2022-03-04 21:30:26 -03:00
PrototypeTrousers b3bfbd0b58 remove debugging log 2022-03-04 17:08:23 -03:00
PrototypeTrousers 49b3dc8b60 undo partially pattern cache rebuild optimization
enabled pattern substitution now can use substitute patterned items
2022-03-03 22:25:10 -03:00
PrototypeTrousers 71ffcfb839 JEI transfer handler OutOfBounds fix 2022-03-01 13:02:09 -03:00
PrototypeTrousers 73f76a6654 clean up 2022-02-28 23:30:52 -03:00
PrototypeTrousers 645de1d868 Merge branch 'craftingtree-tweaks' into AE2-Omnifactory 2022-02-28 23:17:21 -03:00
PrototypeTrousers 8f40478695 version 2022-02-28 23:16:53 -03:00
PrototypeTrousers 056fcc3818 switch to extractable instead of cached item list 2022-02-28 23:16:53 -03:00
PrototypeTrousers 0ed0eb9d5f better logging 2022-02-28 23:16:49 -03:00
PrototypeTrousers 3ddc846648 Merge branch 'craftingtree-tweaks' into AE2-Omnifactory 2022-02-28 23:06:11 -03:00
PrototypeTrousers f98f6ef852 misc cleaning 2022-02-28 22:57:35 -03:00
PrototypeTrousers 4192d721a0 only fire simulation if a player requested it 2022-02-28 21:25:33 -03:00
PrototypeTrousers a0f3ef9d86 cut crafting tree earlier if ingredients are available 2022-02-28 21:25:13 -03:00
PrototypeTrousers 6b29288de6 remove crafting penalties 2022-02-28 00:13:07 -03:00
PrototypeTrousers 285fc6314c small optimization to crafting tree 2022-02-27 23:04:29 -03:00
PrototypeTrousers 50fd83e96b adjust default blocking mode settings 2022-02-25 00:09:33 -03:00
PrototypeTrousers cc51138a6a blocking mode changes again
misc cleaning
2022-02-24 23:54:50 -03:00
PrototypeTrousers 918df0bf7f clean up 2022-02-22 23:55:52 -03:00
PrototypeTrousers c852199901 bump version 2022-02-22 22:55:44 -03:00
PrototypeTrousers fd95d3de47 fixed typo gtceu -> gteu 2022-02-22 22:37:28 -03:00
PrototypeTrousers c3dd6dabe1 fix blocking mode again... 2022-02-22 22:11:57 -03:00
PrototypeTrousers b0e81ac2d1 fix blocking mode somehow voiding items 2022-02-22 19:40:15 -03:00
PrototypeTrousers 30f4cdf545 attempt at pattern rebuild optimization 2022-02-22 00:02:17 -03:00
PrototypeTrousers ee9441474e tweak cache reset on interface config 2022-02-21 18:25:58 -03:00
PrototypeTrousers 8846202270 More itemstacks caching
Micro optimization on molecular assemblers
2022-02-21 15:11:16 -03:00
PrototypeTrousers 17a900ae9a actually return if a crafting job is running 2022-02-19 23:03:33 -03:00
PrototypeTrousers 66bc243b41 cache more itemstacks 2022-02-19 23:02:40 -03:00
PrototypeTrousers a2bda8f449 tile fluid textures on fluid interfaces properly 2022-02-17 20:15:29 -03:00
PrototypeTrousers a2c2a4df0f oops, add integrated circuit to default non blocking items 2022-02-15 19:33:56 -03:00
PrototypeTrousers b4e237244a fix interfaces with crafting cards attached to storage bus not working
add missing buttons to oredict storagebus
2022-02-14 17:15:51 -03:00
PrototypeTrousers b541ad8d18 misc cleaning
add lenses to non blocking list
2022-02-10 20:15:58 -03:00
PrototypeTrousers 64f29a7dba make it work 2022-02-10 17:59:03 -03:00
PrototypeTrousers 6d25b7ef3c reworked blocking mode. now items are configurable per mod 2022-02-09 22:15:44 -03:00
PrototypeTrousers c3a608ef59 fix export busses exporting items out of nowhere 2022-01-31 16:51:06 -03:00
PrototypeTrousers af1f5c34d2 fix npe when placing down an ore dict storage bus 2022-01-30 17:19:01 -03:00
PrototypeTrousers f5378e060e fix importing from storage drawers 2022-01-29 17:21:12 -03:00
PrototypeTrousers 47407acc42 backport of #5823 - try emptying interfaces first before handling crafting jobs 2022-01-29 17:03:15 -03:00
PrototypeTrousers d7f3428824 fix for infinite loop while loading 2022-01-24 13:19:31 -03:00
PrototypeTrousers 63e339b88b cache itemstacks more aggressively 2022-01-24 13:17:50 -03:00
PrototypeTrousers 98761809fd add the patterns inside the terminal to the drop list of the terminal 2022-01-23 23:08:47 -03:00
PrototypeTrousers 8cb013b686 versioning 2022-01-22 23:19:49 -03:00
PrototypeTrousers f2fe376982 Merge pull request #74 from Syrcan/GTEU-fix
GTEU input fix
2022-01-22 23:06:39 -03:00
Syrcan 603452de1f GTEU input fix 2022-01-22 10:11:23 +01:00
PrototypeTrousers 40bd96d21c tweak crafting job size again
null check
2022-01-21 18:12:18 -03:00
PrototypeTrousers a14d160a07 Reworked oredict storage bus
have a recipe now
expression matcher and validator from GTCEU by brachy84
2022-01-20 22:43:18 -03:00
PrototypeTrousers df28a5520f fix mod name
implement GTCEU Energy adapter
2022-01-20 20:02:26 -03:00
PrototypeTrousers 0d096944cc Merge branch 'gtceu-p2p' into AE2-Omnifactory 2022-01-20 17:48:07 -03:00
PrototypeTrousers 963d3414d8 update version
more of renaming mod
2022-01-20 17:46:07 -03:00
PrototypeTrousers 4414451f5e more gtceu p2p fixes 2022-01-20 17:05:21 -03:00
PrototypeTrousers e0ddb92b81 attune gtce p2p with cables 2022-01-20 13:28:08 -03:00
PrototypeTrousers 6f551ad67f wip gtceu p2p 2022-01-20 00:04:04 -03:00
118 changed files with 7594 additions and 3618 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ tasks.withType(JavaCompile) {
options.encoding = 'UTF-8' options.encoding = 'UTF-8'
} }
version = trousers + "-" + aeversion + "-" + aechannel + "-" + aebuild + "-" + trousersversion version = aeversion + "-" + aechannel + "-" + aebuild + "-" + extended + "-" + extendedversion
group = aegroup group = aegroup
archivesBaseName = aebasename archivesBaseName = aebasename
+3 -5
View File
@@ -3,20 +3,18 @@ aechannel=stable
aebuild=7 aebuild=7
aegroup=appeng aegroup=appeng
aebasename=appliedenergistics2 aebasename=appliedenergistics2
trousers=trousers_edition extended=extended_life
trousersversion=v49s extendedversion=v0.52.11
######################################################### #########################################################
# Versions # # Versions #
######################################################### #########################################################
minecraft_version=1.12.2 minecraft_version=1.12.2
mcp_mappings=snapshot_20171003 mcp_mappings=snapshot_20171003
forge_version=14.23.5.2847 forge_version=14.23.5.2847
######################################################### #########################################################
# Installable # # Installable #
######################################################### #########################################################
hwyla_version=1.8.26-B41_1.12.2 hwyla_version=1.8.26-B41_1.12.2
######################################################### #########################################################
# Provided APIs # # Provided APIs #
######################################################### #########################################################
@@ -28,7 +26,7 @@ cofhcore_version=1.12.2-4.5.2.19
crafttweaker_version=4.1.8.9 crafttweaker_version=4.1.8.9
inventorytweaks_version=1.63 inventorytweaks_version=1.63
ctm_version=MC1.12.2-0.3.1.16 ctm_version=MC1.12.2-0.3.1.16
forestry_version=5.8.2.387
######################################################### #########################################################
# Deployment # # Deployment #
######################################################### #########################################################
+8 -7
View File
@@ -59,7 +59,7 @@ repositories {
url "http://maven.k-4u.nl/" url "http://maven.k-4u.nl/"
} }
maven { // CraftTweaker maven { // CraftTweaker
name 'jared maven' name 'jared maven'
url "http://maven.blamejared.com/" url "http://maven.blamejared.com/"
} }
@@ -70,9 +70,9 @@ repositories {
//} //}
maven { maven {
name = "CurseForge" name = "CurseForge"
url = "https://minecraft.curseforge.com/api/maven/" url = "https://minecraft.curseforge.com/api/maven/"
} }
} }
configurations { configurations {
@@ -80,8 +80,7 @@ configurations {
} }
dependencies { dependencies {
compileOnly "gregtechce:gregtech:1.12.2:1.15.1.735" deobfCompile "gregtechce:gregtech:1.12.2:1.15.1.735"
// installable runtime dependencies // installable runtime dependencies
mods "mcp.mobius.waila:Hwyla:${hwyla_version}" mods "mcp.mobius.waila:Hwyla:${hwyla_version}"
mods "net.industrial-craft:industrialcraft-2:${ic2_version}:dev" mods "net.industrial-craft:industrialcraft-2:${ic2_version}:dev"
@@ -95,9 +94,11 @@ dependencies {
compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api" compileOnly "mcjty.theoneprobe:TheOneProbe-1.12:${top_version}:api"
compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf" compileOnly "cofh:CoFHCore:${cofhcore_version}:deobf"
compileOnly "CraftTweaker2:CraftTweaker2-API:${crafttweaker_version}" compileOnly "CraftTweaker2:CraftTweaker2-API:${crafttweaker_version}"
compileOnly "inventory-tweaks:InventoryTweaks:${inventorytweaks_version}:api" compileOnly "inventory-tweaks:InventoryTweaks:${inventorytweaks_version}:api"
compileOnly "team.chisel.ctm:CTM:${ctm_version}" compileOnly "team.chisel.ctm:CTM:${ctm_version}"
compileOnly "de.ellpeck.actuallyadditions:ActuallyAdditions:1.12.2-r152.16:api" compileOnly "de.ellpeck.actuallyadditions:ActuallyAdditions:1.12.2-r152.16:api"
deobfCompile "net.sengir.forestry:forestry_${minecraft_version}:$forestry_version"
// at runtime, use the full JEI jar // at runtime, use the full JEI jar
runtime "mezz.jei:jei_${minecraft_version}:${jei_version}" runtime "mezz.jei:jei_${minecraft_version}:${jei_version}"
@@ -28,7 +28,8 @@ public enum PowerUnits
{ {
AE( "gui.appliedenergistics2.units.appliedenergstics" ), // Native Units - AE Energy AE( "gui.appliedenergistics2.units.appliedenergstics" ), // Native Units - AE Energy
EU( "gui.appliedenergistics2.units.ic2" ), // IndustrialCraft 2 - Energy Units EU( "gui.appliedenergistics2.units.ic2" ), // IndustrialCraft 2 - Energy Units
RF( "gui.appliedenergistics2.units.rf" ); // RF - Redstone Flux RF( "gui.appliedenergistics2.units.rf" ), // RF - Redstone Flux
GTEU( "gui.appliedenergistics2.units.gteu" ); // RF - Redstone Flux
/** /**
* unlocalized name for the power unit. * unlocalized name for the power unit.
@@ -46,14 +47,13 @@ public enum PowerUnits
/** /**
* do power conversion using AE's conversion rates. * do power conversion using AE's conversion rates.
* * <p>
* Example: PowerUnits.EU.convertTo( PowerUnits.AE, 32 ); * Example: PowerUnits.EU.convertTo( PowerUnits.AE, 32 );
* * <p>
* will normally returns 64, as it will convert the EU, to AE with AE's power settings. * will normally returns 64, as it will convert the EU, to AE with AE's power settings.
* *
* @param target target power unit * @param target target power unit
* @param value value * @param value value
*
* @return value converted to target units, from this units. * @return value converted to target units, from this units.
*/ */
public double convertTo( final PowerUnits target, final double value ) public double convertTo( final PowerUnits target, final double value )
@@ -29,6 +29,7 @@ public enum TunnelType
ME, // Network Tunnel ME, // Network Tunnel
IC2_POWER, // EU Tunnel IC2_POWER, // EU Tunnel
FE_POWER, // Forge Energy tunnel FE_POWER, // Forge Energy tunnel
GTEU_POWER, // Forge Energy tunnel
REDSTONE, // Redstone Tunnel REDSTONE, // Redstone Tunnel
FLUID, // Fluid Tunnel FLUID, // Fluid Tunnel
ITEM, // Item Tunnel ITEM, // Item Tunnel
@@ -88,6 +88,8 @@ public interface IParts
IItemDefinition p2PTunnelFE(); IItemDefinition p2PTunnelFE();
IItemDefinition p2PTunnelGTEU();
IItemDefinition p2PTunnelLight(); IItemDefinition p2PTunnelLight();
// IItemDefinition p2PTunnelOpenComputers(); // IItemDefinition p2PTunnelOpenComputers();
@@ -119,6 +119,10 @@ public interface IAEItemStack extends IAEStack<IAEItemStack>
* *
* @param is An item stack * @param is An item stack
*/ */
boolean equals(ItemStack is); boolean equals( ItemStack is );
ItemStack getCachedItemStack( long stackSize );
void setCachedItemStack( ItemStack is );
} }
@@ -56,7 +56,7 @@ public class BlockMolecularAssembler extends AEBaseTileBlock
@Override @Override
protected IProperty[] getAEStates() protected IProperty[] getAEStates()
{ {
return new IProperty[] { POWERED }; return new IProperty[]{POWERED};
} }
@Override @Override
@@ -108,4 +108,14 @@ public class BlockMolecularAssembler extends AEBaseTileBlock
return super.onBlockActivated( w, pos, state, p, hand, side, hitX, hitY, hitZ ); return super.onBlockActivated( w, pos, state, p, hand, side, hitX, hitY, hitZ );
} }
@Override
public void onNeighborChange( IBlockAccess world, BlockPos pos, BlockPos neighbor )
{
final TileMolecularAssembler tg = this.getTileEntity( world, pos );
if( tg != null )
{
tg.updateNeighbors( world, pos, neighbor );
}
}
} }
@@ -20,6 +20,7 @@ package appeng.capabilities;
import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository; import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository;
import gregtech.api.capability.IEnergyContainer;
import net.darkhax.tesla.api.ITeslaConsumer; import net.darkhax.tesla.api.ITeslaConsumer;
import net.darkhax.tesla.api.ITeslaHolder; import net.darkhax.tesla.api.ITeslaHolder;
import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTBase;
@@ -57,6 +58,8 @@ public final class Capabilities
public static Capability<IItemRepository> ITEM_REPOSITORY_CAPABILITY; public static Capability<IItemRepository> ITEM_REPOSITORY_CAPABILITY;
public static Capability<IEnergyContainer> GTCE_ENERGY;
/** /**
* Register AE2 provided capabilities. * Register AE2 provided capabilities.
*/ */
@@ -103,7 +106,19 @@ public final class Capabilities
} }
@CapabilityInject( IItemRepository.class ) @CapabilityInject( IItemRepository.class )
private static void capIItemRepositoryRegistered( Capability<IItemRepository> cap ) { ITEM_REPOSITORY_CAPABILITY = cap; } private static void capIItemRepositoryRegistered( Capability<IItemRepository> cap )
{
ITEM_REPOSITORY_CAPABILITY = cap;
}
@CapabilityInject( IEnergyContainer.class )
private static void capIEnergyContainerRegistered( Capability<IEnergyContainer> cap )
{
if( IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.GTCE ) )
{
GTCE_ENERGY = cap;
}
}
// Create a storage implementation that does not do anything // Create a storage implementation that does not do anything
private static <T> Capability.IStorage<T> createNullStorage() private static <T> Capability.IStorage<T> createNullStorage()
+64 -67
View File
@@ -33,6 +33,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import appeng.container.slot.*; import appeng.container.slot.*;
import appeng.util.Platform;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@@ -107,6 +108,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
private List<IGhostIngredientHandler.Target<Object>> hoveredIngredientTargets = new ArrayList<>(); private List<IGhostIngredientHandler.Target<Object>> hoveredIngredientTargets = new ArrayList<>();
private Object bookmarkedIngredient; private Object bookmarkedIngredient;
private boolean isDraggingJeiGhostItem; private boolean isDraggingJeiGhostItem;
private boolean haltDragging = false;
public void setJeiGhostItem( boolean jeiGhostItem ) public void setJeiGhostItem( boolean jeiGhostItem )
{ {
@@ -159,7 +161,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
final List<Slot> slots = this.getInventorySlots(); final List<Slot> slots = this.getInventorySlots();
final Iterator<Slot> i = slots.iterator(); final Iterator<Slot> i = slots.iterator();
while( i.hasNext() ) while ( i.hasNext() )
{ {
if( i.next() instanceof SlotME ) if( i.next() instanceof SlotME )
{ {
@@ -208,13 +210,17 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
} }
} }
GlStateManager.enableDepth(); GlStateManager.enableDepth();
bookmarkedJEIghostItem(mouseX,mouseY); if( Platform.isModLoaded( "jei" ) )
{
bookmarkedJEIghostItem( mouseX, mouseY );
}
GlStateManager.disableDepth(); GlStateManager.disableDepth();
} }
void bookmarkedJEIghostItem(final int mouseX, final int mouseY) { @Optional.Method( modid = "jei" )
void bookmarkedJEIghostItem( final int mouseX, final int mouseY )
if (!isJeiGhostItem) {
if( !isJeiGhostItem )
{ {
bookmarkedIngredient = runtime.getBookmarkOverlay().getIngredientUnderMouse(); bookmarkedIngredient = runtime.getBookmarkOverlay().getIngredientUnderMouse();
} }
@@ -248,7 +254,9 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
} }
} }
} }
private void drawTargets(int mouseX, int mouseY) {
private void drawTargets( int mouseX, int mouseY )
{
GlStateManager.disableLighting(); GlStateManager.disableLighting();
for( IGhostIngredientHandler.Target target : hoveredIngredientTargets ) for( IGhostIngredientHandler.Target target : hoveredIngredientTargets )
{ {
@@ -377,17 +385,13 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
final AppEngSlot aeSlot = (AppEngSlot) slot; final AppEngSlot aeSlot = (AppEngSlot) slot;
if( aeSlot.isSlotEnabled() ) if( aeSlot.isSlotEnabled() )
{ {
this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18 );
18,
18 );
} }
else else
{ {
GlStateManager.color( 1.0F, 1.0F, 1.0F, 0.4F ); GlStateManager.color( 1.0F, 1.0F, 1.0F, 0.4F );
GlStateManager.enableBlend(); GlStateManager.enableBlend();
this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, this.drawTexturedModalRect( ox + aeSlot.xPos - 1, oy + aeSlot.yPos - 1, optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18 );
18,
18 );
GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F );
} }
} }
@@ -434,6 +438,15 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
super.mouseClicked( xCoord, yCoord, btn ); super.mouseClicked( xCoord, yCoord, btn );
} }
@Override
protected void mouseReleased( int mouseX, int mouseY, int state )
{
this.drag_click.clear();
this.haltDragging = false;
super.mouseReleased( mouseX, mouseY, state );
}
@Override @Override
protected void mouseClickMove( final int x, final int y, final int c, final long d ) protected void mouseClickMove( final int x, final int y, final int c, final long d )
{ {
@@ -447,48 +460,48 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
if( slot instanceof SlotFake && !itemstack.isEmpty() ) if( slot instanceof SlotFake && !itemstack.isEmpty() )
{ {
this.drag_click.add( slot ); if( this.drag_click.add( slot ) )
if( this.drag_click.size() > 1 )
{ {
for( final Slot dr : this.drag_click ) final PacketInventoryAction p = new PacketInventoryAction( c == 0 ? InventoryAction.PICKUP_OR_SET_DOWN : InventoryAction.PLACE_SINGLE, slot.slotNumber, 0 );
{ NetworkHandler.instance().sendToServer( p );
final PacketInventoryAction p = new PacketInventoryAction( c == 0 ? InventoryAction.PICKUP_OR_SET_DOWN : InventoryAction.PLACE_SINGLE, dr.slotNumber, 0 );
NetworkHandler.instance().sendToServer( p );
}
} }
} }
else if( slot instanceof SlotDisconnected ) else if( slot instanceof SlotDisconnected )
{ {
this.drag_click.add( slot ); if( !haltDragging && this.drag_click.add( slot ) )
if( this.drag_click.size() > 1 )
{ {
if( !itemstack.isEmpty() ) if( !itemstack.isEmpty() )
{ {
for( final Slot dr : this.drag_click ) if( slot.getStack().isEmpty() )
{ {
if( slot.getStack().isEmpty() ) InventoryAction action;
if( slot.getSlotStackLimit() == 1 )
{ {
InventoryAction action = InventoryAction.SPLIT_OR_PLACE_SINGLE; action = InventoryAction.SPLIT_OR_PLACE_SINGLE;
final PacketInventoryAction p = new PacketInventoryAction( action, dr.getSlotIndex(), ( (SlotDisconnected) slot ).getSlot().getId() );
NetworkHandler.instance().sendToServer( p );
} }
else
{
action = InventoryAction.PICKUP_OR_SET_DOWN;
}
final PacketInventoryAction p = new PacketInventoryAction( action, slot.getSlotIndex(), ( (SlotDisconnected) slot ).getSlot().getId() );
NetworkHandler.instance().sendToServer( p );
} }
} }
}
else if( isShiftKeyDown() ) else if( isShiftKeyDown() )
{
for( final Slot dr : this.drag_click )
{ {
for( final Slot dr : this.drag_click ) InventoryAction action = null;
if( !slot.getStack().isEmpty() )
{ {
InventoryAction action = null; action = InventoryAction.SHIFT_CLICK;
if( !slot.getStack().isEmpty() ) }
{ if( action != null )
action = InventoryAction.SHIFT_CLICK; {
} final PacketInventoryAction p = new PacketInventoryAction( action, dr.getSlotIndex(), ( (SlotDisconnected) slot ).getSlot().getId() );
if( action != null ) NetworkHandler.instance().sendToServer( p );
{
final PacketInventoryAction p = new PacketInventoryAction( action, dr.getSlotIndex(), ( (SlotDisconnected) slot ).getSlot().getId() );
NetworkHandler.instance().sendToServer( p );
}
} }
} }
} }
@@ -506,7 +519,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{ {
final EntityPlayer player = Minecraft.getMinecraft().player; final EntityPlayer player = Minecraft.getMinecraft().player;
if( this.isJeiGhostItem && isDraggingJeiGhostItem) if( this.isJeiGhostItem && isDraggingJeiGhostItem )
{ {
for( IGhostIngredientHandler.Target target : hoveredIngredientTargets ) for( IGhostIngredientHandler.Target target : hoveredIngredientTargets )
{ {
@@ -625,7 +638,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
if( slot instanceof SlotDisconnected ) if( slot instanceof SlotDisconnected )
{ {
if( this.drag_click.size() > 1 ) if( this.drag_click.size() >= 1 )
{ {
return; return;
} }
@@ -635,11 +648,11 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
switch ( clickType ) switch ( clickType )
{ {
case PICKUP: // pickup / set-down. case PICKUP: // pickup / set-down.
if( slot.getStack().isEmpty() && !player.inventory.getItemStack().isEmpty() ) if( mouseButton == 1 )
{ {
action = InventoryAction.SPLIT_OR_PLACE_SINGLE; action = InventoryAction.SPLIT_OR_PLACE_SINGLE;
} }
if( !slot.getStack().isEmpty() && player.inventory.getItemStack().getCount() <= 1 ) else
{ {
action = InventoryAction.PICKUP_OR_SET_DOWN; action = InventoryAction.PICKUP_OR_SET_DOWN;
} }
@@ -759,7 +772,8 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
this.disableShiftClick = false; this.disableShiftClick = false;
} }
if (clickType == ClickType.PICKUP && isJeiGhostItem && !isDraggingJeiGhostItem) { if( clickType == ClickType.PICKUP && isJeiGhostItem && !isDraggingJeiGhostItem )
{
this.isDraggingJeiGhostItem = true; this.isDraggingJeiGhostItem = true;
return; return;
} }
@@ -854,7 +868,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
} }
} }
private void mouseWheelEvent( final int x, final int y, final int wheel ) protected void mouseWheelEvent( final int x, final int y, final int wheel )
{ {
final Slot slot = this.getSlot( x, y ); final Slot slot = this.getSlot( x, y );
if( slot instanceof SlotME ) if( slot instanceof SlotME )
@@ -879,7 +893,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
if( stack != ItemStack.EMPTY ) if( stack != ItemStack.EMPTY )
{ {
InventoryAction direction = wheel > 0 ? InventoryAction.PLACE_SINGLE : InventoryAction.PICKUP_SINGLE; InventoryAction direction = wheel > 0 ? InventoryAction.PLACE_SINGLE : InventoryAction.PICKUP_SINGLE;
final PacketInventoryAction p = new PacketInventoryAction( direction , slot.slotNumber , 0); final PacketInventoryAction p = new PacketInventoryAction( direction, slot.slotNumber, 0 );
NetworkHandler.instance().sendToServer( p ); NetworkHandler.instance().sendToServer( p );
} }
} }
@@ -1032,27 +1046,11 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
final float f1 = 0.00390625F; final float f1 = 0.00390625F;
final float f = 0.00390625F; final float f = 0.00390625F;
final float par6 = 16; final float par6 = 16;
vb.pos( par1 + 0, par2 + par6, this.zLevel ) vb.pos( par1 + 0, par2 + par6, this.zLevel ).tex( ( par3 + 0 ) * f, ( par4 + par6 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
.tex( ( par3 + 0 ) * f, ( par4 + par6 ) * f1 )
.color( 1.0f, 1.0f, 1.0f,
aes.getOpacityOfIcon() )
.endVertex();
final float par5 = 16; final float par5 = 16;
vb.pos( par1 + par5, par2 + par6, this.zLevel ) vb.pos( par1 + par5, par2 + par6, this.zLevel ).tex( ( par3 + par5 ) * f, ( par4 + par6 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
.tex( ( par3 + par5 ) * f, ( par4 + par6 ) * f1 ) vb.pos( par1 + par5, par2 + 0, this.zLevel ).tex( ( par3 + par5 ) * f, ( par4 + 0 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
.color( 1.0f, 1.0f, 1.0f, vb.pos( par1 + 0, par2 + 0, this.zLevel ).tex( ( par3 + 0 ) * f, ( par4 + 0 ) * f1 ).color( 1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon() ).endVertex();
aes.getOpacityOfIcon() )
.endVertex();
vb.pos( par1 + par5, par2 + 0, this.zLevel )
.tex( ( par3 + par5 ) * f, ( par4 + 0 ) * f1 )
.color( 1.0f, 1.0f, 1.0f,
aes.getOpacityOfIcon() )
.endVertex();
vb.pos( par1 + 0, par2 + 0, this.zLevel )
.tex( ( par3 + 0 ) * f, ( par4 + 0 ) * f1 )
.color( 1.0f, 1.0f, 1.0f,
aes.getOpacityOfIcon() )
.endVertex();
tessellator.draw(); tessellator.draw();
} }
@@ -1066,8 +1064,7 @@ public abstract class AEBaseGui extends GuiContainer implements IMTModGuiContain
{ {
if( ( (AppEngSlot) s ).getIsValid() == hasCalculatedValidness.NotAvailable ) if( ( (AppEngSlot) s ).getIsValid() == hasCalculatedValidness.NotAvailable )
{ {
boolean isValid = s.isItemValid( boolean isValid = s.isItemValid( is ) || s instanceof SlotOutput || s instanceof AppEngCraftingSlot || s instanceof SlotDisabled || s instanceof SlotInaccessible || s instanceof SlotFake || s instanceof SlotRestrictedInput || s instanceof SlotDisconnected;
is ) || s instanceof SlotOutput || s instanceof AppEngCraftingSlot || s instanceof SlotDisabled || s instanceof SlotInaccessible || s instanceof SlotFake || s instanceof SlotRestrictedInput || s instanceof SlotDisconnected;
if( isValid && s instanceof SlotRestrictedInput ) if( isValid && s instanceof SlotRestrictedInput )
{ {
try try
@@ -46,6 +46,7 @@ import appeng.helpers.WirelessTerminalGuiObject;
import appeng.parts.reporting.PartCraftingTerminal; import appeng.parts.reporting.PartCraftingTerminal;
import appeng.parts.reporting.PartPatternTerminal; import appeng.parts.reporting.PartPatternTerminal;
import appeng.parts.reporting.PartTerminal; import appeng.parts.reporting.PartTerminal;
import org.lwjgl.input.Keyboard;
public class GuiCraftAmount extends AEBaseGui public class GuiCraftAmount extends AEBaseGui
@@ -142,6 +143,7 @@ public class GuiCraftAmount extends AEBaseGui
this.amountToCraft.setVisible( true ); this.amountToCraft.setVisible( true );
this.amountToCraft.setFocused( true ); this.amountToCraft.setFocused( true );
this.amountToCraft.setText( "1" ); this.amountToCraft.setText( "1" );
this.amountToCraft.setSelectionPos( 0 );
} }
@Override @Override
@@ -160,8 +162,8 @@ public class GuiCraftAmount extends AEBaseGui
try try
{ {
Long.parseLong( this.amountToCraft.getText() ); long amt = Long.parseLong( this.amountToCraft.getText() );
this.next.enabled = !this.amountToCraft.getText().isEmpty(); this.next.enabled = ( !this.amountToCraft.getText().isEmpty() && amt > 0 );
} }
catch( final NumberFormatException e ) catch( final NumberFormatException e )
{ {
@@ -176,7 +178,7 @@ public class GuiCraftAmount extends AEBaseGui
{ {
if( !this.checkHotbarKeys( key ) ) if( !this.checkHotbarKeys( key ) )
{ {
if( key == 28 ) if( key == Keyboard.KEY_RETURN || key == Keyboard.KEY_NUMPADENTER )
{ {
this.actionPerformed( this.next ); this.actionPerformed( this.next );
} }
@@ -188,7 +190,7 @@ public class GuiCraftAmount extends AEBaseGui
String out = this.amountToCraft.getText(); String out = this.amountToCraft.getText();
boolean fixed = false; boolean fixed = false;
while( out.startsWith( "0" ) && out.length() > 1 ) while ( out.startsWith( "0" ) && out.length() > 1 )
{ {
out = out.substring( 1 ); out = out.substring( 1 );
fixed = true; fixed = true;
@@ -262,7 +264,7 @@ public class GuiCraftAmount extends AEBaseGui
String out = this.amountToCraft.getText(); String out = this.amountToCraft.getText();
boolean fixed = false; boolean fixed = false;
while( out.startsWith( "0" ) && out.length() > 1 ) while ( out.startsWith( "0" ) && out.length() > 1 )
{ {
out = out.substring( 1 ); out = out.substring( 1 );
fixed = true; fixed = true;
@@ -0,0 +1,575 @@
/*
* 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.client.gui.implementations;
import java.awt.*;
import java.io.IOException;
import java.util.*;
import java.util.List;
import appeng.api.config.ActionItems;
import appeng.api.config.Settings;
import appeng.client.gui.widgets.GuiImgButton;
import appeng.container.implementations.ContainerInterfaceConfigurationTerminal;
import appeng.container.interfaces.IJEIGhostIngredients;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.helpers.DualityInterface;
import appeng.helpers.InventoryAction;
import appeng.parts.reporting.PartInterfaceConfigurationTerminal;
import appeng.util.BlockPosUtils;
import appeng.util.item.AEItemStack;
import com.google.common.collect.HashMultimap;
import mezz.jei.api.gui.IGhostIngredientHandler;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import appeng.api.AEApi;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.client.gui.AEBaseGui;
import appeng.client.gui.widgets.GuiScrollbar;
import appeng.client.gui.widgets.MEGuiTextField;
import appeng.client.me.ClientDCInternalInv;
import appeng.client.me.SlotDisconnected;
import appeng.core.localization.GuiText;
import appeng.util.Platform;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.common.DimensionManager;
import org.lwjgl.input.Mouse;
import static appeng.client.render.BlockPosHighlighter.hilightBlock;
public class GuiInterfaceConfigurationTerminal extends AEBaseGui implements IJEIGhostIngredients
{
private static final int LINES_ON_PAGE = 6;
// TODO: copied from GuiMEMonitorable. It looks not changed, maybe unneeded?
private final int offsetX = 21;
private final HashMap<Long, ClientDCInternalInv> byId = new HashMap<>();
private final HashMultimap<String, ClientDCInternalInv> byName = HashMultimap.create();
private final HashMap<ClientDCInternalInv, BlockPos> blockPosHashMap = new HashMap<>();
private final HashMap<GuiButton, ClientDCInternalInv> guiButtonHashMap = new HashMap<>();
private final Map<ClientDCInternalInv, Integer> numUpgradesMap = new HashMap<>();
private final ArrayList<String> names = new ArrayList<>();
private final ArrayList<Object> lines = new ArrayList<>();
private final Set<Object> matchedStacks = new HashSet<>();
private final Map<String, Set<Object>> cachedSearches = new WeakHashMap<>();
private boolean refreshList = false;
private MEGuiTextField searchFieldInputs;
private PartInterfaceConfigurationTerminal partInterfaceTerminal;
private HashMap<ClientDCInternalInv, Integer> dimHashMap = new HashMap<>();
public Map<IGhostIngredientHandler.Target<?>, Object> mapTargetSlot = new HashMap<>();
public GuiInterfaceConfigurationTerminal( final InventoryPlayer inventoryPlayer, final PartInterfaceConfigurationTerminal te )
{
super( new ContainerInterfaceConfigurationTerminal( inventoryPlayer, te ) );
this.partInterfaceTerminal = te;
final GuiScrollbar scrollbar = new GuiScrollbar();
this.setScrollBar( scrollbar );
this.xSize = 208;
this.ySize = 235;
}
@Override
public void initGui()
{
super.initGui();
this.getScrollBar().setLeft( 189 );
this.getScrollBar().setHeight( 106 );
this.getScrollBar().setTop( 31 );
this.searchFieldInputs = new MEGuiTextField( this.fontRenderer, this.guiLeft + Math.max( 32, this.offsetX ), this.guiTop + 17, 65, 12 );
this.searchFieldInputs.setEnableBackgroundDrawing( false );
this.searchFieldInputs.setMaxStringLength( 25 );
this.searchFieldInputs.setTextColor( 0xFFFFFF );
this.searchFieldInputs.setVisible( true );
this.searchFieldInputs.setFocused( false );
this.searchFieldInputs.setText( partInterfaceTerminal.in );
}
@Override
public void onGuiClosed()
{
partInterfaceTerminal.saveSearchStrings( this.searchFieldInputs.getText().toLowerCase() );
super.onGuiClosed();
}
@Override
public void drawFG( final int offsetX, final int offsetY, final int mouseX, final int mouseY )
{
this.buttonList.clear();
this.fontRenderer.drawString( this.getGuiDisplayName( GuiText.InterfaceConfigurationTerminal.getLocal() ), 8, 6, 4210752 );
this.fontRenderer.drawString( GuiText.inventory.getLocal(), this.offsetX + 2, this.ySize - 96 + 3, 4210752 );
final int currentScroll = this.getScrollBar().getCurrentScroll();
this.inventorySlots.inventorySlots.removeIf( slot -> slot instanceof SlotDisconnected );
int offset = 30;
int linesDraw = 0;
for( int x = 0; x < LINES_ON_PAGE && linesDraw < LINES_ON_PAGE && currentScroll + x < this.lines.size(); x++ )
{
final Object lineObj = this.lines.get( currentScroll + x );
if( lineObj instanceof ClientDCInternalInv )
{
final ClientDCInternalInv inv = (ClientDCInternalInv) lineObj;
GuiButton guiButton = new GuiImgButton( guiLeft + 4, guiTop + offset, Settings.ACTIONS, ActionItems.HIGHLIGHT_INTERFACE );
guiButtonHashMap.put( guiButton, inv );
this.buttonList.add( guiButton );
int extraLines = numUpgradesMap.get( inv );
for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row )
{
for( int z = 0; z < 9; z++ )
{
this.inventorySlots.inventorySlots.add( new SlotDisconnected( inv, z + ( row * 9 ), ( z * 18 + 22 ), offset ) );
if( this.matchedStacks.contains( inv.getInventory().getStackInSlot( z + ( row * 9 ) ) ) )
{
drawRect( z * 18 + 22, offset, z * 18 + 22 + 16, offset + 16, 0x2A00FF00 );
}
}
linesDraw++;
offset += 18;
}
}
else if( lineObj instanceof String )
{
String name = (String) lineObj;
final int rows = this.byName.get( name ).size();
if( rows > 1 )
{
name = name + " (" + rows + ')';
}
while ( name.length() > 2 && this.fontRenderer.getStringWidth( name ) > 155 )
{
name = name.substring( 0, name.length() - 1 );
}
this.fontRenderer.drawString( name, this.offsetX + 2, 5 + offset, 4210752 );
linesDraw++;
offset += 18;
}
}
if( searchFieldInputs.isMouseIn( mouseX, mouseY ) )
{
drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Inputs OR names" );
}
}
@Override
protected void mouseClicked( final int xCoord, final int yCoord, final int btn ) throws IOException
{
this.searchFieldInputs.mouseClicked( xCoord, yCoord, btn );
if( btn == 1 && this.searchFieldInputs.isMouseIn( xCoord, yCoord ) )
{
this.searchFieldInputs.setText( "" );
this.refreshList();
}
super.mouseClicked( xCoord, yCoord, btn );
}
@Override
protected void actionPerformed( final GuiButton btn ) throws IOException
{
if( guiButtonHashMap.containsKey( btn ) )
{
BlockPos blockPos = blockPosHashMap.get( guiButtonHashMap.get( this.selectedButton ) );
BlockPos blockPos2 = mc.player.getPosition();
int playerDim = mc.world.provider.getDimension();
int interfaceDim = dimHashMap.get( guiButtonHashMap.get( this.selectedButton ) );
if( playerDim != interfaceDim )
{
try
{
mc.player.sendStatusMessage( new TextComponentString( "Interface located at dimension: " + interfaceDim + " [" + DimensionManager.getWorld( interfaceDim ).provider.getDimensionType().getName() + "] and cant be highlighted" ), false );
}
catch( Exception e )
{
mc.player.sendStatusMessage( new TextComponentString( "Interface is located in another dimension and cannot be highlighted" ), false );
}
}
else
{
hilightBlock( blockPos, System.currentTimeMillis() + 500 * BlockPosUtils.getDistance( blockPos, blockPos2 ), playerDim );
mc.player.sendStatusMessage( new TextComponentString( "The interface is now highlighted at " + "X: " + blockPos.getX() + " Y: " + blockPos.getY() + " Z: " + blockPos.getZ() ), false );
}
mc.player.closeScreen();
}
}
@Override
protected void mouseWheelEvent( final int x, final int y, final int wheel )
{
final Slot slot = this.getSlot( x, y );
if( slot instanceof SlotDisconnected )
{
final ItemStack stack = slot.getStack();
if( stack != ItemStack.EMPTY )
{
InventoryAction direction = wheel > 0 ? InventoryAction.PLACE_SINGLE : InventoryAction.PICKUP_SINGLE;
final PacketInventoryAction p = new PacketInventoryAction( direction, slot.getSlotIndex(), ( (SlotDisconnected) slot ).getSlot().getId() );
NetworkHandler.instance().sendToServer( p );
}
}
else
{
super.mouseWheelEvent( x, y, wheel );
}
}
@Override
public void drawBG( final int offsetX, final int offsetY, final int mouseX, final int mouseY )
{
this.bindTexture( "guis/interfaceconfigurationterminal.png" );
this.drawTexturedModalRect( offsetX, offsetY, 0, 0, this.xSize, this.ySize );
int offset = 29;
final int ex = this.getScrollBar().getCurrentScroll();
int linesDraw = 0;
for( int x = 0; x < LINES_ON_PAGE && linesDraw < LINES_ON_PAGE && ex + x < this.lines.size(); x++ )
{
final Object lineObj = this.lines.get( ex + x );
if( lineObj instanceof ClientDCInternalInv )
{
GlStateManager.color( 1, 1, 1, 1 );
final int width = 9 * 18;
int extraLines = numUpgradesMap.get( lineObj );
for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row )
{
this.drawTexturedModalRect( offsetX + 20, offsetY + offset, 20, 170, width, 18 );
offset += 18;
linesDraw++;
}
}
else
{
offset += 18;
linesDraw++;
}
}
if( this.searchFieldInputs != null )
{
this.searchFieldInputs.drawTextBox();
}
}
@Override
protected void keyTyped( final char character, final int key ) throws IOException
{
if( !this.checkHotbarKeys( key ) )
{
if( character == ' ' && this.searchFieldInputs.getText().isEmpty() && this.searchFieldInputs.isFocused() )
{
return;
}
if( this.searchFieldInputs.textboxKeyTyped( character, key ) )
{
this.refreshList();
}
else
{
super.keyTyped( character, key );
}
}
}
public void postUpdate( final NBTTagCompound in )
{
if( in.getBoolean( "clear" ) )
{
this.byId.clear();
this.refreshList = true;
}
for( final Object oKey : in.getKeySet() )
{
final String key = (String) oKey;
if( key.startsWith( "=" ) )
{
try
{
final long id = Long.parseLong( key.substring( 1 ), Character.MAX_RADIX );
final NBTTagCompound invData = in.getCompoundTag( key );
final ClientDCInternalInv current = this.getById( id, invData.getLong( "sortBy" ), invData.getString( "un" ) );
blockPosHashMap.put( current, NBTUtil.getPosFromTag( invData.getCompoundTag( "pos" ) ) );
dimHashMap.put( current, invData.getInteger( "dim" ) );
numUpgradesMap.put( current, invData.getInteger( "numUpgrades" ) );
for( int x = 0; x < current.getInventory().getSlots(); x++ )
{
final String which = Integer.toString( x );
if( invData.hasKey( which ) )
{
current.getInventory().setStackInSlot( x, new ItemStack( invData.getCompoundTag( which ) ) );
}
}
}
catch( final NumberFormatException ignored )
{
}
}
}
if( this.refreshList )
{
this.refreshList = false;
// invalid caches on refresh
this.cachedSearches.clear();
this.refreshList();
}
}
/**
* Rebuilds the list of interfaces.
* <p>
* Respects a search term if present (ignores case) and adding only matching patterns.
*/
private void refreshList()
{
this.byName.clear();
this.buttonList.clear();
this.matchedStacks.clear();
final String searchFieldInputs = this.searchFieldInputs.getText().toLowerCase();
final Set<Object> cachedSearch = this.getCacheForSearchTerm( searchFieldInputs );
final boolean rebuild = cachedSearch.isEmpty();
for( final ClientDCInternalInv entry : this.byId.values() )
{
// ignore inventory if not doing a full rebuild and cache already marks it as miss.
if( !rebuild && !cachedSearch.contains( entry ) )
{
continue;
}
// Shortcut to skip any filter if search term is ""/empty
boolean found = searchFieldInputs.isEmpty();
// Search if the current inventory holds a pattern containing the search term.
if( !found )
{
int slot = 0;
for( final ItemStack itemStack : entry.getInventory() )
{
if( slot > 8 + numUpgradesMap.get( entry ) * 9 )
{
break;
}
if( this.itemStackMatchesSearchTerm( itemStack, searchFieldInputs ) )
{
found = true;
matchedStacks.add( itemStack );
}
slot++;
}
}
// if found, filter skipped or machine name matching the search term, add it
if( found || entry.getName().toLowerCase().contains( searchFieldInputs ) )
{
this.byName.put( entry.getName(), entry );
cachedSearch.add( entry );
}
else
{
cachedSearch.remove( entry );
}
}
this.names.clear();
this.names.addAll( this.byName.keySet() );
Collections.sort( this.names );
this.lines.clear();
this.lines.ensureCapacity( this.getMaxRows() );
for( final String n : this.names )
{
this.lines.add( n );
final ArrayList<ClientDCInternalInv> clientInventories = new ArrayList<>();
clientInventories.addAll( this.byName.get( n ) );
Collections.sort( clientInventories );
this.lines.addAll( clientInventories );
}
this.getScrollBar().setRange( 0, this.lines.size() - 1, 1 );
}
private boolean itemStackMatchesSearchTerm( final ItemStack itemStack, final String searchTerm )
{
if( itemStack.isEmpty() )
{
return false;
}
boolean foundMatchingItemStack = false;
final String displayName = Platform
.getItemDisplayName( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( itemStack ) )
.toLowerCase();
for( String term : searchTerm.split( " " ) )
{
if( term.length() > 1 && ( term.startsWith( "-" ) || term.startsWith( "!" ) ) )
{
term = term.substring( 1 );
if( displayName.contains( term ) )
{
return false;
}
}
else if( displayName.contains( term ) )
{
foundMatchingItemStack = true;
}
}
return foundMatchingItemStack;
}
/**
* Tries to retrieve a cache for a with search term as keyword.
* <p>
* If this cache should be empty, it will populate it with an earlier cache if available or at least the cache for
* the empty string.
*
* @param searchTerm the corresponding search
* @return a Set matching a superset of the search term
*/
private Set<Object> getCacheForSearchTerm( final String searchTerm )
{
if( !this.cachedSearches.containsKey( searchTerm ) )
{
this.cachedSearches.put( searchTerm, new HashSet<>() );
}
final Set<Object> cache = this.cachedSearches.get( searchTerm );
if( cache.isEmpty() && searchTerm.length() > 1 )
{
cache.addAll( this.getCacheForSearchTerm( searchTerm.substring( 0, searchTerm.length() - 1 ) ) );
return cache;
}
return cache;
}
/**
* The max amount of unique names and each inv row. Not affected by the filtering.
*
* @return max amount of unique names and each inv row
*/
private int getMaxRows()
{
return this.names.size() + this.byId.size();
}
private ClientDCInternalInv getById( final long id, final long sortBy, final String string )
{
ClientDCInternalInv o = this.byId.get( id );
if( o == null )
{
this.byId.put( id, o = new ClientDCInternalInv( DualityInterface.NUMBER_OF_CONFIG_SLOTS, id, sortBy, string, 64 ) );
this.refreshList = true;
}
return o;
}
@Override
public List<IGhostIngredientHandler.Target<?>> getPhantomTargets( Object ingredient )
{
if( !( ingredient instanceof ItemStack ) )
{
return Collections.emptyList();
}
List<IGhostIngredientHandler.Target<?>> targets = new ArrayList<>();
for( Slot slot : this.inventorySlots.inventorySlots )
{
if( slot instanceof SlotDisconnected )
{
ItemStack itemStack = (ItemStack) ingredient;
IGhostIngredientHandler.Target<Object> target = new IGhostIngredientHandler.Target<Object>()
{
@Override
public Rectangle getArea()
{
return new Rectangle( getGuiLeft() + slot.xPos, getGuiTop() + slot.yPos, 16, 16 );
}
@Override
public void accept( Object ingredient )
{
final PacketInventoryAction p;
try
{
p = new PacketInventoryAction( InventoryAction.PLACE_JEI_GHOST_ITEM, (SlotDisconnected) slot, AEItemStack.fromItemStack( itemStack ) );
NetworkHandler.instance().sendToServer( p );
}
catch( IOException e )
{
e.printStackTrace();
}
}
};
targets.add( target );
mapTargetSlot.putIfAbsent( target, slot );
}
}
return targets;
}
@Override
public Map<IGhostIngredientHandler.Target<?>, Object> getFakeSlotTargetMap()
{
return IJEIGhostIngredients.super.getFakeSlotTargetMap();
}
}
@@ -72,9 +72,9 @@ public class GuiInterfaceTerminal extends AEBaseGui
private final HashMap<Long, ClientDCInternalInv> byId = new HashMap<>(); private final HashMap<Long, ClientDCInternalInv> byId = new HashMap<>();
private final HashMultimap<String, ClientDCInternalInv> byName = HashMultimap.create(); private final HashMultimap<String, ClientDCInternalInv> byName = HashMultimap.create();
private final HashMap<ClientDCInternalInv,BlockPos> blockPosHashMap = new HashMap<>(); private final HashMap<ClientDCInternalInv, BlockPos> blockPosHashMap = new HashMap<>();
private final HashMap<GuiButton,ClientDCInternalInv> guiButtonHashMap = new HashMap<>(); private final HashMap<GuiButton, ClientDCInternalInv> guiButtonHashMap = new HashMap<>();
private final Map<ClientDCInternalInv,Integer> numUpgradesMap = new HashMap<>(); private final Map<ClientDCInternalInv, Integer> numUpgradesMap = new HashMap<>();
private final ArrayList<String> names = new ArrayList<>(); private final ArrayList<String> names = new ArrayList<>();
private final ArrayList<Object> lines = new ArrayList<>(); private final ArrayList<Object> lines = new ArrayList<>();
private final Set<Object> matchedStacks = new HashSet<>(); private final Set<Object> matchedStacks = new HashSet<>();
@@ -87,7 +87,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
private PartInterfaceTerminal partInterfaceTerminal; private PartInterfaceTerminal partInterfaceTerminal;
private GuiButton guiButtonHide; private GuiButton guiButtonHide;
private GuiButton guiButtonNextAssembler; private GuiButton guiButtonNextAssembler;
private HashMap<ClientDCInternalInv,Integer> dimHashMap = new HashMap<>(); private HashMap<ClientDCInternalInv, Integer> dimHashMap = new HashMap<>();
public GuiInterfaceTerminal( final InventoryPlayer inventoryPlayer, final PartInterfaceTerminal te ) public GuiInterfaceTerminal( final InventoryPlayer inventoryPlayer, final PartInterfaceTerminal te )
{ {
@@ -166,9 +166,9 @@ public class GuiInterfaceTerminal extends AEBaseGui
this.buttonList.add( guiButton ); this.buttonList.add( guiButton );
int extraLines = numUpgradesMap.get( inv ); int extraLines = numUpgradesMap.get( inv );
for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE ; ++row ) for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row )
{ {
for( int z = 0; z < 9 ; z++ ) for( int z = 0; z < 9; z++ )
{ {
this.inventorySlots.inventorySlots.add( new SlotDisconnected( inv, z + ( row * 9 ), ( z * 18 + 22 ), offset ) ); this.inventorySlots.inventorySlots.add( new SlotDisconnected( inv, z + ( row * 9 ), ( z * 18 + 22 ), offset ) );
if( this.matchedStacks.contains( inv.getInventory().getStackInSlot( z + ( row * 9 ) ) ) ) if( this.matchedStacks.contains( inv.getInventory().getStackInSlot( z + ( row * 9 ) ) ) )
@@ -199,8 +199,14 @@ public class GuiInterfaceTerminal extends AEBaseGui
} }
} }
if( searchFieldInputs.isMouseIn( mouseX, mouseY ) ) drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Inputs OR names" ); if( searchFieldInputs.isMouseIn( mouseX, mouseY ) )
else if( searchFieldOutputs.isMouseIn( mouseX, mouseY ) ) drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Outputs OR names" ); {
drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Inputs OR names" );
}
else if( searchFieldOutputs.isMouseIn( mouseX, mouseY ) )
{
drawTooltip( Mouse.getEventX() * this.width / this.mc.displayWidth - offsetX, mouseY - guiTop, "Outputs OR names" );
}
} }
@@ -237,9 +243,12 @@ public class GuiInterfaceTerminal extends AEBaseGui
int interfaceDim = dimHashMap.get( guiButtonHashMap.get( this.selectedButton ) ); int interfaceDim = dimHashMap.get( guiButtonHashMap.get( this.selectedButton ) );
if( playerDim != interfaceDim ) if( playerDim != interfaceDim )
{ {
try { try
{
mc.player.sendStatusMessage( new TextComponentString( "Interface located at dimension: " + interfaceDim + " [" + DimensionManager.getWorld( interfaceDim ).provider.getDimensionType().getName() + "] and cant be highlighted" ), false ); mc.player.sendStatusMessage( new TextComponentString( "Interface located at dimension: " + interfaceDim + " [" + DimensionManager.getWorld( interfaceDim ).provider.getDimensionType().getName() + "] and cant be highlighted" ), false );
} catch(Exception e){ }
catch( Exception e )
{
mc.player.sendStatusMessage( new TextComponentString( "Interface is located in another dimension and cannot be highlighted" ), false ); mc.player.sendStatusMessage( new TextComponentString( "Interface is located in another dimension and cannot be highlighted" ), false );
} }
} }
@@ -251,25 +260,25 @@ public class GuiInterfaceTerminal extends AEBaseGui
mc.player.closeScreen(); mc.player.closeScreen();
} }
if (btn == guiButtonHide) if( btn == guiButtonHide )
{ {
partInterfaceTerminal.onlyInterfacesWithFreeSlots = !partInterfaceTerminal.onlyInterfacesWithFreeSlots; partInterfaceTerminal.onlyInterfacesWithFreeSlots = !partInterfaceTerminal.onlyInterfacesWithFreeSlots;
this.refreshList(); this.refreshList();
} }
if (btn == guiButtonNextAssembler) if( btn == guiButtonNextAssembler )
{ {
// Set Search to "Molecular Assembler" and set "Only Free Interface" // Set Search to "Molecular Assembler" and set "Only Free Interface"
boolean currentOnlyInterfacesWithFreeSlots = this.partInterfaceTerminal.onlyInterfacesWithFreeSlots; boolean currentOnlyInterfacesWithFreeSlots = this.partInterfaceTerminal.onlyInterfacesWithFreeSlots;
String currentSearchText = this.searchFieldOutputs.getText(); String currentSearchText = this.searchFieldOutputs.getText();
this.partInterfaceTerminal.onlyInterfacesWithFreeSlots = true; this.partInterfaceTerminal.onlyInterfacesWithFreeSlots = true;
this.searchFieldOutputs.setText("Molecular Assembler"); this.searchFieldOutputs.setText( "Molecular Assembler" );
this.refreshList(); this.refreshList();
this.partInterfaceTerminal.onlyInterfacesWithFreeSlots = currentOnlyInterfacesWithFreeSlots; this.partInterfaceTerminal.onlyInterfacesWithFreeSlots = currentOnlyInterfacesWithFreeSlots;
this.searchFieldOutputs.setText(currentSearchText); this.searchFieldOutputs.setText( currentSearchText );
} }
} }
@@ -294,12 +303,13 @@ public class GuiInterfaceTerminal extends AEBaseGui
for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row ) for( int row = 0; row < 1 + extraLines && linesDraw < LINES_ON_PAGE; ++row )
{ {
this.drawTexturedModalRect( offsetX + 20, offsetY + offset , 20, 173, width, 18 ); this.drawTexturedModalRect( offsetX + 20, offsetY + offset, 20, 173, width, 18 );
offset += 18; offset += 18;
linesDraw++; linesDraw++;
} }
} }
else { else
{
offset += 18; offset += 18;
linesDraw++; linesDraw++;
} }
@@ -326,12 +336,12 @@ public class GuiInterfaceTerminal extends AEBaseGui
return; return;
} }
if( character == ' ' && this.searchFieldOutputs.getText().isEmpty() && this.searchFieldOutputs.isFocused()) if( character == ' ' && this.searchFieldOutputs.getText().isEmpty() && this.searchFieldOutputs.isFocused() )
{ {
return; return;
} }
if( this.searchFieldInputs.textboxKeyTyped( character, key ) || this.searchFieldOutputs.textboxKeyTyped( character, key )) if( this.searchFieldInputs.textboxKeyTyped( character, key ) || this.searchFieldOutputs.textboxKeyTyped( character, key ) )
{ {
this.refreshList(); this.refreshList();
} }
@@ -361,9 +371,9 @@ public class GuiInterfaceTerminal extends AEBaseGui
final long id = Long.parseLong( key.substring( 1 ), Character.MAX_RADIX ); final long id = Long.parseLong( key.substring( 1 ), Character.MAX_RADIX );
final NBTTagCompound invData = in.getCompoundTag( key ); final NBTTagCompound invData = in.getCompoundTag( key );
final ClientDCInternalInv current = this.getById( id, invData.getLong( "sortBy" ), invData.getString( "un" ) ); final ClientDCInternalInv current = this.getById( id, invData.getLong( "sortBy" ), invData.getString( "un" ) );
blockPosHashMap.put( current, NBTUtil.getPosFromTag( invData.getCompoundTag( "pos" )) ); blockPosHashMap.put( current, NBTUtil.getPosFromTag( invData.getCompoundTag( "pos" ) ) );
dimHashMap.put( current, invData.getInteger( "dim" )); dimHashMap.put( current, invData.getInteger( "dim" ) );
numUpgradesMap.put( current, invData.getInteger("numUpgrades")); numUpgradesMap.put( current, invData.getInteger( "numUpgrades" ) );
for( int x = 0; x < current.getInventory().getSlots(); x++ ) for( int x = 0; x < current.getInventory().getSlots(); x++ )
{ {
@@ -391,7 +401,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
/** /**
* Rebuilds the list of interfaces. * Rebuilds the list of interfaces.
* * <p>
* Respects a search term if present (ignores case) and adding only matching patterns. * Respects a search term if present (ignores case) and adding only matching patterns.
*/ */
private void refreshList() private void refreshList()
@@ -403,7 +413,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
final String searchFieldInputs = this.searchFieldInputs.getText().toLowerCase(); final String searchFieldInputs = this.searchFieldInputs.getText().toLowerCase();
final String searchFieldOutputs = this.searchFieldOutputs.getText().toLowerCase(); final String searchFieldOutputs = this.searchFieldOutputs.getText().toLowerCase();
final Set<Object> cachedSearch = this.getCacheForSearchTerm( "IN:" + searchFieldInputs + " OUT:" + searchFieldOutputs + partInterfaceTerminal.onlyInterfacesWithFreeSlots); final Set<Object> cachedSearch = this.getCacheForSearchTerm( "IN:" + searchFieldInputs + " OUT:" + searchFieldOutputs + partInterfaceTerminal.onlyInterfacesWithFreeSlots );
final boolean rebuild = cachedSearch.isEmpty(); final boolean rebuild = cachedSearch.isEmpty();
for( final ClientDCInternalInv entry : this.byId.values() ) for( final ClientDCInternalInv entry : this.byId.values() )
@@ -416,7 +426,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
// Shortcut to skip any filter if search term is ""/empty // Shortcut to skip any filter if search term is ""/empty
boolean found = (searchFieldInputs.isEmpty() && searchFieldOutputs.isEmpty() && !partInterfaceTerminal.onlyInterfacesWithFreeSlots); boolean found = ( searchFieldInputs.isEmpty() && searchFieldOutputs.isEmpty() && !partInterfaceTerminal.onlyInterfacesWithFreeSlots );
boolean interfaceHasFreeSlots = false; boolean interfaceHasFreeSlots = false;
// Search if the current inventory holds a pattern containing the search term. // Search if the current inventory holds a pattern containing the search term.
@@ -425,42 +435,52 @@ public class GuiInterfaceTerminal extends AEBaseGui
int slot = 0; int slot = 0;
for( final ItemStack itemStack : entry.getInventory() ) for( final ItemStack itemStack : entry.getInventory() )
{ {
if (slot > 8 + numUpgradesMap.get(entry) * 9) { if( slot > 8 + numUpgradesMap.get( entry ) * 9 )
{
break; break;
} }
if( !searchFieldInputs.isEmpty() && !searchFieldOutputs.isEmpty() ) { if( !searchFieldInputs.isEmpty() && !searchFieldOutputs.isEmpty() )
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldInputs, 0) || this.itemStackMatchesSearchTerm(itemStack, searchFieldOutputs, 1)) { {
if( this.itemStackMatchesSearchTerm( itemStack, searchFieldInputs, 0 ) || this.itemStackMatchesSearchTerm( itemStack, searchFieldOutputs, 1 ) )
{
found = true; found = true;
matchedStacks.add(itemStack); matchedStacks.add( itemStack );
} }
} }
else if( !searchFieldInputs.isEmpty() ) { else if( !searchFieldInputs.isEmpty() )
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldInputs, 0)) { {
if( this.itemStackMatchesSearchTerm( itemStack, searchFieldInputs, 0 ) )
{
found = true; found = true;
matchedStacks.add(itemStack); matchedStacks.add( itemStack );
} }
} }
else if( !searchFieldOutputs.isEmpty() ) { else if( !searchFieldOutputs.isEmpty() )
if (this.itemStackMatchesSearchTerm(itemStack, searchFieldOutputs, 1)) { {
if( this.itemStackMatchesSearchTerm( itemStack, searchFieldOutputs, 1 ) )
{
found = true; found = true;
matchedStacks.add(itemStack); matchedStacks.add( itemStack );
} }
} }
// If only Interfaces with empty slots should be shown, check that here // If only Interfaces with empty slots should be shown, check that here
if(itemStack.isEmpty()) if( itemStack.isEmpty() )
{
interfaceHasFreeSlots = true; interfaceHasFreeSlots = true;
}
slot++; slot++;
} }
} }
// if found, filter skipped or machine name matching the search term, add it // if found, filter skipped or machine name matching the search term, add it
if( found || (entry.getName().toLowerCase().contains( searchFieldInputs ) && entry.getName().toLowerCase().contains( searchFieldOutputs ))) if( found || ( entry.getName().toLowerCase().contains( searchFieldInputs ) && entry.getName().toLowerCase().contains( searchFieldOutputs ) ) )
{ {
if (!partInterfaceTerminal.onlyInterfacesWithFreeSlots) if( !partInterfaceTerminal.onlyInterfacesWithFreeSlots )
{ {
this.byName.put( entry.getName(), entry ); this.byName.put( entry.getName(), entry );
cachedSearch.add( entry ); cachedSearch.add( entry );
} }
else if ( interfaceHasFreeSlots ){ else if( interfaceHasFreeSlots )
{
this.byName.put( entry.getName(), entry ); this.byName.put( entry.getName(), entry );
cachedSearch.add( entry ); cachedSearch.add( entry );
} }
@@ -493,7 +513,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
this.getScrollBar().setRange( 0, this.lines.size() - 1, 1 ); this.getScrollBar().setRange( 0, this.lines.size() - 1, 1 );
} }
private boolean itemStackMatchesSearchTerm( final ItemStack itemStack, final String searchTerm,int pass ) private boolean itemStackMatchesSearchTerm( final ItemStack itemStack, final String searchTerm, int pass )
{ {
if( itemStack.isEmpty() ) if( itemStack.isEmpty() )
{ {
@@ -509,7 +529,7 @@ public class GuiInterfaceTerminal extends AEBaseGui
NBTTagList tag = new NBTTagList(); NBTTagList tag = new NBTTagList();
if (pass == 0) if( pass == 0 )
{ {
tag = encodedValue.getTagList( "in", 10 ); tag = encodedValue.getTagList( "in", 10 );
} }
@@ -518,32 +538,44 @@ public class GuiInterfaceTerminal extends AEBaseGui
tag = encodedValue.getTagList( "out", 10 ); tag = encodedValue.getTagList( "out", 10 );
} }
boolean foundMatchingItemStack = false;
for( int i = 0; i < tag.tagCount(); i++ ) for( int i = 0; i < tag.tagCount(); i++ )
{ {
final ItemStack parsedItemStack = new ItemStack( tag.getCompoundTagAt( i ) ); final ItemStack parsedItemStack = new ItemStack( tag.getCompoundTagAt( i ) );
if( !parsedItemStack.isEmpty() ) if( !parsedItemStack.isEmpty() )
{ {
final String displayName = Platform final String displayName = Platform
.getItemDisplayName( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( parsedItemStack ) ) .getItemDisplayName( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( parsedItemStack ) )
.toLowerCase(); .toLowerCase();
if( displayName.contains( searchTerm ) )
for( String term : searchTerm.split( " " ) )
{ {
return true; if( term.length() > 1 && ( term.startsWith( "-" ) || term.startsWith( "!" ) ) )
{
term = term.substring( 1 );
if( displayName.contains( term ) )
{
return false;
}
}
else if( displayName.contains( term ) )
{
foundMatchingItemStack = true;
}
} }
} }
} }
return false; return foundMatchingItemStack;
} }
/** /**
* Tries to retrieve a cache for a with search term as keyword. * Tries to retrieve a cache for a with search term as keyword.
* * <p>
* If this cache should be empty, it will populate it with an earlier cache if available or at least the cache for * If this cache should be empty, it will populate it with an earlier cache if available or at least the cache for
* the empty string. * the empty string.
* *
* @param searchTerm the corresponding search * @param searchTerm the corresponding search
*
* @return a Set matching a superset of the search term * @return a Set matching a superset of the search term
*/ */
private Set<Object> getCacheForSearchTerm( final String searchTerm ) private Set<Object> getCacheForSearchTerm( final String searchTerm )
@@ -20,8 +20,12 @@ package appeng.client.gui.implementations;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import appeng.client.me.SlotME;
import appeng.container.slot.SlotRestrictedInput;
import appeng.core.features.ColoredItemDefinition;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse; import org.lwjgl.input.Mouse;
@@ -100,6 +104,7 @@ public class GuiMEMonitorable extends AEBaseMEGui implements ISortSource, IConfi
private boolean isAutoFocus = false; private boolean isAutoFocus = false;
private int currentMouseX = 0; private int currentMouseX = 0;
private int currentMouseY = 0; private int currentMouseY = 0;
private boolean delayedUpdate;
public GuiMEMonitorable( final InventoryPlayer inventoryPlayer, final ITerminalHost te ) public GuiMEMonitorable( final InventoryPlayer inventoryPlayer, final ITerminalHost te )
{ {
@@ -159,8 +164,26 @@ public class GuiMEMonitorable extends AEBaseMEGui implements ISortSource, IConfi
this.repo.postUpdate( is ); this.repo.postUpdate( is );
} }
this.repo.updateView(); if( isShiftKeyDown() )
this.setScrollBar(); {
for( Slot slot : this.inventorySlots.inventorySlots )
{
if( slot instanceof SlotME )
{
if( this.isPointInRegion( slot.xPos, slot.yPos, 18, 18, currentMouseX, currentMouseY ) )
{
this.delayedUpdate = true;
break;
}
}
}
}
if( !this.delayedUpdate )
{
this.repo.updateView();
this.setScrollBar();
}
} }
private void setScrollBar() private void setScrollBar()
@@ -429,7 +452,7 @@ public class GuiMEMonitorable extends AEBaseMEGui implements ISortSource, IConfi
} }
this.drawTexturedModalRect( offsetX, offsetY + 16 + this.rows * 18 + this.lowerTextureOffset, 0, 106 - 18 - 18, x_width, this.drawTexturedModalRect( offsetX, offsetY + 16 + this.rows * 18 + this.lowerTextureOffset, 0, 106 - 18 - 18, x_width,
99 + this.reservedSpace - this.lowerTextureOffset ); 99 + this.reservedSpace - this.lowerTextureOffset );
if( this.viewCell ) if( this.viewCell )
{ {
@@ -526,6 +549,33 @@ public class GuiMEMonitorable extends AEBaseMEGui implements ISortSource, IConfi
public void updateScreen() public void updateScreen()
{ {
this.repo.setPower( this.monitorableContainer.isPowered() ); this.repo.setPower( this.monitorableContainer.isPowered() );
if( this.delayedUpdate )
{
if( isShiftKeyDown() )
{
this.delayedUpdate = false;
for( Slot slot : this.inventorySlots.inventorySlots )
{
if( slot instanceof SlotME )
{
if( this.isPointInRegion( slot.xPos, slot.yPos, 18, 18, currentMouseX, currentMouseY ) )
{
this.delayedUpdate = true;
break;
}
}
}
}
else
{
this.delayedUpdate = false;
}
}
if( !this.delayedUpdate )
{
this.repo.updateView();
this.setScrollBar();
}
super.updateScreen(); super.updateScreen();
} }
@@ -1,37 +1,46 @@
package appeng.client.gui.implementations; package appeng.client.gui.implementations;
import appeng.api.config.AccessRestriction;
import appeng.api.config.ActionItems; import appeng.api.config.ActionItems;
import appeng.api.config.Settings; import appeng.api.config.Settings;
import appeng.api.config.StorageFilter;
import appeng.client.gui.AEBaseGui; import appeng.client.gui.AEBaseGui;
import appeng.client.gui.widgets.GuiImgButton; import appeng.client.gui.widgets.GuiImgButton;
import appeng.client.gui.widgets.GuiTabButton; import appeng.client.gui.widgets.GuiTabButton;
import appeng.client.gui.widgets.MEGuiTextField; import appeng.client.gui.widgets.MEGuiTextField;
import appeng.container.implementations.ContainerPartOreDictStorageBus; import appeng.container.implementations.ContainerOreDictStorageBus;
import appeng.core.AELog;
import appeng.core.localization.GuiText; import appeng.core.localization.GuiText;
import appeng.core.sync.GuiBridge; import appeng.core.sync.GuiBridge;
import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketConfigButton;
import appeng.core.sync.packets.PacketSwitchGuis; import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketValueConfig; import appeng.core.sync.packets.PacketValueConfig;
import appeng.parts.misc.PartOreDicStorageBus; import appeng.parts.misc.PartOreDicStorageBus;
import appeng.util.item.OreDictFilterMatcher;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import org.lwjgl.input.Mouse;
import java.io.IOException; import java.io.IOException;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class GuiPartOreDictStorageBus extends AEBaseGui public class GuiOreDictStorageBus extends AEBaseGui
{ {
private final ContainerOreDictStorageBus container;
PartOreDicStorageBus part; PartOreDicStorageBus part;
private GuiTabButton priority; private GuiTabButton priority;
private GuiImgButton partition; private GuiImgButton partition;
private GuiImgButton storageFilter;
private static final Pattern ORE_DICTIONARY_FILTER = Pattern.compile( "\\*?[a-zA-Z0-9_|\\\\+(){,}?!=\\-\\[:\\]&^$]*\\*?" ); private GuiImgButton rwMode;
private static final Pattern ORE_DICTIONARY_FILTER = Pattern.compile( "[(!]* *[0-9a-zA-Z*]* *\\)*( *[&|^]? *[(!]* *[0-9a-zA-Z*]* *\\)*)*" );
private MEGuiTextField searchFieldInputs; private MEGuiTextField searchFieldInputs;
public GuiPartOreDictStorageBus( final InventoryPlayer inventoryPlayer, final PartOreDicStorageBus te ) public GuiOreDictStorageBus( final InventoryPlayer inventoryPlayer, final PartOreDicStorageBus te )
{ {
super( new ContainerPartOreDictStorageBus( inventoryPlayer, te ) ); super( new ContainerOreDictStorageBus( inventoryPlayer, te ) );
this.container = (ContainerOreDictStorageBus) super.inventorySlots;
part = te; part = te;
this.ySize = 84; this.ySize = 84;
} }
@@ -51,6 +60,8 @@ public class GuiPartOreDictStorageBus extends AEBaseGui
this.buttonList.add( this.priority = new GuiTabButton( this.guiLeft + 154, this.guiTop, 2 + 4 * 16, GuiText.Priority.getLocal(), this.itemRender ) ); this.buttonList.add( this.priority = new GuiTabButton( this.guiLeft + 154, this.guiTop, 2 + 4 * 16, GuiText.Priority.getLocal(), this.itemRender ) );
this.buttonList.add( this.partition = new GuiImgButton( this.guiLeft - 18, this.guiTop + 28, Settings.ACTIONS, ActionItems.WRENCH ) ); this.buttonList.add( this.partition = new GuiImgButton( this.guiLeft - 18, this.guiTop + 28, Settings.ACTIONS, ActionItems.WRENCH ) );
this.buttonList.add( this.rwMode = new GuiImgButton( this.guiLeft - 18, this.guiTop + 48, Settings.ACCESS, AccessRestriction.READ_WRITE ) );
this.buttonList.add( this.storageFilter = new GuiImgButton( this.guiLeft - 18, this.guiTop + 68, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY ) );
try try
{ {
@@ -72,21 +83,31 @@ public class GuiPartOreDictStorageBus extends AEBaseGui
protected void actionPerformed( final GuiButton btn ) throws IOException protected void actionPerformed( final GuiButton btn ) throws IOException
{ {
super.actionPerformed( btn ); super.actionPerformed( btn );
if( btn == this.priority )
final boolean backwards = Mouse.isButtonDown( 1 );
try
{ {
NetworkHandler.instance().sendToServer( new PacketSwitchGuis( GuiBridge.GUI_PRIORITY ) ); if( btn == this.priority )
{
NetworkHandler.instance().sendToServer( new PacketSwitchGuis( GuiBridge.GUI_PRIORITY ) );
}
else if( btn == this.partition )
{
NetworkHandler.instance().sendToServer( new PacketValueConfig( "StorageBus.Action", "Partition" ) );
}
else if( btn == this.rwMode )
{
NetworkHandler.instance().sendToServer( new PacketConfigButton( this.rwMode.getSetting(), backwards ) );
}
else if( btn == this.storageFilter )
{
NetworkHandler.instance().sendToServer( new PacketConfigButton( this.storageFilter.getSetting(), backwards ) );
}
} }
if( btn == this.partition ) catch( final IOException e )
{ {
NetworkHandler.instance().sendToServer( new PacketValueConfig( "StorageBus.Action", "Partition" ) ); AELog.debug( e );
try
{
NetworkHandler.instance().sendToServer( new PacketValueConfig( "OreDictStorageBus.getRegex", "1" ) );
}
catch( IOException e )
{
e.printStackTrace();
}
} }
} }
@@ -103,6 +124,7 @@ public class GuiPartOreDictStorageBus extends AEBaseGui
if( !searchFieldInputs.isFocused() && wasFocused ) if( !searchFieldInputs.isFocused() && wasFocused )
{ {
searchFieldInputs.setText( OreDictFilterMatcher.validateExp( searchFieldInputs.getText() ) );
NetworkHandler.instance().sendToServer( new PacketValueConfig( "OreDictStorageBus.save", searchFieldInputs.getText() ) ); NetworkHandler.instance().sendToServer( new PacketValueConfig( "OreDictStorageBus.save", searchFieldInputs.getText() ) );
} }
@@ -125,8 +147,21 @@ public class GuiPartOreDictStorageBus extends AEBaseGui
public void drawFG( int offsetX, int offsetY, int mouseX, int mouseY ) public void drawFG( int offsetX, int offsetY, int mouseX, int mouseY )
{ {
this.fontRenderer.drawString( this.getGuiDisplayName( GuiText.OreDictStorageBus.getLocal() ), 8, 6, 4210752 ); this.fontRenderer.drawString( this.getGuiDisplayName( GuiText.OreDictStorageBus.getLocal() ), 8, 6, 4210752 );
this.fontRenderer.drawString( this.searchFieldInputs.getText().length() + " / " + this.searchFieldInputs.getMaxStringLength(), 8, 36, 4210752 ); this.fontRenderer.drawString( this.searchFieldInputs.getText().length() + " / " + this.searchFieldInputs.getMaxStringLength(), 120, 36, 4210752 );
this.fontRenderer.drawSplitString( "Supports regex. Or use * as a wildcard", 6, 48, 174, 4210752 ); this.fontRenderer.drawString( "& = AND " + "| = OR", 8, 36, 4210752 );
this.fontRenderer.drawString( "^ = XOR " + "! = NOT", 8, 48, 4210752 );
this.fontRenderer.drawString( "() for priority " + "* for wildcard", 8, 60, 4210752 );
this.fontRenderer.drawString( "Ex.: *Redstone*&!dustRedstone", 8, 72, 4210752 );
if( this.storageFilter != null )
{
this.storageFilter.set( container.getStorageFilter() );
}
if( this.rwMode != null )
{
this.rwMode.set( container.getReadWriteMode() );
}
} }
@Override @Override
@@ -87,6 +87,7 @@ public class GuiImgButton extends GuiButton implements ITooltip
this.registerApp( 16 * 10, Settings.POWER_UNITS, PowerUnits.AE, ButtonToolTips.PowerUnits, PowerUnits.AE.unlocalizedName ); this.registerApp( 16 * 10, Settings.POWER_UNITS, PowerUnits.AE, ButtonToolTips.PowerUnits, PowerUnits.AE.unlocalizedName );
this.registerApp( 16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.EU, ButtonToolTips.PowerUnits, PowerUnits.EU.unlocalizedName ); this.registerApp( 16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.EU, ButtonToolTips.PowerUnits, PowerUnits.EU.unlocalizedName );
this.registerApp( 16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.RF, ButtonToolTips.PowerUnits, PowerUnits.RF.unlocalizedName ); this.registerApp( 16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.RF, ButtonToolTips.PowerUnits, PowerUnits.RF.unlocalizedName );
this.registerApp( 16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.GTEU, ButtonToolTips.PowerUnits, PowerUnits.EU.unlocalizedName );
this.registerApp( 3, Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE, ButtonToolTips.RedstoneMode, ButtonToolTips.AlwaysActive ); this.registerApp( 3, Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE, ButtonToolTips.RedstoneMode, ButtonToolTips.AlwaysActive );
this.registerApp( 0, Settings.REDSTONE_CONTROLLED, RedstoneMode.LOW_SIGNAL, ButtonToolTips.RedstoneMode, ButtonToolTips.ActiveWithoutSignal ); this.registerApp( 0, Settings.REDSTONE_CONTROLLED, RedstoneMode.LOW_SIGNAL, ButtonToolTips.RedstoneMode, ButtonToolTips.ActiveWithoutSignal );
@@ -108,15 +109,11 @@ public class GuiImgButton extends GuiButton implements ITooltip
this.registerApp( 16 * 2 + 3, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_Auto ); this.registerApp( 16 * 2 + 3, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_Auto );
this.registerApp( 16 * 2 + 4, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_Standard ); this.registerApp( 16 * 2 + 4, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_Standard );
this.registerApp( 16 * 2 + 5, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIAuto ); this.registerApp( 16 * 2 + 5, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIAuto );
this.registerApp( 16 * 2 + 6, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH, ButtonToolTips.SearchMode, this.registerApp( 16 * 2 + 6, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIStandard );
ButtonToolTips.SearchMode_JEIStandard );
this.registerApp( 16 * 2 + 7, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_AutoKeep ); this.registerApp( 16 * 2 + 7, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_AutoKeep );
this.registerApp( 16 * 2 + 8, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode, this.registerApp( 16 * 2 + 8, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_StandardKeep );
ButtonToolTips.SearchMode_StandardKeep ); this.registerApp( 16 * 2 + 9, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIAutoKeep );
this.registerApp( 16 * 2 + 9, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH_KEEP, ButtonToolTips.SearchMode, this.registerApp( 16 * 2 + 10, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIStandardKeep );
ButtonToolTips.SearchMode_JEIAutoKeep );
this.registerApp( 16 * 2 + 10, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIStandardKeep );
this.registerApp( 16 * 5 + 3, Settings.LEVEL_TYPE, LevelType.ENERGY_LEVEL, ButtonToolTips.LevelType, ButtonToolTips.LevelType_Energy ); this.registerApp( 16 * 5 + 3, Settings.LEVEL_TYPE, LevelType.ENERGY_LEVEL, ButtonToolTips.LevelType, ButtonToolTips.LevelType_Energy );
this.registerApp( 16 * 4 + 3, Settings.LEVEL_TYPE, LevelType.ITEM_LEVEL, ButtonToolTips.LevelType, ButtonToolTips.LevelType_Item ); this.registerApp( 16 * 4 + 3, Settings.LEVEL_TYPE, LevelType.ITEM_LEVEL, ButtonToolTips.LevelType, ButtonToolTips.LevelType_Item );
@@ -174,19 +171,15 @@ public class GuiImgButton extends GuiButton implements ITooltip
this.registerApp( 16 * 11 + 2, Settings.CRAFT_VIA_REDSTONE, YesNo.YES, ButtonToolTips.EmitterMode, ButtonToolTips.CraftViaRedstone ); this.registerApp( 16 * 11 + 2, Settings.CRAFT_VIA_REDSTONE, YesNo.YES, ButtonToolTips.EmitterMode, ButtonToolTips.CraftViaRedstone );
this.registerApp( 16 * 11 + 1, Settings.CRAFT_VIA_REDSTONE, YesNo.NO, ButtonToolTips.EmitterMode, ButtonToolTips.EmitWhenCrafting ); this.registerApp( 16 * 11 + 1, Settings.CRAFT_VIA_REDSTONE, YesNo.NO, ButtonToolTips.EmitterMode, ButtonToolTips.EmitWhenCrafting );
this.registerApp( 16 * 3 + 5, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY, ButtonToolTips.ReportInaccessibleItems, this.registerApp( 16 * 3 + 5, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY, ButtonToolTips.ReportInaccessibleItems, ButtonToolTips.ReportInaccessibleItemsNo );
ButtonToolTips.ReportInaccessibleItemsNo ); this.registerApp( 16 * 3 + 6, Settings.STORAGE_FILTER, StorageFilter.NONE, ButtonToolTips.ReportInaccessibleItems, ButtonToolTips.ReportInaccessibleItemsYes );
this.registerApp( 16 * 3 + 6, Settings.STORAGE_FILTER, StorageFilter.NONE, ButtonToolTips.ReportInaccessibleItems,
ButtonToolTips.ReportInaccessibleItemsYes );
this.registerApp( 16 * 14, Settings.PLACE_BLOCK, YesNo.YES, ButtonToolTips.BlockPlacement, ButtonToolTips.BlockPlacementYes ); this.registerApp( 16 * 14, Settings.PLACE_BLOCK, YesNo.YES, ButtonToolTips.BlockPlacement, ButtonToolTips.BlockPlacementYes );
this.registerApp( 16 * 14 + 1, Settings.PLACE_BLOCK, YesNo.NO, ButtonToolTips.BlockPlacement, ButtonToolTips.BlockPlacementNo ); this.registerApp( 16 * 14 + 1, Settings.PLACE_BLOCK, YesNo.NO, ButtonToolTips.BlockPlacement, ButtonToolTips.BlockPlacementNo );
this.registerApp( 16 * 15, Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT, ButtonToolTips.SchedulingMode, ButtonToolTips.SchedulingModeDefault ); this.registerApp( 16 * 15, Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT, ButtonToolTips.SchedulingMode, ButtonToolTips.SchedulingModeDefault );
this.registerApp( 16 * 15 + 1, Settings.SCHEDULING_MODE, SchedulingMode.ROUNDROBIN, ButtonToolTips.SchedulingMode, this.registerApp( 16 * 15 + 1, Settings.SCHEDULING_MODE, SchedulingMode.ROUNDROBIN, ButtonToolTips.SchedulingMode, ButtonToolTips.SchedulingModeRoundRobin );
ButtonToolTips.SchedulingModeRoundRobin ); this.registerApp( 16 * 15 + 2, Settings.SCHEDULING_MODE, SchedulingMode.RANDOM, ButtonToolTips.SchedulingMode, ButtonToolTips.SchedulingModeRandom );
this.registerApp( 16 * 15 + 2, Settings.SCHEDULING_MODE, SchedulingMode.RANDOM, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeRandom );
} }
} }
@@ -336,7 +329,7 @@ public class GuiImgButton extends GuiButton implements ITooltip
{ {
i = 0; i = 0;
} }
while( i + 30 < sb.length() && ( i = sb.lastIndexOf( " ", i + 30 ) ) != -1 ) while ( i + 30 < sb.length() && ( i = sb.lastIndexOf( " ", i + 30 ) ) != -1 )
{ {
sb.replace( i, i + 1, "\n" ); sb.replace( i, i + 1, "\n" );
} }
@@ -43,6 +43,14 @@ public class ClientDCInternalInv implements Comparable<ClientDCInternalInv>
this.sortBy = sortBy; this.sortBy = sortBy;
} }
public ClientDCInternalInv( final int size, final long id, final long sortBy, final String unlocalizedName, int stackSize )
{
this.inventory = new AppEngInternalInventory( null, size, stackSize );
this.unlocalizedName = unlocalizedName;
this.id = id;
this.sortBy = sortBy;
}
public String getName() public String getName()
{ {
final String s = I18n.translateToLocal( this.unlocalizedName + ".name" ); final String s = I18n.translateToLocal( this.unlocalizedName + ".name" );
+28 -12
View File
@@ -99,6 +99,12 @@ public class ItemRepo
} }
} }
public long getItemCount( final IAEItemStack is )
{
IAEItemStack st = this.list.findPrecise( is );
return st == null ? 0 : st.getStackSize();
}
public void setViewCell( final ItemStack[] list ) public void setViewCell( final ItemStack[] list )
{ {
this.myPartitionList = ItemViewCell.createFilter( list ); this.myPartitionList = ItemViewCell.createFilter( list );
@@ -120,10 +126,11 @@ public class ItemRepo
this.updateJEI( this.searchString ); this.updateJEI( this.searchString );
} }
this.innerSearch = this.searchString;
final boolean terminalSearchToolTips = AEConfig.instance().getConfigManager().getSetting( Settings.SEARCH_TOOLTIPS ) != YesNo.NO; final boolean terminalSearchToolTips = AEConfig.instance().getConfigManager().getSetting( Settings.SEARCH_TOOLTIPS ) != YesNo.NO;
boolean searchMod = false; boolean searchMod = false;
this.innerSearch = searchString.toLowerCase();
if( this.innerSearch.startsWith( "@" ) ) if( this.innerSearch.startsWith( "@" ) )
{ {
searchMod = true; searchMod = true;
@@ -133,13 +140,13 @@ public class ItemRepo
Pattern m = null; Pattern m = null;
try try
{ {
m = Pattern.compile( this.innerSearch.toLowerCase(), Pattern.CASE_INSENSITIVE ); m = Pattern.compile( this.innerSearch, Pattern.CASE_INSENSITIVE );
} }
catch( final Throwable ignore ) catch( final Throwable ignore )
{ {
try try
{ {
m = Pattern.compile( Pattern.quote( this.innerSearch.toLowerCase() ), Pattern.CASE_INSENSITIVE ); m = Pattern.compile( Pattern.quote( this.innerSearch ), Pattern.CASE_INSENSITIVE );
} }
catch( final Throwable __ ) catch( final Throwable __ )
{ {
@@ -168,26 +175,35 @@ public class ItemRepo
continue; continue;
} }
final String dspName = searchMod ? Platform.getModId( is ) : Platform.getItemDisplayName( is ); final String dspName = ( searchMod ? Platform.getModId( is ) : Platform.getItemDisplayName( is ) ).toLowerCase();
boolean foundMatchingItemStack = false; boolean foundMatchingItemStack = true;
notDone = true;
if( m.matcher( dspName.toLowerCase() ).find() ) for( String term : innerSearch.split( " " ) )
{ {
notDone = false; if( term.length() > 1 && ( term.startsWith( "-" ) || term.startsWith( "!" ) ) )
foundMatchingItemStack = true; {
term = term.substring( 1 );
if( dspName.contains( term ) )
{
foundMatchingItemStack = false;
break;
}
}
else if( !dspName.contains( term ) )
{
foundMatchingItemStack = false;
break;
}
} }
if( terminalSearchToolTips && notDone && !searchMod ) if( terminalSearchToolTips && !foundMatchingItemStack )
{ {
final List<String> tooltip = Platform.getTooltip( is ); final List<String> tooltip = Platform.getTooltip( is );
for( final String line : tooltip ) for( final String line : tooltip )
{ {
if( m.matcher( line ).find() ) if( m.matcher( line ).find() )
{ {
foundMatchingItemStack = true; foundMatchingItemStack = true;
notDone = false;
break; break;
} }
} }
@@ -19,6 +19,7 @@
package appeng.client.me; package appeng.client.me;
import appeng.container.slot.IJEITargetSlot;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -28,7 +29,7 @@ import appeng.items.misc.ItemEncodedPattern;
import appeng.util.Platform; import appeng.util.Platform;
public class SlotDisconnected extends AppEngSlot public class SlotDisconnected extends AppEngSlot implements IJEITargetSlot
{ {
private final ClientDCInternalInv mySlot; private final ClientDCInternalInv mySlot;
@@ -20,6 +20,8 @@ package appeng.container.implementations;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IContainerListener;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import appeng.api.config.CondenserOutput; import appeng.api.config.CondenserOutput;
@@ -43,6 +45,7 @@ public class ContainerCondenser extends AEBaseContainer implements IProgressProv
public long storedPower = 0; public long storedPower = 0;
@GuiSync( 2 ) @GuiSync( 2 )
public CondenserOutput output = CondenserOutput.TRASH; public CondenserOutput output = CondenserOutput.TRASH;
private ItemStack prevStack = ItemStack.EMPTY;
public ContainerCondenser( final InventoryPlayer ip, final TileCondenser condenser ) public ContainerCondenser( final InventoryPlayer ip, final TileCondenser condenser )
{ {
@@ -62,6 +65,7 @@ public class ContainerCondenser extends AEBaseContainer implements IProgressProv
@Override @Override
public void detectAndSendChanges() public void detectAndSendChanges()
{ {
final ItemStack is = this.condenser.getInternalInventory().getStackInSlot( 1 );
if( Platform.isServer() ) if( Platform.isServer() )
{ {
final double maxStorage = this.condenser.getStorage(); final double maxStorage = this.condenser.getStorage();
@@ -70,6 +74,14 @@ public class ContainerCondenser extends AEBaseContainer implements IProgressProv
this.requiredEnergy = requiredEnergy == 0 ? (int) maxStorage : (int) Math.min( requiredEnergy, maxStorage ); this.requiredEnergy = requiredEnergy == 0 ? (int) maxStorage : (int) Math.min( requiredEnergy, maxStorage );
this.storedPower = (int) this.condenser.getStoredPower(); this.storedPower = (int) this.condenser.getStoredPower();
this.setOutput( (CondenserOutput) this.condenser.getConfigManager().getSetting( Settings.CONDENSER_OUTPUT ) ); this.setOutput( (CondenserOutput) this.condenser.getConfigManager().getSetting( Settings.CONDENSER_OUTPUT ) );
for( final IContainerListener listener : this.listeners )
{
if( !ItemStack.areItemsEqual( is, prevStack ) )
{
listener.sendSlotContents( this, 1, is );
}
}
} }
super.detectAndSendChanges(); super.detectAndSendChanges();
@@ -150,6 +150,7 @@ public class ContainerCraftConfirm extends AEBaseContainer
if( ccr.getCpu() == c ) if( ccr.getCpu() == c )
{ {
found = true; found = true;
break;
} }
} }
@@ -10,7 +10,9 @@ import appeng.util.Platform;
import appeng.util.inv.IAEAppEngInventory; import appeng.util.inv.IAEAppEngInventory;
import appeng.util.inv.InvOperation; import appeng.util.inv.InvOperation;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.Slot; import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTBase;
@@ -29,500 +31,523 @@ import static appeng.helpers.PatternHelper.PROCESSING_OUTPUT_LIMIT;
public class ContainerExpandedProcessingPatternTerm extends ContainerMEMonitorable implements IAEAppEngInventory, IOptionalSlotHost, IContainerCraftingPacket public class ContainerExpandedProcessingPatternTerm extends ContainerMEMonitorable implements IAEAppEngInventory, IOptionalSlotHost, IContainerCraftingPacket
{ {
private final IItemHandler crafting; private final IItemHandler crafting;
private final SlotFakeCraftingMatrix[] gridSlots = new SlotFakeCraftingMatrix[PROCESSING_INPUT_LIMIT]; private final SlotFakeCraftingMatrix[] gridSlots = new SlotFakeCraftingMatrix[PROCESSING_INPUT_LIMIT];
private final OptionalSlotFake[] outputSlots = new OptionalSlotFake[PROCESSING_OUTPUT_LIMIT]; private final OptionalSlotFake[] outputSlots = new OptionalSlotFake[PROCESSING_OUTPUT_LIMIT];
private final SlotRestrictedInput patternSlotIN; private final SlotRestrictedInput patternSlotIN;
private final SlotRestrictedInput patternSlotOUT; private final SlotRestrictedInput patternSlotOUT;
private final PartExpandedProcessingPatternTerminal expandedProcessingPatternTerminal; private final PartExpandedProcessingPatternTerminal expandedProcessingPatternTerminal;
public ContainerExpandedProcessingPatternTerm( InventoryPlayer ip, ITerminalHost monitorable ) public ContainerExpandedProcessingPatternTerm( InventoryPlayer ip, ITerminalHost monitorable )
{ {
super( ip, monitorable, false ); super( ip, monitorable, false );
this.expandedProcessingPatternTerminal = (PartExpandedProcessingPatternTerminal) monitorable; this.expandedProcessingPatternTerminal = (PartExpandedProcessingPatternTerminal) monitorable;
final IItemHandler patternInv = this.getExpandedPatternTerminal().getInventoryByName( "pattern" ); final IItemHandler patternInv = this.getExpandedPatternTerminal().getInventoryByName( "pattern" );
final IItemHandler output = this.getExpandedPatternTerminal().getInventoryByName( "output" ); final IItemHandler output = this.getExpandedPatternTerminal().getInventoryByName( "output" );
this.crafting = this.getExpandedPatternTerminal().getInventoryByName( "crafting" ); this.crafting = this.getExpandedPatternTerminal().getInventoryByName( "crafting" );
for( int y = 0; y < 4; y++ ) for( int y = 0; y < 4; y++ )
{ {
for( int x = 0; x < 4; x++ ) for( int x = 0; x < 4; x++ )
{ {
this.addSlotToContainer( this.gridSlots[x + y * 4] = new SlotFakeCraftingMatrix( this.crafting, x + y * 4, 4 + x * 18, -85 + y * 18 ) ); this.addSlotToContainer( this.gridSlots[x + y * 4] = new SlotFakeCraftingMatrix( this.crafting, x + y * 4, 4 + x * 18, -85 + y * 18 ) );
} }
} }
for( int y = 0; y < 3; y++ ) for( int y = 0; y < 3; y++ )
{ {
for( int x = 0; x < 2; x++ ) for( int x = 0; x < 2; x++ )
{ {
this.addSlotToContainer( this.outputSlots[x + y * 2] = new SlotPatternOutputs( output, this, x + y * 2, 96 + x * 18, -76 + y * 18, 0, 0, 1 ) ); this.addSlotToContainer( this.outputSlots[x + y * 2] = new SlotPatternOutputs( output, this, x + y * 2, 96 + x * 18, -76 + y * 18, 0, 0, 1 ) );
this.outputSlots[x + y * 2].setRenderDisabled( false ); this.outputSlots[x + y * 2].setRenderDisabled( false );
this.outputSlots[x + y * 2].setIIcon( -1 ); this.outputSlots[x + y * 2].setIIcon( -1 );
} }
} }
this.addSlotToContainer( this.patternSlotIN = new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.BLANK_PATTERN, patternInv, 0, 147, -72 - 9, this.getInventoryPlayer() ) ); this.addSlotToContainer( this.patternSlotIN = new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.BLANK_PATTERN, patternInv, 0, 147, -72 - 9, this.getInventoryPlayer() ) );
this.addSlotToContainer( this.patternSlotOUT = new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.ENCODED_PATTERN, patternInv, 1, 147, -72 + 34, this.getInventoryPlayer() ) ); this.addSlotToContainer( this.patternSlotOUT = new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.ENCODED_PATTERN, patternInv, 1, 147, -72 + 34, this.getInventoryPlayer() ) );
this.patternSlotOUT.setStackLimit( 1 ); this.patternSlotOUT.setStackLimit( 1 );
this.bindPlayerInventory( ip, 0, 0 ); this.bindPlayerInventory( ip, 0, 0 );
} }
@Override @Override
public ItemStack transferStackInSlot( final EntityPlayer p, final int idx ) public ItemStack transferStackInSlot( final EntityPlayer p, final int idx )
{ {
if( Platform.isClient() ) if( Platform.isClient() )
{ {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
if( this.inventorySlots.get( idx ) instanceof SlotPlayerInv || this.inventorySlots.get( idx ) instanceof SlotPlayerHotBar ) if( this.inventorySlots.get( idx ) instanceof SlotPlayerInv || this.inventorySlots.get( idx ) instanceof SlotPlayerHotBar )
{ {
final AppEngSlot clickSlot = (AppEngSlot) this.inventorySlots.get( idx ); // require AE SLots! final AppEngSlot clickSlot = (AppEngSlot) this.inventorySlots.get( idx ); // require AE SLots!
ItemStack itemStack = clickSlot.getStack(); ItemStack itemStack = clickSlot.getStack();
if( AEApi.instance().definitions().materials().blankPattern().isSameAs( itemStack ) ) if( AEApi.instance().definitions().materials().blankPattern().isSameAs( itemStack ) )
{ {
IItemHandler patternInv = this.getExpandedPatternTerminal().getInventoryByName( "pattern" ); IItemHandler patternInv = this.getExpandedPatternTerminal().getInventoryByName( "pattern" );
ItemStack remainder = patternInv.insertItem( 0, itemStack, false ); ItemStack remainder = patternInv.insertItem( 0, itemStack, false );
clickSlot.putStack( remainder ); clickSlot.putStack( remainder );
} }
} }
return super.transferStackInSlot( p, idx ); return super.transferStackInSlot( p, idx );
} }
@Override @Override
public void saveChanges() public void saveChanges()
{ {
} }
@Override @Override
public void onChangeInventory( final IItemHandler inv, final int slot, final InvOperation mc, final ItemStack removedStack, final ItemStack newStack ) public void onChangeInventory( final IItemHandler inv, final int slot, final InvOperation mc, final ItemStack removedStack, final ItemStack newStack )
{ {
} }
public void encodeAndMoveToInventory() public void encodeAndMoveToInventory()
{ {
encode(); encode();
ItemStack output = this.patternSlotOUT.getStack(); ItemStack output = this.patternSlotOUT.getStack();
if( !output.isEmpty() ) if( !output.isEmpty() )
{ {
if( !getPlayerInv().addItemStackToInventory( output ) ) if( !getPlayerInv().addItemStackToInventory( output ) )
{ {
getPlayerInv().player.dropItem( output, false ); getPlayerInv().player.dropItem( output, false );
} }
this.patternSlotOUT.putStack( ItemStack.EMPTY ); this.patternSlotOUT.putStack( ItemStack.EMPTY );
} }
} }
public void encode() public void encode()
{ {
ItemStack output = this.patternSlotOUT.getStack(); ItemStack output = this.patternSlotOUT.getStack();
final ItemStack[] in = this.getInputs(); final ItemStack[] in = this.getInputs();
final ItemStack[] out = this.getOutputs(); final ItemStack[] out = this.getOutputs();
// if there is no input, this would be silly. // if there is no input, this would be silly.
if( in == null || out == null ) if( in == null || out == null )
{ {
return; return;
} }
// first check the output slots, should either be null, or a pattern // first check the output slots, should either be null, or a pattern
if( !output.isEmpty() && !this.isPattern( output ) ) if( !output.isEmpty() && !this.isPattern( output ) )
{ {
return; return;
} // if nothing is there we should snag a new pattern. } // if nothing is there we should snag a new pattern.
else if( output.isEmpty() ) else if( output.isEmpty() )
{ {
output = this.patternSlotIN.getStack(); output = this.patternSlotIN.getStack();
if( output.isEmpty() || !this.isPattern( output ) ) if( output.isEmpty() || !this.isPattern( output ) )
{ {
return; // no blanks. return; // no blanks.
} }
// remove one, and clear the input slot. // remove one, and clear the input slot.
output.setCount( output.getCount() - 1 ); output.setCount( output.getCount() - 1 );
if( output.getCount() == 0 ) if( output.getCount() == 0 )
{ {
this.patternSlotIN.putStack( ItemStack.EMPTY ); this.patternSlotIN.putStack( ItemStack.EMPTY );
} }
// add a new encoded pattern. // add a new encoded pattern.
Optional<ItemStack> maybePattern = AEApi.instance().definitions().items().encodedPattern().maybeStack( 1 ); Optional<ItemStack> maybePattern = AEApi.instance().definitions().items().encodedPattern().maybeStack( 1 );
if( maybePattern.isPresent() ) if( maybePattern.isPresent() )
{ {
output = maybePattern.get(); output = maybePattern.get();
this.patternSlotOUT.putStack( output ); this.patternSlotOUT.putStack( output );
} }
} }
// encode the slot. // encode the slot.
final NBTTagCompound encodedValue = new NBTTagCompound(); final NBTTagCompound encodedValue = new NBTTagCompound();
final NBTTagList tagIn = new NBTTagList(); final NBTTagList tagIn = new NBTTagList();
final NBTTagList tagOut = new NBTTagList(); final NBTTagList tagOut = new NBTTagList();
for( final ItemStack i : in ) for( final ItemStack i : in )
{ {
tagIn.appendTag( this.createItemTag( i ) ); tagIn.appendTag( this.createItemTag( i ) );
} }
for( final ItemStack i : out ) for( final ItemStack i : out )
{ {
tagOut.appendTag( this.createItemTag( i ) ); tagOut.appendTag( this.createItemTag( i ) );
} }
encodedValue.setTag( "in", tagIn ); encodedValue.setTag( "in", tagIn );
encodedValue.setTag( "out", tagOut ); encodedValue.setTag( "out", tagOut );
encodedValue.setBoolean( "crafting", false ); encodedValue.setBoolean( "crafting", false );
encodedValue.setBoolean( "substitute", false ); encodedValue.setBoolean( "substitute", false );
output.setTagCompound( encodedValue ); output.setTagCompound( encodedValue );
} }
boolean isPattern( final ItemStack output ) boolean isPattern( final ItemStack output )
{ {
if( output.isEmpty() ) if( output.isEmpty() )
{ {
return false; return false;
} }
final IDefinitions definitions = AEApi.instance().definitions(); final IDefinitions definitions = AEApi.instance().definitions();
boolean isPattern = definitions.items().encodedPattern().isSameAs( output ); boolean isPattern = definitions.items().encodedPattern().isSameAs( output );
isPattern |= definitions.materials().blankPattern().isSameAs( output ); isPattern |= definitions.materials().blankPattern().isSameAs( output );
return isPattern; return isPattern;
} }
NBTBase createItemTag( final ItemStack i ) NBTBase createItemTag( final ItemStack i )
{ {
final NBTTagCompound c = new NBTTagCompound(); final NBTTagCompound c = new NBTTagCompound();
if( !i.isEmpty() ) if( !i.isEmpty() )
{ {
i.writeToNBT( c ); i.writeToNBT( c );
} }
return c; return c;
} }
@Override @Override
public boolean isSlotEnabled( final int idx ) public boolean isSlotEnabled( final int idx )
{ {
return true; return true;
} }
protected ItemStack[] getInputs() protected ItemStack[] getInputs()
{ {
final ItemStack[] input = new ItemStack[16]; final ItemStack[] input = new ItemStack[16];
boolean hasValue = false; boolean hasValue = false;
for( int x = 0; x < this.gridSlots.length; x++ ) for( int x = 0; x < this.gridSlots.length; x++ )
{ {
input[x] = this.gridSlots[x].getStack(); input[x] = this.gridSlots[x].getStack();
if( !input[x].isEmpty() ) if( !input[x].isEmpty() )
{ {
hasValue = true; hasValue = true;
} }
} }
if( hasValue ) if( hasValue )
{ {
return input; return input;
} }
return null; return null;
} }
protected ItemStack[] getOutputs() protected ItemStack[] getOutputs()
{ {
final List<ItemStack> list = new ArrayList<>( 3 ); final List<ItemStack> list = new ArrayList<>( 3 );
boolean hasValue = false; boolean hasValue = false;
for( final OptionalSlotFake outputSlot : this.outputSlots ) for( final OptionalSlotFake outputSlot : this.outputSlots )
{ {
final ItemStack out = outputSlot.getStack(); final ItemStack out = outputSlot.getStack();
if( !out.isEmpty() && out.getCount() > 0 ) if( !out.isEmpty() && out.getCount() > 0 )
{ {
list.add( out ); list.add( out );
hasValue = true; hasValue = true;
} }
} }
if( hasValue ) if( hasValue )
{ {
return list.toArray( new ItemStack[0] ); return list.toArray( new ItemStack[0] );
} }
return null; return null;
} }
public void clear() public void clear()
{ {
for( final Slot s : this.gridSlots ) for( final Slot s : this.gridSlots )
{ {
s.putStack( ItemStack.EMPTY ); s.putStack( ItemStack.EMPTY );
} }
for( final Slot s : this.outputSlots ) for( final Slot s : this.outputSlots )
{ {
s.putStack( ItemStack.EMPTY ); s.putStack( ItemStack.EMPTY );
} }
this.detectAndSendChanges(); this.detectAndSendChanges();
} }
@Override @Override
public IItemHandler getInventoryByName( final String name ) public IItemHandler getInventoryByName( final String name )
{ {
if( name.equals( "player" ) ) if( name.equals( "player" ) )
{ {
return new PlayerInvWrapper( this.getInventoryPlayer() ); return new PlayerInvWrapper( this.getInventoryPlayer() );
} }
return this.getExpandedPatternTerminal().getInventoryByName( name ); return this.getExpandedPatternTerminal().getInventoryByName( name );
} }
@Override @Override
public boolean useRealItems() public boolean useRealItems()
{ {
return false; return false;
} }
public PartExpandedProcessingPatternTerminal getExpandedPatternTerminal() public PartExpandedProcessingPatternTerminal getExpandedPatternTerminal()
{ {
return this.expandedProcessingPatternTerminal; return this.expandedProcessingPatternTerminal;
} }
public void multiply( int multiple ) public void multiply( int multiple )
{ {
ItemStack[] input = new ItemStack[gridSlots.length]; ItemStack[] input = new ItemStack[gridSlots.length];
boolean canMultiplyInputs = true; boolean canMultiplyInputs = true;
boolean canMultiplyOutputs = true; boolean canMultiplyOutputs = true;
for( int x = 0; x < this.gridSlots.length; x++ ) for( int x = 0; x < this.gridSlots.length; x++ )
{ {
input[x] = this.gridSlots[x].getStack(); input[x] = this.gridSlots[x].getStack();
if( !input[x].isEmpty() && input[x].getCount() * multiple > input[x].getMaxStackSize() ) if( !input[x].isEmpty() && input[x].getCount() * multiple > input[x].getMaxStackSize() )
{ {
canMultiplyInputs = false; canMultiplyInputs = false;
} }
} }
for( final OptionalSlotFake outputSlot : this.outputSlots ) for( final OptionalSlotFake outputSlot : this.outputSlots )
{ {
final ItemStack out = outputSlot.getStack(); final ItemStack out = outputSlot.getStack();
if( !out.isEmpty() && out.getCount() * multiple > out.getMaxStackSize() ) if( !out.isEmpty() && out.getCount() * multiple > out.getMaxStackSize() )
{ {
canMultiplyOutputs = false; canMultiplyOutputs = false;
} }
} }
if( canMultiplyInputs && canMultiplyOutputs ) if( canMultiplyInputs && canMultiplyOutputs )
{ {
for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots ) for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots )
{ {
ItemStack stack = craftingSlot.getStack(); ItemStack stack = craftingSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
craftingSlot.getStack().setCount( stack.getCount() * multiple ); craftingSlot.getStack().setCount( stack.getCount() * multiple );
} }
} }
for( OptionalSlotFake outputSlot : this.outputSlots ) for( OptionalSlotFake outputSlot : this.outputSlots )
{ {
ItemStack stack = outputSlot.getStack(); ItemStack stack = outputSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
outputSlot.getStack().setCount( stack.getCount() * multiple ); outputSlot.getStack().setCount( stack.getCount() * multiple );
} }
} }
} }
} }
public void divide( int divide ) public void divide( int divide )
{ {
ItemStack[] input = new ItemStack[gridSlots.length]; ItemStack[] input = new ItemStack[gridSlots.length];
boolean canDivideInputs = true; boolean canDivideInputs = true;
boolean canDivideOutputs = true; boolean canDivideOutputs = true;
for( int x = 0; x < this.gridSlots.length; x++ ) for( int x = 0; x < this.gridSlots.length; x++ )
{ {
input[x] = this.gridSlots[x].getStack(); input[x] = this.gridSlots[x].getStack();
if( !input[x].isEmpty() && input[x].getCount() % divide != 0 ) if( !input[x].isEmpty() && input[x].getCount() % divide != 0 )
{ {
canDivideInputs = false; canDivideInputs = false;
} }
} }
for( final OptionalSlotFake outputSlot : this.outputSlots ) for( final OptionalSlotFake outputSlot : this.outputSlots )
{ {
final ItemStack out = outputSlot.getStack(); final ItemStack out = outputSlot.getStack();
if( !out.isEmpty() && out.getCount() % divide != 0 ) if( !out.isEmpty() && out.getCount() % divide != 0 )
{ {
canDivideOutputs = false; canDivideOutputs = false;
} }
} }
if( canDivideInputs && canDivideOutputs ) if( canDivideInputs && canDivideOutputs )
{ {
for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots ) for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots )
{ {
ItemStack stack = craftingSlot.getStack(); ItemStack stack = craftingSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
craftingSlot.getStack().setCount( stack.getCount() / divide ); craftingSlot.getStack().setCount( stack.getCount() / divide );
} }
} }
for( OptionalSlotFake outputSlot : this.outputSlots ) for( OptionalSlotFake outputSlot : this.outputSlots )
{ {
ItemStack stack = outputSlot.getStack(); ItemStack stack = outputSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
outputSlot.getStack().setCount( stack.getCount() / divide ); outputSlot.getStack().setCount( stack.getCount() / divide );
} }
} }
} }
} }
public void increase( int increase ) public void increase( int increase )
{ {
ItemStack[] input = new ItemStack[gridSlots.length]; ItemStack[] input = new ItemStack[gridSlots.length];
boolean canIncreaseInputs = true; boolean canIncreaseInputs = true;
boolean canIncreaseOutputs = true; boolean canIncreaseOutputs = true;
for( int x = 0; x < this.gridSlots.length; x++ ) for( int x = 0; x < this.gridSlots.length; x++ )
{ {
input[x] = this.gridSlots[x].getStack(); input[x] = this.gridSlots[x].getStack();
if( !input[x].isEmpty() && input[x].getCount() + increase > input[x].getMaxStackSize() ) if( !input[x].isEmpty() && input[x].getCount() + increase > input[x].getMaxStackSize() )
{ {
canIncreaseInputs = false; canIncreaseInputs = false;
} }
} }
for( final OptionalSlotFake outputSlot : this.outputSlots ) for( final OptionalSlotFake outputSlot : this.outputSlots )
{ {
final ItemStack out = outputSlot.getStack(); final ItemStack out = outputSlot.getStack();
if( !out.isEmpty() && out.getCount() + increase > out.getMaxStackSize() ) if( !out.isEmpty() && out.getCount() + increase > out.getMaxStackSize() )
{ {
canIncreaseOutputs = false; canIncreaseOutputs = false;
} }
} }
if( canIncreaseInputs && canIncreaseOutputs ) if( canIncreaseInputs && canIncreaseOutputs )
{ {
for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots ) for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots )
{ {
ItemStack stack = craftingSlot.getStack(); ItemStack stack = craftingSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
craftingSlot.getStack().setCount( stack.getCount() + increase ); craftingSlot.getStack().setCount( stack.getCount() + increase );
} }
} }
for( OptionalSlotFake outputSlot : this.outputSlots ) for( OptionalSlotFake outputSlot : this.outputSlots )
{ {
ItemStack stack = outputSlot.getStack(); ItemStack stack = outputSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
outputSlot.getStack().setCount( stack.getCount() + increase ); outputSlot.getStack().setCount( stack.getCount() + increase );
} }
} }
} }
} }
public void decrease( int decrease ) public void decrease( int decrease )
{ {
ItemStack[] input = new ItemStack[gridSlots.length]; ItemStack[] input = new ItemStack[gridSlots.length];
boolean canDecreaseInputs = true; boolean canDecreaseInputs = true;
boolean canDecreaseOutputs = true; boolean canDecreaseOutputs = true;
for( int x = 0; x < this.gridSlots.length; x++ ) for( int x = 0; x < this.gridSlots.length; x++ )
{ {
input[x] = this.gridSlots[x].getStack(); input[x] = this.gridSlots[x].getStack();
if( !input[x].isEmpty() && input[x].getCount() - decrease < 1 ) if( !input[x].isEmpty() && input[x].getCount() - decrease < 1 )
{ {
canDecreaseInputs = false; canDecreaseInputs = false;
} }
} }
for( final OptionalSlotFake outputSlot : this.outputSlots ) for( final OptionalSlotFake outputSlot : this.outputSlots )
{ {
final ItemStack out = outputSlot.getStack(); final ItemStack out = outputSlot.getStack();
if( !out.isEmpty() && out.getCount() - decrease < 1 ) if( !out.isEmpty() && out.getCount() - decrease < 1 )
{ {
canDecreaseOutputs = false; canDecreaseOutputs = false;
} }
} }
if( canDecreaseInputs && canDecreaseOutputs ) if( canDecreaseInputs && canDecreaseOutputs )
{ {
for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots ) for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots )
{ {
ItemStack stack = craftingSlot.getStack(); ItemStack stack = craftingSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
craftingSlot.getStack().setCount( stack.getCount() - decrease ); craftingSlot.getStack().setCount( stack.getCount() - decrease );
} }
} }
for( OptionalSlotFake outputSlot : this.outputSlots ) for( OptionalSlotFake outputSlot : this.outputSlots )
{ {
ItemStack stack = outputSlot.getStack(); ItemStack stack = outputSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
outputSlot.getStack().setCount( stack.getCount() - decrease ); outputSlot.getStack().setCount( stack.getCount() - decrease );
} }
} }
} }
} }
public void maximizeCount() public void maximizeCount()
{ {
ItemStack[] input = new ItemStack[gridSlots.length]; ItemStack[] input = new ItemStack[gridSlots.length];
boolean canGrowInputs = true; boolean canGrowInputs = true;
boolean canGrowOutputs = true; boolean canGrowOutputs = true;
int maxInputStackGrowth = 0; int maxInputStackGrowth = 0;
int maxOutputStackGrowth = 0; int maxOutputStackGrowth = 0;
for( int x = 0; x < this.gridSlots.length; x++ ) for( int x = 0; x < this.gridSlots.length; x++ )
{ {
input[x] = this.gridSlots[x].getStack(); input[x] = this.gridSlots[x].getStack();
if( !input[x].isEmpty() && input[x].getMaxStackSize() - input[x].getCount() > maxInputStackGrowth ) if( !input[x].isEmpty() && input[x].getMaxStackSize() - input[x].getCount() > maxInputStackGrowth )
{ {
maxInputStackGrowth = input[x].getMaxStackSize() - input[x].getCount(); maxInputStackGrowth = input[x].getMaxStackSize() - input[x].getCount();
} }
if( !input[x].isEmpty() && input[x].getCount() + maxInputStackGrowth > input[x].getMaxStackSize() ) if( !input[x].isEmpty() && input[x].getCount() + maxInputStackGrowth > input[x].getMaxStackSize() )
{ {
canGrowInputs = false; canGrowInputs = false;
} }
} }
for( final OptionalSlotFake outputSlot : this.outputSlots ) for( final OptionalSlotFake outputSlot : this.outputSlots )
{ {
final ItemStack out = outputSlot.getStack(); final ItemStack out = outputSlot.getStack();
{ {
maxOutputStackGrowth = out.getMaxStackSize() - out.getCount(); maxOutputStackGrowth = out.getMaxStackSize() - out.getCount();
} }
if( !out.isEmpty() && out.getCount() + maxOutputStackGrowth > out.getMaxStackSize() ) if( !out.isEmpty() && out.getCount() + maxOutputStackGrowth > out.getMaxStackSize() )
{ {
canGrowOutputs = false; canGrowOutputs = false;
} }
} }
if( canGrowInputs && canGrowOutputs ) if( canGrowInputs && canGrowOutputs )
{ {
int maxStackGrowth = Math.min( maxInputStackGrowth, maxOutputStackGrowth ); int maxStackGrowth = Math.min( maxInputStackGrowth, maxOutputStackGrowth );
for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots ) for( SlotFakeCraftingMatrix craftingSlot : this.gridSlots )
{ {
ItemStack stack = craftingSlot.getStack(); ItemStack stack = craftingSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
craftingSlot.getStack().setCount( stack.getCount() + maxStackGrowth ); craftingSlot.getStack().setCount( stack.getCount() + maxStackGrowth );
} }
} }
for( OptionalSlotFake outputSlot : this.outputSlots ) for( OptionalSlotFake outputSlot : this.outputSlots )
{ {
ItemStack stack = outputSlot.getStack(); ItemStack stack = outputSlot.getStack();
if( !stack.isEmpty() ) if( !stack.isEmpty() )
{ {
outputSlot.getStack().setCount( stack.getCount() + maxStackGrowth ); outputSlot.getStack().setCount( stack.getCount() + maxStackGrowth );
} }
} }
} }
} }
@Override
public void onSlotChange( final Slot s )
{
if( s == this.patternSlotOUT && Platform.isServer() )
{
for( final IContainerListener listener : this.listeners )
{
for( final Slot slot : this.inventorySlots )
{
if( slot instanceof OptionalSlotFake || slot instanceof SlotFakeCraftingMatrix )
{
listener.sendSlotContents( this, slot.slotNumber, slot.getStack() );
}
}
if( listener instanceof EntityPlayerMP )
{
( (EntityPlayerMP) listener ).isChangingQuantityOnly = false;
}
}
this.detectAndSendChanges();
}
}
} }
@@ -0,0 +1,400 @@
/*
* 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.container.implementations;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import appeng.parts.reporting.PartInterfaceConfigurationTerminal;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.items.IItemHandler;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.security.IActionHost;
import appeng.container.AEBaseContainer;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketCompressedNBT;
import appeng.helpers.DualityInterface;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.InventoryAction;
import appeng.parts.misc.PartInterface;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.tile.misc.TileInterface;
import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.WrapperRangeItemHandler;
public final class ContainerInterfaceConfigurationTerminal extends AEBaseContainer
{
/**
* this stuff is all server side..
*/
private static long autoBase = Long.MIN_VALUE;
private final Map<IInterfaceHost, ConfigTracker> diList = new HashMap<>();
private final Map<Long, ConfigTracker> byId = new HashMap<>();
private IGrid grid;
private NBTTagCompound data = new NBTTagCompound();
public ContainerInterfaceConfigurationTerminal( final InventoryPlayer ip, final PartInterfaceConfigurationTerminal anchor )
{
super( ip, anchor );
if( Platform.isServer() )
{
this.grid = anchor.getActionableNode().getGrid();
}
this.bindPlayerInventory( ip, 14, 235 - /* height of player inventory */82 );
}
@Override
public void detectAndSendChanges()
{
if( Platform.isClient() )
{
return;
}
super.detectAndSendChanges();
if( this.grid == null )
{
return;
}
int total = 0;
boolean missing = false;
final IActionHost host = this.getActionHost();
if( host != null )
{
final IGridNode agn = host.getActionableNode();
if( agn != null && agn.isActive() )
{
for( final IGridNode gn : this.grid.getMachines( TileInterface.class ) )
{
if( gn.isActive() )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
if( ih.getInterfaceDuality().getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.NO )
{
continue;
}
final ConfigTracker t = this.diList.get( ih );
if( t == null )
{
missing = true;
}
else
{
final DualityInterface dual = ih.getInterfaceDuality();
if( !t.unlocalizedName.equals( dual.getTermName() ) )
{
missing = true;
}
}
total++;
}
}
for( final IGridNode gn : this.grid.getMachines( PartInterface.class ) )
{
if( gn.isActive() )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
if( ih.getInterfaceDuality().getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.NO )
{
continue;
}
final ConfigTracker t = this.diList.get( ih );
if( t == null )
{
missing = true;
}
else
{
final DualityInterface dual = ih.getInterfaceDuality();
if( !t.unlocalizedName.equals( dual.getTermName() ) )
{
missing = true;
}
}
total++;
}
}
}
}
if( total != this.diList.size() || missing )
{
this.regenList( this.data );
}
else
{
for( final Entry<IInterfaceHost, ConfigTracker> en : this.diList.entrySet() )
{
final ConfigTracker inv = en.getValue();
for( int x = 0; x < inv.server.getSlots(); x++ )
{
if( this.isDifferent( inv.server.getStackInSlot( x ), inv.client.getStackInSlot( x ) ) )
{
this.addItems( this.data, inv, x, 1 );
}
}
}
}
if( !this.data.hasNoTags() )
{
try
{
NetworkHandler.instance().sendTo( new PacketCompressedNBT( this.data ), (EntityPlayerMP) this.getPlayerInv().player );
}
catch( final IOException e )
{
// :P
}
this.data = new NBTTagCompound();
}
}
public ConfigTracker getSlotByID( long id )
{
return this.byId.get( id );
}
@Override
public void doAction( final EntityPlayerMP player, final InventoryAction action, final int slot, final long id )
{
final ConfigTracker inv = this.byId.get( id );
if( inv != null )
{
final boolean hasItemInHand = !player.inventory.getItemStack().isEmpty();
final IItemHandler theSlot = new WrapperRangeItemHandler( inv.server, slot, slot + 1 );
ItemStack inSlot = theSlot.getStackInSlot( 0 );
switch ( action )
{
case PICKUP_OR_SET_DOWN:
if( hasItemInHand )
{
ItemHandlerUtil.setStackInSlot( theSlot, 0, player.inventory.getItemStack().copy() );
}
else
{
ItemHandlerUtil.setStackInSlot( theSlot, 0, ItemStack.EMPTY );
}
break;
case PLACE_SINGLE:
if( inSlot.getMaxStackSize() > inSlot.getCount() )
{
inSlot.grow( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot );
}
break;
case PICKUP_SINGLE:
if( theSlot.getStackInSlot( 0 ).getCount() > 1 )
{
inSlot.shrink( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot );
}
break;
case SPLIT_OR_PLACE_SINGLE:
if( hasItemInHand )
{
if( ItemStack.areItemsEqual( inSlot, player.inventory.getItemStack() ) && ItemStack.areItemStackTagsEqual( inSlot, player.inventory.getItemStack() ) )
{
inSlot.grow( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot.copy() );
}
else
{
ItemStack configuredStack = player.inventory.getItemStack().copy();
configuredStack.setCount( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, configuredStack );
}
}
else if( !inSlot.isEmpty() )
{
inSlot.shrink( 1 );
ItemHandlerUtil.setStackInSlot( theSlot, 0, inSlot.copy() );
}
break;
case SHIFT_CLICK:
ItemHandlerUtil.setStackInSlot( theSlot, 0, ItemStack.EMPTY );
break;
case CREATIVE_DUPLICATE:
if( player.capabilities.isCreativeMode && hasItemInHand )
{
ItemHandlerUtil.setStackInSlot( theSlot, 0, player.inventory.getItemStack().copy() );
}
break;
default:
return;
}
this.updateHeld( player );
}
}
private void regenList( final NBTTagCompound data )
{
this.byId.clear();
this.diList.clear();
final IActionHost host = this.getActionHost();
if( host != null )
{
final IGridNode agn = host.getActionableNode();
if( agn != null && agn.isActive() )
{
for( final IGridNode gn : this.grid.getMachines( TileInterface.class ) )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
final DualityInterface dual = ih.getInterfaceDuality();
if( gn.isActive() && dual.getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.YES )
{
this.diList.put( ih, new ConfigTracker( dual, dual.getConfig(), dual.getTermName() ) );
}
}
for( final IGridNode gn : this.grid.getMachines( PartInterface.class ) )
{
final IInterfaceHost ih = (IInterfaceHost) gn.getMachine();
final DualityInterface dual = ih.getInterfaceDuality();
if( gn.isActive() && dual.getConfigManager().getSetting( Settings.INTERFACE_TERMINAL ) == YesNo.YES )
{
this.diList.put( ih, new ConfigTracker( dual, dual.getConfig(), dual.getTermName() ) );
}
}
}
}
data.setBoolean( "clear", true );
for( final Entry<IInterfaceHost, ConfigTracker> en : this.diList.entrySet() )
{
final ConfigTracker inv = en.getValue();
this.byId.put( inv.which, inv );
this.addItems( data, inv, 0, inv.server.getSlots() );
}
}
private boolean isDifferent( final ItemStack a, final ItemStack b )
{
if( a.isEmpty() && b.isEmpty() )
{
return false;
}
if( a.isEmpty() || b.isEmpty() )
{
return true;
}
return !ItemStack.areItemStacksEqual( a, b );
}
private void addItems( final NBTTagCompound data, final ConfigTracker inv, final int offset, final int length )
{
final String name = '=' + Long.toString( inv.which, Character.MAX_RADIX );
final NBTTagCompound tag = data.getCompoundTag( name );
if( tag.hasNoTags() )
{
tag.setLong( "sortBy", inv.sortBy );
tag.setString( "un", inv.unlocalizedName );
tag.setTag( "pos", NBTUtil.createPosTag( inv.pos ) );
tag.setInteger( "dim", inv.dim );
}
for( int x = 0; x < length; x++ )
{
final NBTTagCompound itemNBT = new NBTTagCompound();
final ItemStack is = inv.server.getStackInSlot( x + offset );
// "update" client side.
ItemHandlerUtil.setStackInSlot( inv.client, x + offset, is.isEmpty() ? ItemStack.EMPTY : is.copy() );
if( !is.isEmpty() )
{
is.writeToNBT( itemNBT );
}
tag.setTag( Integer.toString( x + offset ), itemNBT );
}
data.setTag( name, tag );
}
public static class ConfigTracker
{
private final long sortBy;
private final long which = autoBase++;
private final String unlocalizedName;
private final IItemHandler client;
private final IItemHandler server;
private final BlockPos pos;
private final int dim;
public ConfigTracker( final DualityInterface dual, final IItemHandler configSlots, final String unlocalizedName )
{
this.server = configSlots;
this.client = new AppEngInternalInventory( null, this.server.getSlots() );
this.unlocalizedName = unlocalizedName;
this.sortBy = dual.getSortValue();
this.pos = dual.getLocation().getPos();
this.dim = dual.getLocation().getWorld().provider.getDimension();
}
public IItemHandler getServer()
{
return server;
}
}
}
@@ -20,6 +20,7 @@ package appeng.container.implementations;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
@@ -50,7 +51,7 @@ public class ContainerNetworkTool extends AEBaseContainer
for( int x = 0; x < 3; x++ ) for( int x = 0; x < 3; x++ )
{ {
this.addSlotToContainer( ( new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, te this.addSlotToContainer( ( new SlotRestrictedInput( SlotRestrictedInput.PlacableItemType.UPGRADES, te
.getInventory(), y * 3 + x, 80 - 18 + x * 18, 37 - 18 + y * 18, this.getInventoryPlayer() ) ) ); .getInventory(), y * 3 + x, 80 - 18 + x * 18, 37 - 18 + y * 18, this.getInventoryPlayer() ) ) );
} }
} }
@@ -97,6 +98,13 @@ public class ContainerNetworkTool extends AEBaseContainer
super.detectAndSendChanges(); super.detectAndSendChanges();
} }
@Override
public void onSlotChange( Slot s )
{
super.detectAndSendChanges();
}
public boolean isFacadeMode() public boolean isFacadeMode()
{ {
return this.facadeMode; return this.facadeMode;
@@ -1,27 +1,20 @@
package appeng.container.implementations; package appeng.container.implementations;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.AccessRestriction; import appeng.api.config.*;
import appeng.api.config.FuzzyMode;
import appeng.api.config.Settings;
import appeng.api.config.StorageFilter;
import appeng.api.storage.IMEInventory; import appeng.api.storage.IMEInventory;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.container.AEBaseContainer; import appeng.container.AEBaseContainer;
import appeng.container.guisync.GuiSync;
import appeng.core.sync.network.NetworkHandler; import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketValueConfig; import appeng.core.sync.packets.PacketValueConfig;
import appeng.parts.misc.PartOreDicStorageBus; import appeng.parts.misc.PartOreDicStorageBus;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import appeng.util.item.OreReference; import appeng.util.item.OreReference;
import appeng.util.iterators.NullIterator;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.oredict.OreDictionary; import net.minecraftforge.oredict.OreDictionary;
import java.io.IOException; import java.io.IOException;
@@ -30,11 +23,17 @@ import java.util.Iterator;
import java.util.Set; import java.util.Set;
public class ContainerPartOreDictStorageBus extends AEBaseContainer public class ContainerOreDictStorageBus extends AEBaseContainer
{ {
private final PartOreDicStorageBus part; private final PartOreDicStorageBus part;
public ContainerPartOreDictStorageBus( final InventoryPlayer ip, final PartOreDicStorageBus anchor ) @GuiSync( 3 )
public AccessRestriction rwMode = AccessRestriction.READ_WRITE;
@GuiSync( 4 )
public StorageFilter storageFilter = StorageFilter.EXTRACTABLE_ONLY;
public ContainerOreDictStorageBus( final InventoryPlayer ip, final PartOreDicStorageBus anchor )
{ {
super( ip, anchor ); super( ip, anchor );
this.part = anchor; this.part = anchor;
@@ -45,9 +44,12 @@ public class ContainerPartOreDictStorageBus extends AEBaseContainer
@Override @Override
public void detectAndSendChanges() public void detectAndSendChanges()
{ {
if( Platform.isClient() ) this.verifyPermissions( SecurityPermissions.BUILD, false );
if( Platform.isServer() )
{ {
return; this.setReadWriteMode( (AccessRestriction) part.getConfigManager().getSetting( Settings.ACCESS ) );
this.setStorageFilter( (StorageFilter) part.getConfigManager().getSetting( Settings.STORAGE_FILTER ) );
} }
super.detectAndSendChanges(); super.detectAndSendChanges();
@@ -57,6 +59,11 @@ public class ContainerPartOreDictStorageBus extends AEBaseContainer
{ {
final IMEInventory<IAEItemStack> cellInv = this.part.getInternalHandler(); final IMEInventory<IAEItemStack> cellInv = this.part.getInternalHandler();
if( cellInv == null )
{
return;
}
Set<Integer> oreIDs = new HashSet<>(); Set<Integer> oreIDs = new HashSet<>();
for( IAEItemStack itemStack : cellInv.getAvailableItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) ) for( IAEItemStack itemStack : cellInv.getAvailableItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) )
@@ -103,11 +110,31 @@ public class ContainerPartOreDictStorageBus extends AEBaseContainer
{ {
try try
{ {
NetworkHandler.instance().sendTo( new PacketValueConfig( "OreDictStorageBus.sendRegex", part.getOreMatch() ), (EntityPlayerMP) getInventoryPlayer().player ); NetworkHandler.instance().sendTo( new PacketValueConfig( "OreDictStorageBus.sendRegex", part.getOreExp() ), (EntityPlayerMP) getInventoryPlayer().player );
} }
catch( IOException e ) catch( IOException e )
{ {
e.printStackTrace(); e.printStackTrace();
} }
} }
public AccessRestriction getReadWriteMode()
{
return this.rwMode;
}
private void setReadWriteMode( final AccessRestriction rwMode )
{
this.rwMode = rwMode;
}
public StorageFilter getStorageFilter()
{
return this.storageFilter;
}
private void setStorageFilter( final StorageFilter storageFilter )
{
this.storageFilter = storageFilter;
}
} }
@@ -138,6 +138,15 @@ public class AppEngSlot extends Slot
public void onSlotChanged() public void onSlotChanged()
{ {
this.setIsValid( hasCalculatedValidness.NotAvailable ); this.setIsValid( hasCalculatedValidness.NotAvailable );
if( this.isSlotEnabled() )
{
ItemHandlerUtil.setStackInSlot( this.itemHandler, this.index, this.getStack().copy() );
if( this.getContainer() != null )
{
this.getContainer().onSlotChange( this );
}
}
} }
@Override @Override
+74 -102
View File
@@ -19,30 +19,7 @@
package appeng.core; package appeng.core;
import java.io.File; import appeng.api.config.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import com.google.common.collect.Sets;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import appeng.api.config.CondenserOutput;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.PowerUnits;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.Settings;
import appeng.api.config.TerminalStyle;
import appeng.api.config.YesNo;
import appeng.api.util.IConfigManager; import appeng.api.util.IConfigManager;
import appeng.api.util.IConfigurableObject; import appeng.api.util.IConfigurableObject;
import appeng.core.features.AEFeature; import appeng.core.features.AEFeature;
@@ -51,6 +28,17 @@ import appeng.items.materials.MaterialType;
import appeng.util.ConfigManager; import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost; import appeng.util.IConfigManagerHost;
import appeng.util.Platform; import appeng.util.Platform;
import com.google.common.collect.Sets;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.File;
import java.util.*;
import java.util.stream.Stream;
public final class AEConfig extends Configuration implements IConfigurableObject, IConfigManagerHost public final class AEConfig extends Configuration implements IConfigurableObject, IConfigManagerHost
@@ -59,26 +47,33 @@ public final class AEConfig extends Configuration implements IConfigurableObject
public static final String VERSION = "@version@"; public static final String VERSION = "@version@";
public static final String CHANNEL = "@aechannel@"; public static final String CHANNEL = "@aechannel@";
public static final String PACKET_CHANNEL = "AE"; public static final String PACKET_CHANNEL = "AE";
// Tunnels
// Config instance public static final double TUNNEL_POWER_LOSS = 0.05;
private static AEConfig instance;
// Default Grindstone ores // Default Grindstone ores
private static final String[] ORES_VANILLA = { "Obsidian", "Ender", "EnderPearl", "Coal", "Iron", "Gold", "Charcoal", "NetherQuartz" }; private static final String[] ORES_VANILLA = {"Obsidian", "Ender", "EnderPearl", "Coal", "Iron", "Gold", "Charcoal", "NetherQuartz"};
private static final String[] ORES_AE = { "CertusQuartz", "Wheat", "Fluix" }; private static final String[] ORES_AE = {"CertusQuartz", "Wheat", "Fluix"};
private static final String[] ORES_COMMON = { "Copper", "Tin", "Silver", "Lead", "Bronze" }; private static final String[] ORES_COMMON = {"Copper", "Tin", "Silver", "Lead", "Bronze"};
private static final String[] ORES_MISC = { "Brass", "Platinum", "Nickel", "Invar", "Aluminium", "Electrum", "Osmium", "Zinc" }; private static final String[] ORES_MISC = {"Brass", "Platinum", "Nickel", "Invar", "Aluminium", "Electrum", "Osmium", "Zinc"};
// Default Energy Conversion Rates // Default Energy Conversion Rates
private static final double DEFAULT_IC2_EXCHANGE = 2.0; private static final double DEFAULT_IC2_EXCHANGE = 2.0;
private static final double DEFAULT_GTEU_EXCHANGE = 2.0;
private static final double DEFAULT_RF_EXCHANGE = 0.5; private static final double DEFAULT_RF_EXCHANGE = 0.5;
// Config instance
private static AEConfig instance;
private final IConfigManager settings = new ConfigManager( this ); private final IConfigManager settings = new ConfigManager( this );
private final EnumSet<AEFeature> featureFlags = EnumSet.noneOf( AEFeature.class ); private final EnumSet<AEFeature> featureFlags = EnumSet.noneOf( AEFeature.class );
private final File configFile; private final File configFile;
// GUI Buttons
private final int[] craftByStacks = {1, 10, 100, 1000};
private final int[] priorityByStacks = {1, 10, 100, 1000};
private final int[] levelByStacks = {1, 10, 100, 1000};
private final int[] levelByMillibuckets = {10, 100, 1000, 10000};
private final Set<String> grinderBlackList;
private final int chargedChange = 4;
private final double wirelessHighWirelessCount = 64;
private String[] nonBlockingItems = {"[gregtech|actuallyadditions]", "gregtech:circuit.integrated", "gregtech:shape.mold.plate", "gregtech:shape.mold.gear", "gregtech:shape.mold.credit", "gregtech:shape.mold.bottle", "gregtech:shape.mold.ingot", "gregtech:shape.mold.ball", "gregtech:shape.mold.block", "gregtech:shape.mold.nugget", "gregtech:shape.mold.cylinder", "gregtech:shape.mold.anvil", "gregtech:shape.mold.name", "gregtech:shape.mold.gear.small", "gregtech:shape.mold.rotor", "gregtech:shape.extruder.plate", "gregtech:shape.extruder.rod", "gregtech:shape.extruder.bolt", "gregtech:shape.extruder.ring", "gregtech:shape.extruder.cell", "gregtech:shape.extruder.ingot", "gregtech:shape.extruder.wire", "gregtech:shape.extruder.pipe.tiny", "gregtech:shape.extruder.pipe.small", "gregtech:shape.extruder.pipe.medium", "gregtech:shape.extruder.pipe.normal", "gregtech:shape.extruder.pipe.large", "gregtech:shape.extruder.pipe.huge", "gregtech:shape.extruder.block", "gregtech:shape.extruder.sword", "gregtech:shape.extruder.pickaxe", "gregtech:shape.extruder.shovel", "gregtech:shape.extruder.axe", "gregtech:shape.extruder.hoe", "gregtech:shape.extruder.hammer", "gregtech:shape.extruder.file", "gregtech:shape.extruder.saw", "gregtech:shape.extruder.gear", "gregtech:shape.extruder.bottle", "gregtech:shape.extruder.foil", "gregtech:shape.extruder.gear_small", "gregtech:shape.extruder.rod_long", "gregtech:shape.extruder.rotor", "gregtech:glass_lens.white", "gregtech:glass_lens.orange", "gregtech:glass_lens.magenta", "gregtech:glass_lens.light_blue", "gregtech:glass_lens.yellow", "gregtech:glass_lens.lime", "gregtech:glass_lens.pink", "gregtech:glass_lens.gray", "gregtech:glass_lens.light_gray", "gregtech:glass_lens.cyan", "gregtech:glass_lens.purple", "gregtech:glass_lens.blue", "gregtech:glass_lens.brown", "gregtech:glass_lens.green", "gregtech:glass_lens.red", "gregtech:glass_lens.black", "contenttweaker:smallgearextrudershape", "contenttweaker:creativeportabletankmold", "ore:lensAlmandine", "ore:lensBlueTopaz", "ore:lensDiamond", "ore:lensEmerald", "ore:lensGreenSapphire", "ore:lensRutile", "ore:lensRuby", "ore:lensSapphire", "ore:lensTopaz", "ore:lensJasper", "ore:lensGlass", "ore:lensOlivine", "ore:lensOpal", "ore:lensAmethyst", "ore:lensLapis", "ore:lensEnderPearl", "ore:lensEnderEye", "ore:lensGarnetRed", "ore:lensGarnetYellow", "ore:lensVinteum", "ore:lensNetherStar",};
private boolean updatable = false; private boolean updatable = false;
// Misc // Misc
private boolean removeCrashingItemsOnLoad = false; private boolean removeCrashingItemsOnLoad = false;
private int formationPlaneEntityLimit = 128; private int formationPlaneEntityLimit = 128;
@@ -88,24 +83,14 @@ public final class AEConfig extends Configuration implements IConfigurableObject
private boolean disableColoredCableRecipesInJEI = true; private boolean disableColoredCableRecipesInJEI = true;
private int craftingCalculationTimePerTick = 5; private int craftingCalculationTimePerTick = 5;
private PowerUnits selectedPowerUnit = PowerUnits.AE; private PowerUnits selectedPowerUnit = PowerUnits.AE;
// GUI Buttons
private final int[] craftByStacks = { 1, 10, 100, 1000 };
private final int[] priorityByStacks = { 1, 10, 100, 1000 };
private final int[] levelByStacks = { 1, 10, 100, 1000 };
private final int[] levelByMillibuckets = { 10, 100, 1000, 10000 };
// Spatial IO/Dimension // Spatial IO/Dimension
private int storageProviderID = -1; private int storageProviderID = -1;
private int storageDimensionID = -1; private int storageDimensionID = -1;
private double spatialPowerExponent = 1.35; private double spatialPowerExponent = 1.35;
private double spatialPowerMultiplier = 1250.0; private double spatialPowerMultiplier = 1250.0;
// Grindstone // Grindstone
private String[] grinderOres = Stream.of( ORES_VANILLA, ORES_AE, ORES_COMMON, ORES_MISC ).flatMap( Stream::of ).toArray( String[]::new ); private String[] grinderOres = Stream.of( ORES_VANILLA, ORES_AE, ORES_COMMON, ORES_MISC ).flatMap( Stream::of ).toArray( String[]::new );
private Set<String> grinderBlackList;
private double oreDoublePercentage = 90.0; private double oreDoublePercentage = 90.0;
// Batteries // Batteries
private int wirelessTerminalBattery = 1600000; private int wirelessTerminalBattery = 1600000;
private int entropyManipulatorBattery = 200000; private int entropyManipulatorBattery = 200000;
@@ -113,20 +98,16 @@ public final class AEConfig extends Configuration implements IConfigurableObject
private int portableCellBattery = 20000; private int portableCellBattery = 20000;
private int colorApplicatorBattery = 20000; private int colorApplicatorBattery = 20000;
private int chargedStaffBattery = 8000; private int chargedStaffBattery = 8000;
// Certus quartz // Certus quartz
private float spawnChargedChance = 0.92f; private float spawnChargedChance = 0.92f;
private int quartzOresPerCluster = 4; private int quartzOresPerCluster = 4;
private int quartzOresClusterAmount = 15; private int quartzOresClusterAmount = 15;
private int chargedChange = 4;
// Meteors // Meteors
private int minMeteoriteDistance = 707; private int minMeteoriteDistance = 707;
private int minMeteoriteDistanceSq = this.minMeteoriteDistance * this.minMeteoriteDistance; private int minMeteoriteDistanceSq = this.minMeteoriteDistance * this.minMeteoriteDistance;
private double meteoriteClusterChance = 0.1; private double meteoriteClusterChance = 0.1;
private int meteoriteMaximumSpawnHeight = 180; private int meteoriteMaximumSpawnHeight = 180;
private int[] meteoriteDimensionWhitelist = { 0 }; private int[] meteoriteDimensionWhitelist = {0};
// Wireless // Wireless
private double wirelessBaseCost = 8; private double wirelessBaseCost = 8;
private double wirelessCostMultiplier = 1; private double wirelessCostMultiplier = 1;
@@ -134,10 +115,8 @@ public final class AEConfig extends Configuration implements IConfigurableObject
private double wirelessBaseRange = 16; private double wirelessBaseRange = 16;
private double wirelessBoosterRangeMultiplier = 1; private double wirelessBoosterRangeMultiplier = 1;
private double wirelessBoosterExp = 1.5; private double wirelessBoosterExp = 1.5;
private double wirelessHighWirelessCount = 64; // Autocrafting
private boolean enableCraftingSubstitutes = false;
// Tunnels
public static final double TUNNEL_POWER_LOSS = 0.05;
private AEConfig( final File configFile ) private AEConfig( final File configFile )
{ {
@@ -148,6 +127,7 @@ public final class AEConfig extends Configuration implements IConfigurableObject
PowerUnits.EU.conversionRatio = this.get( "PowerRatios", "IC2", DEFAULT_IC2_EXCHANGE ).getDouble( DEFAULT_IC2_EXCHANGE ); PowerUnits.EU.conversionRatio = this.get( "PowerRatios", "IC2", DEFAULT_IC2_EXCHANGE ).getDouble( DEFAULT_IC2_EXCHANGE );
PowerUnits.RF.conversionRatio = this.get( "PowerRatios", "ForgeEnergy", DEFAULT_RF_EXCHANGE ).getDouble( DEFAULT_RF_EXCHANGE ); PowerUnits.RF.conversionRatio = this.get( "PowerRatios", "ForgeEnergy", DEFAULT_RF_EXCHANGE ).getDouble( DEFAULT_RF_EXCHANGE );
PowerUnits.GTEU.conversionRatio = this.get( "PowerRatios", "GTEU", DEFAULT_GTEU_EXCHANGE ).getDouble( DEFAULT_GTEU_EXCHANGE );
final double usageEffective = this.get( "PowerRatios", "UsageMultiplier", 1.0 ).getDouble( 1.0 ); final double usageEffective = this.get( "PowerRatios", "UsageMultiplier", 1.0 ).getDouble( 1.0 );
PowerMultiplier.CONFIG.multiplier = Math.max( 0.01, usageEffective ); PowerMultiplier.CONFIG.multiplier = Math.max( 0.01, usageEffective );
@@ -155,32 +135,24 @@ public final class AEConfig extends Configuration implements IConfigurableObject
CondenserOutput.MATTER_BALLS.requiredPower = this.get( "Condenser", "MatterBalls", 256 ).getInt( 256 ); CondenserOutput.MATTER_BALLS.requiredPower = this.get( "Condenser", "MatterBalls", 256 ).getInt( 256 );
CondenserOutput.SINGULARITY.requiredPower = this.get( "Condenser", "Singularity", 256000 ).getInt( 256000 ); CondenserOutput.SINGULARITY.requiredPower = this.get( "Condenser", "Singularity", 256000 ).getInt( 256000 );
this.removeCrashingItemsOnLoad = this.get( "general", "removeCrashingItemsOnLoad", false, this.removeCrashingItemsOnLoad = this.get( "general", "removeCrashingItemsOnLoad", false, "Will auto-remove items that crash when being loaded from storage. This will destroy those items instead of crashing the game!" ).getBoolean();
"Will auto-remove items that crash when being loaded from storage. This will destroy those items instead of crashing the game!" ).getBoolean();
this.setCategoryComment( "GrindStone", this.setCategoryComment( "BlockingMode", "Map of items to not block when blockingmode is enabled.\n[modid]\nmodid:item:metadata(optional,default:0)\nSupports more than one modid, so you can block different things between, for example, gregtech or enderio" );
"Creates recipe of the following pattern automatically: '1 oreTYPE => 2 dustTYPE' and '(1 ingotTYPE or 1 crystalTYPE or 1 gemTYPE) => 1 dustTYPE'" ); this.nonBlockingItems = this.get( "BlockingMode", "nonBlockingItems", nonBlockingItems, "NonBlockingItems" ).getStringList();
this.grinderOres = this.get( "GrindStone", "grinderOres", this.grinderOres, "The list of types to handle. Specify without a prefix like ore or dust." )
.getStringList(); this.setCategoryComment( "GrindStone", "Creates recipe of the following pattern automatically: '1 oreTYPE => 2 dustTYPE' and '(1 ingotTYPE or 1 crystalTYPE or 1 gemTYPE) => 1 dustTYPE'" );
this.grinderBlackList = Sets.newHashSet( this.grinderOres = this.get( "GrindStone", "grinderOres", this.grinderOres, "The list of types to handle. Specify without a prefix like ore or dust." ).getStringList();
this.get( "GrindStone", "blacklist", new String[] {}, "Blacklists the exact oredict name from being handled by any recipe." ) this.grinderBlackList = Sets.newHashSet( this.get( "GrindStone", "blacklist", new String[]{}, "Blacklists the exact oredict name from being handled by any recipe." ).getStringList() );
.getStringList() ); this.oreDoublePercentage = this.get( "GrindStone", "oreDoublePercentage", this.oreDoublePercentage, "Chance to actually get an output with stacksize > 1." ).getDouble( this.oreDoublePercentage );
this.oreDoublePercentage = this
.get( "GrindStone", "oreDoublePercentage", this.oreDoublePercentage, "Chance to actually get an output with stacksize > 1." )
.getDouble( this.oreDoublePercentage );
this.settings.registerSetting( Settings.SEARCH_TOOLTIPS, YesNo.YES ); this.settings.registerSetting( Settings.SEARCH_TOOLTIPS, YesNo.YES );
this.settings.registerSetting( Settings.TERMINAL_STYLE, TerminalStyle.TALL ); this.settings.registerSetting( Settings.TERMINAL_STYLE, TerminalStyle.TALL );
this.settings.registerSetting( Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH ); this.settings.registerSetting( Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH );
this.spawnChargedChance = (float) ( 1.0 - this.get( "worldGen", "spawnChargedChance", 1.0 - this.spawnChargedChance ) this.spawnChargedChance = (float) ( 1.0 - this.get( "worldGen", "spawnChargedChance", 1.0 - this.spawnChargedChance ).getDouble( 1.0 - this.spawnChargedChance ) );
.getDouble(
1.0 - this.spawnChargedChance ) );
this.minMeteoriteDistance = this.get( "worldGen", "minMeteoriteDistance", this.minMeteoriteDistance ).getInt( this.minMeteoriteDistance ); this.minMeteoriteDistance = this.get( "worldGen", "minMeteoriteDistance", this.minMeteoriteDistance ).getInt( this.minMeteoriteDistance );
this.meteoriteClusterChance = this.get( "worldGen", "meteoriteClusterChance", this.meteoriteClusterChance ).getDouble( this.meteoriteClusterChance ); this.meteoriteClusterChance = this.get( "worldGen", "meteoriteClusterChance", this.meteoriteClusterChance ).getDouble( this.meteoriteClusterChance );
this.meteoriteMaximumSpawnHeight = this.get( "worldGen", "meteoriteMaximumSpawnHeight", this.meteoriteMaximumSpawnHeight ) this.meteoriteMaximumSpawnHeight = this.get( "worldGen", "meteoriteMaximumSpawnHeight", this.meteoriteMaximumSpawnHeight ).getInt( this.meteoriteMaximumSpawnHeight );
.getInt(
this.meteoriteMaximumSpawnHeight );
this.meteoriteDimensionWhitelist = this.get( "worldGen", "meteoriteDimensionWhitelist", this.meteoriteDimensionWhitelist ).getIntList(); this.meteoriteDimensionWhitelist = this.get( "worldGen", "meteoriteDimensionWhitelist", this.meteoriteDimensionWhitelist ).getIntList();
this.quartzOresPerCluster = this.get( "worldGen", "quartzOresPerCluster", this.quartzOresPerCluster ).getInt( this.quartzOresPerCluster ); this.quartzOresPerCluster = this.get( "worldGen", "quartzOresPerCluster", this.quartzOresPerCluster ).getInt( this.quartzOresPerCluster );
@@ -188,23 +160,16 @@ public final class AEConfig extends Configuration implements IConfigurableObject
this.minMeteoriteDistanceSq = this.minMeteoriteDistance * this.minMeteoriteDistance; this.minMeteoriteDistanceSq = this.minMeteoriteDistance * this.minMeteoriteDistance;
this.addCustomCategoryComment( "wireless", this.addCustomCategoryComment( "wireless", "Range= wirelessBaseRange + wirelessBoosterRangeMultiplier * Math.pow( boosters, wirelessBoosterExp )\nPowerDrain= wirelessBaseCost + wirelessCostMultiplier * Math.pow( boosters, 1 + boosters / wirelessHighWirelessCount )" );
"Range= wirelessBaseRange + wirelessBoosterRangeMultiplier * Math.pow( boosters, wirelessBoosterExp )\nPowerDrain= wirelessBaseCost + wirelessCostMultiplier * Math.pow( boosters, 1 + boosters / wirelessHighWirelessCount )" );
this.wirelessBaseCost = this.get( "wireless", "wirelessBaseCost", this.wirelessBaseCost ).getDouble( this.wirelessBaseCost ); this.wirelessBaseCost = this.get( "wireless", "wirelessBaseCost", this.wirelessBaseCost ).getDouble( this.wirelessBaseCost );
this.wirelessCostMultiplier = this.get( "wireless", "wirelessCostMultiplier", this.wirelessCostMultiplier ).getDouble( this.wirelessCostMultiplier ); this.wirelessCostMultiplier = this.get( "wireless", "wirelessCostMultiplier", this.wirelessCostMultiplier ).getDouble( this.wirelessCostMultiplier );
this.wirelessBaseRange = this.get( "wireless", "wirelessBaseRange", this.wirelessBaseRange ).getDouble( this.wirelessBaseRange ); this.wirelessBaseRange = this.get( "wireless", "wirelessBaseRange", this.wirelessBaseRange ).getDouble( this.wirelessBaseRange );
this.wirelessBoosterRangeMultiplier = this.get( "wireless", "wirelessBoosterRangeMultiplier", this.wirelessBoosterRangeMultiplier ) this.wirelessBoosterRangeMultiplier = this.get( "wireless", "wirelessBoosterRangeMultiplier", this.wirelessBoosterRangeMultiplier ).getDouble( this.wirelessBoosterRangeMultiplier );
.getDouble(
this.wirelessBoosterRangeMultiplier );
this.wirelessBoosterExp = this.get( "wireless", "wirelessBoosterExp", this.wirelessBoosterExp ).getDouble( this.wirelessBoosterExp ); this.wirelessBoosterExp = this.get( "wireless", "wirelessBoosterExp", this.wirelessBoosterExp ).getDouble( this.wirelessBoosterExp );
this.wirelessTerminalDrainMultiplier = this.get( "wireless", "wirelessTerminalDrainMultiplier", this.wirelessTerminalDrainMultiplier ) this.wirelessTerminalDrainMultiplier = this.get( "wireless", "wirelessTerminalDrainMultiplier", this.wirelessTerminalDrainMultiplier ).getDouble( this.wirelessTerminalDrainMultiplier );
.getDouble(
this.wirelessTerminalDrainMultiplier );
this.formationPlaneEntityLimit = this.get( "automation", "formationPlaneEntityLimit", this.formationPlaneEntityLimit ) this.formationPlaneEntityLimit = this.get( "automation", "formationPlaneEntityLimit", this.formationPlaneEntityLimit ).getInt( this.formationPlaneEntityLimit );
.getInt(
this.formationPlaneEntityLimit );
this.wirelessTerminalBattery = this.get( "battery", "wirelessTerminal", this.wirelessTerminalBattery ).getInt( this.wirelessTerminalBattery ); this.wirelessTerminalBattery = this.get( "battery", "wirelessTerminal", this.wirelessTerminalBattery ).getInt( this.wirelessTerminalBattery );
this.chargedStaffBattery = this.get( "battery", "chargedStaff", this.chargedStaffBattery ).getInt( this.chargedStaffBattery ); this.chargedStaffBattery = this.get( "battery", "chargedStaff", this.chargedStaffBattery ).getInt( this.chargedStaffBattery );
@@ -213,6 +178,9 @@ public final class AEConfig extends Configuration implements IConfigurableObject
this.colorApplicatorBattery = this.get( "battery", "colorApplicator", this.colorApplicatorBattery ).getInt( this.colorApplicatorBattery ); this.colorApplicatorBattery = this.get( "battery", "colorApplicator", this.colorApplicatorBattery ).getInt( this.colorApplicatorBattery );
this.matterCannonBattery = this.get( "battery", "matterCannon", this.matterCannonBattery ).getInt( this.matterCannonBattery ); this.matterCannonBattery = this.get( "battery", "matterCannon", this.matterCannonBattery ).getInt( this.matterCannonBattery );
this.addCustomCategoryComment( "autocrafting", "Enable patterns with substitutions on to have their substitutes to be auto craftable.\nThis changes the crafting tree, and can show missing ingredients for the substitute, instead of the patterned item" );
this.enableCraftingSubstitutes = this.get( "autocrafting", "EnableAutocraftinSubstitutes", this.enableCraftingSubstitutes ).getBoolean( this.enableCraftingSubstitutes );
this.clientSync(); this.clientSync();
this.addCustomCategoryComment( "features", "Warning: Disabling a feature may disable other features depending on it." ); this.addCustomCategoryComment( "features", "Warning: Disabling a feature may disable other features depending on it." );
@@ -245,8 +213,7 @@ public final class AEConfig extends Configuration implements IConfigurableObject
try try
{ {
this.selectedPowerUnit = PowerUnits.valueOf( this.selectedPowerUnit = PowerUnits.valueOf( this.get( "Client", "PowerUnit", this.selectedPowerUnit.name(), this.getListComment( this.selectedPowerUnit ) ).getString() );
this.get( "Client", "PowerUnit", this.selectedPowerUnit.name(), this.getListComment( this.selectedPowerUnit ) ).getString() );
} }
catch( final Throwable t ) catch( final Throwable t )
{ {
@@ -262,17 +229,13 @@ public final class AEConfig extends Configuration implements IConfigurableObject
{ {
this.storageProviderID = this.get( "spatialio", "storageProviderID", this.storageProviderID ).getInt( this.storageProviderID ); this.storageProviderID = this.get( "spatialio", "storageProviderID", this.storageProviderID ).getInt( this.storageProviderID );
this.storageDimensionID = this.get( "spatialio", "storageDimensionID", this.storageDimensionID ).getInt( this.storageDimensionID ); this.storageDimensionID = this.get( "spatialio", "storageDimensionID", this.storageDimensionID ).getInt( this.storageDimensionID );
this.spatialPowerMultiplier = this.get( "spatialio", "spatialPowerMultiplier", this.spatialPowerMultiplier ) this.spatialPowerMultiplier = this.get( "spatialio", "spatialPowerMultiplier", this.spatialPowerMultiplier ).getDouble( this.spatialPowerMultiplier );
.getDouble(
this.spatialPowerMultiplier );
this.spatialPowerExponent = this.get( "spatialio", "spatialPowerExponent", this.spatialPowerExponent ).getDouble( this.spatialPowerExponent ); this.spatialPowerExponent = this.get( "spatialio", "spatialPowerExponent", this.spatialPowerExponent ).getDouble( this.spatialPowerExponent );
} }
if( this.isFeatureEnabled( AEFeature.CRAFTING_CPU ) ) if( this.isFeatureEnabled( AEFeature.CRAFTING_CPU ) )
{ {
this.craftingCalculationTimePerTick = this.get( "craftingCPU", "craftingCalculationTimePerTick", this.craftingCalculationTimePerTick ) this.craftingCalculationTimePerTick = this.get( "craftingCPU", "craftingCalculationTimePerTick", this.craftingCalculationTimePerTick ).getInt( this.craftingCalculationTimePerTick );
.getInt(
this.craftingCalculationTimePerTick );
} }
this.updatable = true; this.updatable = true;
@@ -446,8 +409,7 @@ public final class AEConfig extends Configuration implements IConfigurableObject
return true; return true;
} }
this.setCategoryComment( "OreCamouflage", this.setCategoryComment( "OreCamouflage", "AE2 Automatically uses alternative ores present in your instance of MC to blend better with its surroundings, if you prefer you can disable this selectively using these flags; Its important to note, that some if these items even if enabled may not be craftable in game because other items are overriding their recipes." );
"AE2 Automatically uses alternative ores present in your instance of MC to blend better with its surroundings, if you prefer you can disable this selectively using these flags; Its important to note, that some if these items even if enabled may not be craftable in game because other items are overriding their recipes." );
final Property p = this.get( "OreCamouflage", mt.name(), true ); final Property p = this.get( "OreCamouflage", mt.name(), true );
p.setComment( "OreDictionary Names: " + mt.getOreName() ); p.setComment( "OreDictionary Names: " + mt.getOreName() );
@@ -640,11 +602,21 @@ public final class AEConfig extends Configuration implements IConfigurableObject
return this.storageProviderID; return this.storageProviderID;
} }
void setStorageProviderID( int id )
{
this.storageProviderID = id;
}
public int getStorageDimensionID() public int getStorageDimensionID()
{ {
return this.storageDimensionID; return this.storageDimensionID;
} }
void setStorageDimensionID( int id )
{
this.storageDimensionID = id;
}
public double getSpatialPowerExponent() public double getSpatialPowerExponent()
{ {
return this.spatialPowerExponent; return this.spatialPowerExponent;
@@ -715,6 +687,11 @@ public final class AEConfig extends Configuration implements IConfigurableObject
return this.quartzOresClusterAmount; return this.quartzOresClusterAmount;
} }
public String[] getNonBlockingItems()
{
return nonBlockingItems;
}
public int getChargedChange() public int getChargedChange()
{ {
return this.chargedChange; return this.chargedChange;
@@ -775,20 +752,15 @@ public final class AEConfig extends Configuration implements IConfigurableObject
return this.wirelessBoosterExp; return this.wirelessBoosterExp;
} }
// Setters keep visibility as low as possible.
public double getWirelessHighWirelessCount() public double getWirelessHighWirelessCount()
{ {
return this.wirelessHighWirelessCount; return this.wirelessHighWirelessCount;
} }
// Setters keep visibility as low as possible. public boolean getEnableCraftingSubstitutes()
void setStorageProviderID( int id )
{ {
this.storageProviderID = id; return this.enableCraftingSubstitutes;
}
void setStorageDimensionID( int id )
{
this.storageDimensionID = id;
} }
} }
+4 -2
View File
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import appeng.helpers.NonBlockingItems;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@@ -183,8 +184,7 @@ public final class AppEng
AELog.info( "Pre Initialization ( ended after " + watch.elapsed( TimeUnit.MILLISECONDS ) + "ms )" ); AELog.info( "Pre Initialization ( ended after " + watch.elapsed( TimeUnit.MILLISECONDS ) + "ms )" );
// Instantiate all Plugins // Instantiate all Plugins
List<Object> injectables = Lists.newArrayList( List<Object> injectables = Lists.newArrayList( AEApi.instance() );
AEApi.instance() );
new PluginLoader().loadPlugins( injectables, event.getAsmData() ); new PluginLoader().loadPlugins( injectables, event.getAsmData() );
} }
@@ -239,6 +239,8 @@ public final class AppEng
AppEng.proxy.postInit(); AppEng.proxy.postInit();
AEConfig.instance().save(); AEConfig.instance().save();
NonBlockingItems.INSTANCE.init();
NetworkRegistry.INSTANCE.registerGuiHandler( this, GuiBridge.GUI_Handler ); NetworkRegistry.INSTANCE.registerGuiHandler( this, GuiBridge.GUI_Handler );
NetworkHandler.init( "AE2" ); NetworkHandler.init( "AE2" );
@@ -359,16 +359,16 @@ public final class ApiBlocks implements IBlocks
this.tinyTNT = registry.block( "tiny_tnt", BlockTinyTNT::new ) this.tinyTNT = registry.block( "tiny_tnt", BlockTinyTNT::new )
.features( AEFeature.TINY_TNT ) .features( AEFeature.TINY_TNT )
.bootstrap( ( block, item ) -> (IPreInitComponent) side -> BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject( item, .bootstrap( ( block, item ) -> (IPreInitComponent) side -> BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject( item,
new DispenserBehaviorTinyTNT() ) ) new DispenserBehaviorTinyTNT() ) )
.bootstrap( ( block, item ) -> (IEntityRegistrationComponent) r -> .bootstrap( ( block, item ) -> (IEntityRegistrationComponent) r ->
{ {
r.register( EntityEntryBuilder.create() r.register( EntityEntryBuilder.create()
.entity( EntityTinyTNTPrimed.class ) .entity( EntityTinyTNTPrimed.class )
.id( new ResourceLocation( "appliedenergistics2", EntityTinyTNTPrimed.class.getName() ), .id( new ResourceLocation( "appliedenergistics2", EntityTinyTNTPrimed.class.getName() ),
EntityIds.get( EntityTinyTNTPrimed.class ) ) EntityIds.get( EntityTinyTNTPrimed.class ) )
.name( "EntityTinyTNTPrimed" ) .name( "EntityTinyTNTPrimed" )
.tracker( 16, 4, true ) .tracker( 16, 4, true )
.build() ); .build() );
} ) } )
.build(); .build();
this.securityStation = registry.block( "security_station", BlockSecurityStation::new ) this.securityStation = registry.block( "security_station", BlockSecurityStation::new )
@@ -397,7 +397,6 @@ public final class ApiBlocks implements IBlocks
.tileEntity( new TileEntityDefinition( TileSpatialIOPort.class ) ) .tileEntity( new TileEntityDefinition( TileSpatialIOPort.class ) )
.build(); .build();
this.controller = registry.block( "controller", BlockController::new ) this.controller = registry.block( "controller", BlockController::new )
.features( AEFeature.CHANNELS )
.tileEntity( new TileEntityDefinition( TileController.class ) ) .tileEntity( new TileEntityDefinition( TileController.class ) )
.useCustomItemModel() .useCustomItemModel()
.rendering( new ControllerRendering() ) .rendering( new ControllerRendering() )
@@ -635,7 +634,7 @@ public final class ApiBlocks implements IBlocks
} ) } )
.build(); .build();
Verify.verify(stairs.maybeBlock().isPresent()); Verify.verify( stairs.maybeBlock().isPresent() );
return stairs; return stairs;
} }
@@ -70,6 +70,7 @@ public final class ApiParts implements IParts
private final IItemDefinition p2PTunnelFluids; private final IItemDefinition p2PTunnelFluids;
private final IItemDefinition p2PTunnelEU; private final IItemDefinition p2PTunnelEU;
private final IItemDefinition p2PTunnelFE; private final IItemDefinition p2PTunnelFE;
private final IItemDefinition p2PTunnelGTEU;
private final IItemDefinition p2PTunnelLight; private final IItemDefinition p2PTunnelLight;
// private final IItemDefinition p2PTunnelOpenComputers; // private final IItemDefinition p2PTunnelOpenComputers;
private final IItemDefinition cableAnchor; private final IItemDefinition cableAnchor;
@@ -79,6 +80,7 @@ public final class ApiParts implements IParts
private final IItemDefinition interfaceTerminal; private final IItemDefinition interfaceTerminal;
private final IItemDefinition patternTerminal; private final IItemDefinition patternTerminal;
private final IItemDefinition expandedProcessingPatternTerminal; private final IItemDefinition expandedProcessingPatternTerminal;
private final IItemDefinition interfaceConfigurationTerminal;
private final IItemDefinition craftingTerminal; private final IItemDefinition craftingTerminal;
private final IItemDefinition terminal; private final IItemDefinition terminal;
private final IItemDefinition storageMonitor; private final IItemDefinition storageMonitor;
@@ -91,9 +93,7 @@ public final class ApiParts implements IParts
public ApiParts( FeatureFactory registry, PartModels partModels ) public ApiParts( FeatureFactory registry, PartModels partModels )
{ {
final ItemPart itemPart = new ItemPart(); final ItemPart itemPart = new ItemPart();
registry.item( "part", () -> itemPart ) registry.item( "part", () -> itemPart ).rendering( new ItemPartRendering( partModels, itemPart ) ).build();
.rendering( new ItemPartRendering( partModels, itemPart ) )
.build();
// Register all part models // Register all part models
for( PartType partType : PartType.values() ) for( PartType partType : PartType.values() )
@@ -122,8 +122,7 @@ public final class ApiParts implements IParts
this.levelEmitter = new DamagedItemDefinition( "part.level_emitter", itemPart.createPart( PartType.LEVEL_EMITTER ) ); this.levelEmitter = new DamagedItemDefinition( "part.level_emitter", itemPart.createPart( PartType.LEVEL_EMITTER ) );
this.fluidLevelEmitter = new DamagedItemDefinition( "part.fluid_level_emitter", itemPart.createPart( PartType.FLUID_LEVEL_EMITTER ) ); this.fluidLevelEmitter = new DamagedItemDefinition( "part.fluid_level_emitter", itemPart.createPart( PartType.FLUID_LEVEL_EMITTER ) );
this.annihilationPlane = new DamagedItemDefinition( "part.plane.annihilation", itemPart.createPart( PartType.ANNIHILATION_PLANE ) ); this.annihilationPlane = new DamagedItemDefinition( "part.plane.annihilation", itemPart.createPart( PartType.ANNIHILATION_PLANE ) );
this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", itemPart this.identityAnnihilationPlane = new DamagedItemDefinition( "part.plane.annihiliation.identity", itemPart.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) );
.createPart( PartType.IDENTITY_ANNIHILATION_PLANE ) );
this.fluidAnnihilationPlane = new DamagedItemDefinition( "part.plane.fluid_annihilation", itemPart.createPart( PartType.FLUID_ANNIHILATION_PLANE ) ); this.fluidAnnihilationPlane = new DamagedItemDefinition( "part.plane.fluid_annihilation", itemPart.createPart( PartType.FLUID_ANNIHILATION_PLANE ) );
this.formationPlane = new DamagedItemDefinition( "part.plane.formation", itemPart.createPart( PartType.FORMATION_PLANE ) ); this.formationPlane = new DamagedItemDefinition( "part.plane.formation", itemPart.createPart( PartType.FORMATION_PLANE ) );
this.fluidFormationPlane = new DamagedItemDefinition( "part.plane.fluid_formation", itemPart.createPart( PartType.FLUID_FORMATION_PLANE ) ); this.fluidFormationPlane = new DamagedItemDefinition( "part.plane.fluid_formation", itemPart.createPart( PartType.FLUID_FORMATION_PLANE ) );
@@ -133,6 +132,7 @@ public final class ApiParts implements IParts
this.p2PTunnelFluids = new DamagedItemDefinition( "part.tunnel.fluid", itemPart.createPart( PartType.P2P_TUNNEL_FLUIDS ) ); this.p2PTunnelFluids = new DamagedItemDefinition( "part.tunnel.fluid", itemPart.createPart( PartType.P2P_TUNNEL_FLUIDS ) );
this.p2PTunnelEU = new DamagedItemDefinition( "part.tunnel.eu", itemPart.createPart( PartType.P2P_TUNNEL_IC2 ) ); this.p2PTunnelEU = new DamagedItemDefinition( "part.tunnel.eu", itemPart.createPart( PartType.P2P_TUNNEL_IC2 ) );
this.p2PTunnelFE = new DamagedItemDefinition( "part.tunnel.fe", itemPart.createPart( PartType.P2P_TUNNEL_FE ) ); this.p2PTunnelFE = new DamagedItemDefinition( "part.tunnel.fe", itemPart.createPart( PartType.P2P_TUNNEL_FE ) );
this.p2PTunnelGTEU = new DamagedItemDefinition( "part.tunnel.gteu", itemPart.createPart( PartType.P2P_TUNNEL_GTEU ) );
this.p2PTunnelLight = new DamagedItemDefinition( "part.tunnel.light", itemPart.createPart( PartType.P2P_TUNNEL_LIGHT ) ); this.p2PTunnelLight = new DamagedItemDefinition( "part.tunnel.light", itemPart.createPart( PartType.P2P_TUNNEL_LIGHT ) );
// this.p2PTunnelOpenComputers = new DamagedItemDefinition( itemMultiPart.createPart( // this.p2PTunnelOpenComputers = new DamagedItemDefinition( itemMultiPart.createPart(
// PartType.P2PTunnelOpenComputers ) ); // PartType.P2PTunnelOpenComputers ) );
@@ -143,6 +143,7 @@ public final class ApiParts implements IParts
this.interfaceTerminal = new DamagedItemDefinition( "part.terminal.interface", itemPart.createPart( PartType.INTERFACE_TERMINAL ) ); this.interfaceTerminal = new DamagedItemDefinition( "part.terminal.interface", itemPart.createPart( PartType.INTERFACE_TERMINAL ) );
this.patternTerminal = new DamagedItemDefinition( "part.terminal.pattern", itemPart.createPart( PartType.PATTERN_TERMINAL ) ); this.patternTerminal = new DamagedItemDefinition( "part.terminal.pattern", itemPart.createPart( PartType.PATTERN_TERMINAL ) );
this.expandedProcessingPatternTerminal = new DamagedItemDefinition( "part.terminal.expanded_processing_pattern", itemPart.createPart( PartType.EXPANDED_PROCESSING_PATTERN_TERMINAL ) ); this.expandedProcessingPatternTerminal = new DamagedItemDefinition( "part.terminal.expanded_processing_pattern", itemPart.createPart( PartType.EXPANDED_PROCESSING_PATTERN_TERMINAL ) );
this.interfaceConfigurationTerminal = new DamagedItemDefinition( "part.terminal.interface_configuration_terminal", itemPart.createPart( PartType.INTERFACE_CONFIGURATION_TERMINAL ) );
this.craftingTerminal = new DamagedItemDefinition( "part.terminal.crafting", itemPart.createPart( PartType.CRAFTING_TERMINAL ) ); this.craftingTerminal = new DamagedItemDefinition( "part.terminal.crafting", itemPart.createPart( PartType.CRAFTING_TERMINAL ) );
this.terminal = new DamagedItemDefinition( "part.terminal", itemPart.createPart( PartType.TERMINAL ) ); this.terminal = new DamagedItemDefinition( "part.terminal", itemPart.createPart( PartType.TERMINAL ) );
this.storageMonitor = new DamagedItemDefinition( "part.monitor.storage", itemPart.createPart( PartType.STORAGE_MONITOR ) ); this.storageMonitor = new DamagedItemDefinition( "part.monitor.storage", itemPart.createPart( PartType.STORAGE_MONITOR ) );
@@ -339,6 +340,11 @@ public final class ApiParts implements IParts
return this.p2PTunnelFE; return this.p2PTunnelFE;
} }
public IItemDefinition p2PTunnelGTEU()
{
return this.p2PTunnelGTEU;
}
@Override @Override
public IItemDefinition p2PTunnelLight() public IItemDefinition p2PTunnelLight()
{ {
@@ -25,13 +25,13 @@ public enum AEFeature
// is just flat out required by tons of // is just flat out required by tons of
// important stuff. // important stuff.
CORE( "Core", null ) CORE( "Core", null )
{ {
@Override @Override
public boolean isVisible() public boolean isVisible()
{ {
return false; return false;
} }
}, },
CERTUS_QUARTZ_WORLD_GEN( "CertusQuartzWorldGen", Constants.CATEGORY_WORLD ), CERTUS_QUARTZ_WORLD_GEN( "CertusQuartzWorldGen", Constants.CATEGORY_WORLD ),
METEORITE_WORLD_GEN( "MeteoriteWorldGen", Constants.CATEGORY_WORLD ), METEORITE_WORLD_GEN( "MeteoriteWorldGen", Constants.CATEGORY_WORLD ),
@@ -126,6 +126,7 @@ public enum AEFeature
P2P_TUNNEL_REDSTONE( "P2PTunnelRedstone", Constants.CATEGORY_P2P_TUNNELS ), P2P_TUNNEL_REDSTONE( "P2PTunnelRedstone", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_EU( "P2PTunnelEU", Constants.CATEGORY_P2P_TUNNELS ), P2P_TUNNEL_EU( "P2PTunnelEU", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_FE( "P2PTunnelFE", Constants.CATEGORY_P2P_TUNNELS ), P2P_TUNNEL_FE( "P2PTunnelFE", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_GTEU( "P2PTunnelGTEU", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_FLUIDS( "P2PTunnelFluids", Constants.CATEGORY_P2P_TUNNELS ), P2P_TUNNEL_FLUIDS( "P2PTunnelFluids", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_LIGHT( "P2PTunnelLight", Constants.CATEGORY_P2P_TUNNELS ), P2P_TUNNEL_LIGHT( "P2PTunnelLight", Constants.CATEGORY_P2P_TUNNELS ),
P2P_TUNNEL_OPEN_COMPUTERS( "P2PTunnelOpenComputers", Constants.CATEGORY_P2P_TUNNELS ), P2P_TUNNEL_OPEN_COMPUTERS( "P2PTunnelOpenComputers", Constants.CATEGORY_P2P_TUNNELS ),
@@ -163,7 +164,6 @@ public enum AEFeature
MOLECULAR_ASSEMBLER( "MolecularAssembler", Constants.CATEGORY_CRAFTING_FEATURES ), MOLECULAR_ASSEMBLER( "MolecularAssembler", Constants.CATEGORY_CRAFTING_FEATURES ),
PATTERNS( "Patterns", Constants.CATEGORY_CRAFTING_FEATURES ), PATTERNS( "Patterns", Constants.CATEGORY_CRAFTING_FEATURES ),
CRAFTING_CPU( "CraftingCPU", Constants.CATEGORY_CRAFTING_FEATURES ), CRAFTING_CPU( "CraftingCPU", Constants.CATEGORY_CRAFTING_FEATURES ),
CRAFTING_MANAGER_FALLBACK( "CraftingManagerFallback", Constants.CATEGORY_CRAFTING_FEATURES, "Use CraftingManager to find an alternative recipe, after a pattern rejected an ingredient. Should be enabled to avoid issues, but can have a minor performance impact." ),
BASIC_CARDS( "BasicCards", Constants.CATEGORY_UPGRADES ), BASIC_CARDS( "BasicCards", Constants.CATEGORY_UPGRADES ),
ADVANCED_CARDS( "AdvancedCards", Constants.CATEGORY_UPGRADES ), ADVANCED_CARDS( "AdvancedCards", Constants.CATEGORY_UPGRADES ),
@@ -19,13 +19,14 @@
package appeng.core.features.registries; package appeng.core.features.registries;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import appeng.core.AELog;
import appeng.util.item.OreHelper;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.item.Item; import net.minecraft.item.Item;
@@ -67,6 +68,25 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
this.addNewAttunement( new ItemStack( Blocks.TORCH ), TunnelType.LIGHT ); this.addNewAttunement( new ItemStack( Blocks.TORCH ), TunnelType.LIGHT );
this.addNewAttunement( new ItemStack( Blocks.GLOWSTONE ), TunnelType.LIGHT ); this.addNewAttunement( new ItemStack( Blocks.GLOWSTONE ), TunnelType.LIGHT );
List<String> gtceOreDict = new ArrayList<>();
gtceOreDict.add( "wireGtHex" );
gtceOreDict.add( "wireGtOctal" );
gtceOreDict.add( "wireGtQuadruple" );
gtceOreDict.add( "wireGtDouble" );
gtceOreDict.add( "wireGtSingle" );
gtceOreDict.add( "cableGtHex" );
gtceOreDict.add( "cableGtOctal" );
gtceOreDict.add( "cableGtQuadruple" );
gtceOreDict.add( "cableGtDouble" );
gtceOreDict.add( "cableGtSingle" );
for( String oreDict : gtceOreDict )
{
Arrays.stream( OreDictionary.getOreNames() ).filter( oreName -> oreName.startsWith( oreDict ) ).forEach( oreName -> {
OreHelper.INSTANCE.getCachedOres( oreName ).forEach( stack -> this.addNewAttunement( stack, TunnelType.GTEU_POWER ) );
} );
}
/** /**
* Forge energy tunnel items * Forge energy tunnel items
*/ */
@@ -127,12 +147,12 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
this.addNewAttunement( this.getModItem( "enderio", "itemitemconduit", OreDictionary.WILDCARD_VALUE ), TunnelType.ITEM ); this.addNewAttunement( this.getModItem( "enderio", "itemitemconduit", OreDictionary.WILDCARD_VALUE ), TunnelType.ITEM );
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 0 ), TunnelType.ITEM ); // itemduct this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 0 ), TunnelType.ITEM ); // itemduct
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 1 ), TunnelType.ITEM ); // itemduct this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 1 ), TunnelType.ITEM ); // itemduct
// (opaque) // (opaque)
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 2 ), TunnelType.ITEM ); // impulse this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 2 ), TunnelType.ITEM ); // impulse
// itemduct // itemduct
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 3 ), TunnelType.ITEM ); // impulse this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_32", 3 ), TunnelType.ITEM ); // impulse
// itemduct // itemduct
// (opaque) // (opaque)
/** /**
* attune based on lots of random item related stuff * attune based on lots of random item related stuff
@@ -148,12 +168,12 @@ public final class P2PTunnelRegistry implements IP2PTunnelRegistry
this.addNewAttunement( this.getModItem( "enderio", "itemliquidconduit", OreDictionary.WILDCARD_VALUE ), TunnelType.FLUID ); this.addNewAttunement( this.getModItem( "enderio", "itemliquidconduit", OreDictionary.WILDCARD_VALUE ), TunnelType.FLUID );
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 0 ), TunnelType.FLUID ); // fluiduct this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 0 ), TunnelType.FLUID ); // fluiduct
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 1 ), TunnelType.FLUID ); // fluiduct this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 1 ), TunnelType.FLUID ); // fluiduct
// (opaque) // (opaque)
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 2 ), TunnelType.FLUID ); // fluiduct this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 2 ), TunnelType.FLUID ); // fluiduct
// hardened // hardened
this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 3 ), TunnelType.FLUID ); // fluiduct this.addNewAttunement( this.getModItem( "thermaldynamics", "duct_16", 3 ), TunnelType.FLUID ); // fluiduct
// hardened // hardened
// (opaque) // (opaque)
for( final AEColor c : AEColor.values() ) for( final AEColor c : AEColor.values() )
{ {
@@ -99,6 +99,7 @@ public enum GuiText
OCTunnel, OCTunnel,
LightTunnel, LightTunnel,
FETunnel, FETunnel,
GTEUTunnel,
PressureTunnel, PressureTunnel,
// spatial // spatial
@@ -171,6 +172,7 @@ public enum GuiText
Missing, Missing,
InterfaceTerminal, InterfaceTerminal,
InterfaceConfigurationTerminal,
NoCraftingCPUs, NoCraftingCPUs,
Clean, Clean,
InvalidPattern, InvalidPattern,
@@ -24,34 +24,9 @@ import java.lang.reflect.InvocationTargetException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import appeng.core.sync.packets.*;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import appeng.core.sync.packets.PacketAssemblerAnimation;
import appeng.core.sync.packets.PacketClick;
import appeng.core.sync.packets.PacketCompassRequest;
import appeng.core.sync.packets.PacketCompassResponse;
import appeng.core.sync.packets.PacketCompressedNBT;
import appeng.core.sync.packets.PacketConfigButton;
import appeng.core.sync.packets.PacketCraftRequest;
import appeng.core.sync.packets.PacketFluidSlot;
import appeng.core.sync.packets.PacketInventoryAction;
import appeng.core.sync.packets.PacketJEIRecipe;
import appeng.core.sync.packets.PacketLightning;
import appeng.core.sync.packets.PacketMEFluidInventoryUpdate;
import appeng.core.sync.packets.PacketMEInventoryUpdate;
import appeng.core.sync.packets.PacketMatterCannon;
import appeng.core.sync.packets.PacketMockExplosion;
import appeng.core.sync.packets.PacketPaintedEntity;
import appeng.core.sync.packets.PacketPartPlacement;
import appeng.core.sync.packets.PacketPatternSlot;
import appeng.core.sync.packets.PacketProgressBar;
import appeng.core.sync.packets.PacketSwapSlots;
import appeng.core.sync.packets.PacketSwitchGuis;
import appeng.core.sync.packets.PacketTargetFluidStack;
import appeng.core.sync.packets.PacketTargetItemStack;
import appeng.core.sync.packets.PacketTransitionEffect;
import appeng.core.sync.packets.PacketValueConfig;
public class AppEngPacketHandlerBase public class AppEngPacketHandlerBase
{ {
@@ -107,7 +82,10 @@ public class AppEngPacketHandlerBase
PACKET_PAINTED_ENTITY( PacketPaintedEntity.class ), PACKET_PAINTED_ENTITY( PacketPaintedEntity.class ),
PACKET_FLUID_TANK( PacketFluidSlot.class ); PACKET_FLUID_TANK( PacketFluidSlot.class ),
PACKET_INFORM_PLAYER( PacketInformPlayer.class );
private final Class<? extends AppEngPacket> packetClass; private final Class<? extends AppEngPacket> packetClass;
private final Constructor<? extends AppEngPacket> packetConstructor; private final Constructor<? extends AppEngPacket> packetConstructor;
@@ -23,7 +23,7 @@ import java.lang.reflect.Constructor;
import appeng.container.implementations.*; import appeng.container.implementations.*;
import appeng.parts.misc.PartOreDicStorageBus; import appeng.parts.misc.PartOreDicStorageBus;
import appeng.parts.reporting.PartExpandedProcessingPatternTerminal; import appeng.parts.reporting.*;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -74,9 +74,6 @@ import appeng.items.contents.QuartzKnifeObj;
import appeng.parts.automation.PartFormationPlane; import appeng.parts.automation.PartFormationPlane;
import appeng.parts.automation.PartLevelEmitter; import appeng.parts.automation.PartLevelEmitter;
import appeng.parts.misc.PartStorageBus; import appeng.parts.misc.PartStorageBus;
import appeng.parts.reporting.PartCraftingTerminal;
import appeng.parts.reporting.PartInterfaceTerminal;
import appeng.parts.reporting.PartPatternTerminal;
import appeng.tile.crafting.TileCraftingTile; import appeng.tile.crafting.TileCraftingTile;
import appeng.tile.crafting.TileMolecularAssembler; import appeng.tile.crafting.TileMolecularAssembler;
import appeng.tile.grindstone.TileGrinder; import appeng.tile.grindstone.TileGrinder;
@@ -141,7 +138,7 @@ public enum GuiBridge implements IGuiHandler
GUI_STORAGEBUS( ContainerStorageBus.class, PartStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), GUI_STORAGEBUS( ContainerStorageBus.class, PartStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_OREDICTSTORAGEBUS( ContainerPartOreDictStorageBus.class, PartOreDicStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), GUI_OREDICTSTORAGEBUS( ContainerOreDictStorageBus.class, PartOreDicStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_STORAGEBUS_FLUID( ContainerFluidStorageBus.class, PartFluidStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), GUI_STORAGEBUS_FLUID( ContainerFluidStorageBus.class, PartFluidStorageBus.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
@@ -180,7 +177,9 @@ public enum GuiBridge implements IGuiHandler
GUI_INTERFACE_TERMINAL( ContainerInterfaceTerminal.class, PartInterfaceTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD ), GUI_INTERFACE_TERMINAL( ContainerInterfaceTerminal.class, PartInterfaceTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD ),
GUI_CRAFTING_STATUS( ContainerCraftingStatus.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD, SecurityPermissions.CRAFT ); GUI_CRAFTING_STATUS( ContainerCraftingStatus.class, ITerminalHost.class, GuiHostType.ITEM_OR_WORLD, SecurityPermissions.CRAFT ),
GUI_INTERFACE_CONFIGURATION_TERMINAL( ContainerInterfaceConfigurationTerminal.class, PartInterfaceConfigurationTerminal.class, GuiHostType.WORLD, SecurityPermissions.BUILD );
private final Class tileClass; private final Class tileClass;
private final Class containerClass; private final Class containerClass;
@@ -343,7 +342,7 @@ public enum GuiBridge implements IGuiHandler
if( target == null ) if( target == null )
{ {
throw new IllegalStateException( "Cannot find " + this.containerClass.getName() + "( " + this.typeName( inventory ) + ", " + this throw new IllegalStateException( "Cannot find " + this.containerClass.getName() + "( " + this.typeName( inventory ) + ", " + this
.typeName( tE ) + " )" ); .typeName( tE ) + " )" );
} }
return target.newInstance( inventory, tE ); return target.newInstance( inventory, tE );
@@ -441,7 +440,7 @@ public enum GuiBridge implements IGuiHandler
if( target == null ) if( target == null )
{ {
throw new IllegalStateException( "Cannot find " + this.containerClass.getName() + "( " + this.typeName( inventory ) + ", " + this throw new IllegalStateException( "Cannot find " + this.containerClass.getName() + "( " + this.typeName( inventory ) + ", " + this
.typeName( tE ) + " )" ); .typeName( tE ) + " )" );
} }
return target.newInstance( inventory, tE ); return target.newInstance( inventory, tE );
@@ -27,6 +27,7 @@ import java.io.OutputStream;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
import appeng.client.gui.implementations.GuiInterfaceConfigurationTerminal;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@@ -113,5 +114,9 @@ public class PacketCompressedNBT extends AppEngPacket
{ {
( (GuiInterfaceTerminal) gs ).postUpdate( this.in ); ( (GuiInterfaceTerminal) gs ).postUpdate( this.in );
} }
else if( gs instanceof GuiInterfaceConfigurationTerminal )
{
( (GuiInterfaceConfigurationTerminal) gs ).postUpdate( this.in );
}
} }
} }
@@ -0,0 +1,76 @@
package appeng.core.sync.packets;
import appeng.api.storage.data.IAEItemStack;
import appeng.core.AppEng;
import appeng.core.sync.AppEngPacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.util.item.AEItemStack;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.text.TextComponentString;
import java.io.IOException;
public class PacketInformPlayer extends AppEngPacket
{
private IAEItemStack actualItem = null;
private IAEItemStack reportedItem = null;
private final InfoType type;
public PacketInformPlayer( ByteBuf stream ) throws IOException
{
this.type = InfoType.values()[stream.readInt()];
switch ( type )
{
case PARTIAL_ITEM_EXTRACTION:
this.reportedItem = AEItemStack.fromPacket( stream );
this.actualItem = AEItemStack.fromPacket( stream );
break;
case NO_ITEMS_EXTRACTED:
this.reportedItem = AEItemStack.fromPacket( stream );
break;
}
}
public PacketInformPlayer( IAEItemStack expected, IAEItemStack actual, InfoType type ) throws IOException
{
this.reportedItem = expected;
this.actualItem = actual;
this.type = type;
final ByteBuf data = Unpooled.buffer();
data.writeInt( this.getPacketID() );
data.writeInt( type.ordinal() );
reportedItem.writeToPacket( data );
if( actualItem != null )
{
actualItem.writeToPacket( data );
}
this.configureWrite( data );
}
@Override
public void clientPacketData( final INetworkInfo network, final AppEngPacket packet, final EntityPlayer player )
{
TextComponentString msg = null;
if( this.type == InfoType.PARTIAL_ITEM_EXTRACTION )
{
AppEng.proxy.getPlayers().get( 0 ).sendStatusMessage( new TextComponentString( "System reported " + reportedItem.getStackSize() + " " + reportedItem.getItem().getItemStackDisplayName( reportedItem.getDefinition() ) + " available but could only extract" + actualItem.getStackSize() ), false );
}
else if( this.type == InfoType.NO_ITEMS_EXTRACTED )
{
AppEng.proxy.getPlayers().get( 0 ).sendStatusMessage( new TextComponentString( "System reported " + reportedItem.getStackSize() + " " + reportedItem.getItem().getItemStackDisplayName( reportedItem.getDefinition() ) + " available but could not extract anything" ), false );
}
}
public enum InfoType
{
PARTIAL_ITEM_EXTRACTION, NO_ITEMS_EXTRACTED
}
}
@@ -23,6 +23,9 @@ import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
import appeng.client.me.SlotDisconnected;
import appeng.container.implementations.ContainerInterfaceConfigurationTerminal;
import appeng.container.implementations.ContainerInterfaceConfigurationTerminal.ConfigTracker;
import appeng.container.slot.IJEITargetSlot; import appeng.container.slot.IJEITargetSlot;
import appeng.container.slot.SlotFake; import appeng.container.slot.SlotFake;
import appeng.core.AELog; import appeng.core.AELog;
@@ -30,11 +33,14 @@ import appeng.core.sync.network.NetworkHandler;
import appeng.fluids.client.gui.widgets.GuiFluidSlot; import appeng.fluids.client.gui.widgets.GuiFluidSlot;
import appeng.fluids.container.ContainerFluidConfigurable; import appeng.fluids.container.ContainerFluidConfigurable;
import appeng.fluids.util.AEFluidStack; import appeng.fluids.util.AEFluidStack;
import appeng.util.helpers.ItemHandlerUtil;
import appeng.util.inv.WrapperRangeItemHandler;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@@ -50,6 +56,7 @@ import appeng.helpers.InventoryAction;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.items.IItemHandler;
public class PacketInventoryAction extends AppEngPacket public class PacketInventoryAction extends AppEngPacket
@@ -111,14 +118,25 @@ public class PacketInventoryAction extends AppEngPacket
this.configureWrite( data ); this.configureWrite( data );
} }
public PacketInventoryAction(final InventoryAction action, final IJEITargetSlot slot, final IAEItemStack slotItem ) throws IOException public PacketInventoryAction( final InventoryAction action, final IJEITargetSlot slot, final IAEItemStack slotItem ) throws IOException
{ {
this.action = action; this.action = action;
if (slot instanceof SlotFake) if( slot instanceof SlotFake )
this.slot = ((SlotFake) slot).slotNumber; {
else this.slot = ((GuiFluidSlot) slot).getId(); this.slot = ( (SlotFake) slot ).slotNumber;
this.id = 0; this.id = 0;
}
else if( slot instanceof SlotDisconnected )
{
this.slot = ( (SlotDisconnected) slot ).getSlotIndex();
this.id = ( (SlotDisconnected) slot ).getSlot().getId();
}
else
{
this.slot = ( (GuiFluidSlot) slot ).getId();
this.id = 0;
}
this.slotItem = slotItem; this.slotItem = slotItem;
final ByteBuf data = Unpooled.buffer(); final ByteBuf data = Unpooled.buffer();
@@ -205,29 +223,44 @@ public class PacketInventoryAction extends AppEngPacket
} }
} }
} }
else if( this.slot < sender.openContainer.inventorySlots.size() && sender.openContainer.inventorySlots.get( this.slot ) instanceof SlotFake ) else if( sender.openContainer instanceof ContainerInterfaceConfigurationTerminal )
{ {
if( this.slotItem != null ) ConfigTracker inv = ( (ContainerInterfaceConfigurationTerminal) sender.openContainer ).getSlotByID( this.id );
final IItemHandler theSlot = new WrapperRangeItemHandler( inv.getServer(), 0, slot + 1 );
ItemHandlerUtil.setStackInSlot( theSlot, this.slot, this.slotItem.createItemStack() );
}
else if( this.slot < sender.openContainer.inventorySlots.size() )
{
Slot senderSlot = sender.openContainer.inventorySlots.get( this.slot );
if( senderSlot instanceof SlotFake )
{ {
sender.openContainer.inventorySlots.get( this.slot ).putStack( this.slotItem.createItemStack() ); if( this.slotItem != null )
if( sender.openContainer.inventorySlots.get( this.slot ).getStack().isEmpty() )
{ {
IAEFluidStack aefs = AEFluidStack.fromNBT( this.slotItem.getDefinition().getTagCompound() ); senderSlot.putStack( this.slotItem.createItemStack() );
if( aefs != null ) if( senderSlot.getStack().isEmpty() )
{ {
FluidStack fluid = aefs.getFluidStack(); IAEFluidStack aefs = AEFluidStack.fromNBT( this.slotItem.getDefinition().getTagCompound() );
sender.openContainer.inventorySlots.get( this.slot ).putStack( AEFluidStack.fromFluidStack( fluid ).asItemStackRepresentation() ); if( aefs != null )
{
FluidStack fluid = aefs.getFluidStack();
senderSlot.putStack( AEFluidStack.fromFluidStack( fluid ).asItemStackRepresentation() );
}
} }
} }
} else
else sender.openContainer.inventorySlots.get( this.slot ).putStack( ItemStack.EMPTY ); {
try senderSlot.putStack( ItemStack.EMPTY );
{ }
NetworkHandler.instance().sendTo( new PacketInventoryAction( InventoryAction.UPDATE_HAND, 0, AEItemStack.fromItemStack( ItemStack.EMPTY ) ), sender ); try
} {
catch( final IOException e ) NetworkHandler.instance().sendTo( new PacketInventoryAction( InventoryAction.UPDATE_HAND, 0, AEItemStack.fromItemStack( ItemStack.EMPTY ) ), sender );
{ }
AELog.debug( e ); catch( final IOException e )
{
AELog.debug( e );
}
} }
} }
} }
@@ -30,7 +30,6 @@ import java.util.List;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.container.implementations.ContainerExpandedProcessingPatternTerm; import appeng.container.implementations.ContainerExpandedProcessingPatternTerm;
import appeng.container.implementations.ContainerPatternTerm; import appeng.container.implementations.ContainerPatternTerm;
import gregtech.common.items.MetaTool;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@@ -41,6 +40,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.fml.common.Optional;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import appeng.api.AEApi; import appeng.api.AEApi;
@@ -175,7 +175,8 @@ public class PacketJEIRecipe extends AppEngPacket
{ {
ItemStack currentItem = craftMatrix.getStackInSlot( x ); ItemStack currentItem = craftMatrix.getStackInSlot( x );
if (x >= this.recipe.size()) { if( x >= this.recipe.size() )
{
currentItem = ItemStack.EMPTY; currentItem = ItemStack.EMPTY;
} }
@@ -228,7 +229,7 @@ public class PacketJEIRecipe extends AppEngPacket
out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() ); out = Platform.poweredExtraction( energy, storage, request, cct.getActionSource() );
if( out == null ) if( out == null )
{ {
if( request.getItem().isDamageable() || ( Platform.isModLoaded( "gregtech" ) && request.getItem() instanceof MetaTool ) ) if( request.getItem().isDamageable() || Platform.isGTDamageableItem( request.getItem() ) )
{ {
Collection<IAEItemStack> outList = inv.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findFuzzy( request, FuzzyMode.IGNORE_ALL ); Collection<IAEItemStack> outList = inv.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findFuzzy( request, FuzzyMode.IGNORE_ALL );
for( IAEItemStack is : outList ) for( IAEItemStack is : outList )
@@ -261,7 +262,7 @@ public class PacketJEIRecipe extends AppEngPacket
if( out != null ) if( out != null )
{ {
if (!cct.useRealItems()) if( !cct.useRealItems() )
{ {
out.setStackSize( recipe.get( x )[y].getCount() ); out.setStackSize( recipe.get( x )[y].getCount() );
} }
@@ -285,7 +286,7 @@ public class PacketJEIRecipe extends AppEngPacket
} }
} }
} }
if (!cct.useRealItems()) if( !cct.useRealItems() )
{ {
if( currentItem.isEmpty() && recipe.size() > x && this.recipe.get( x ) != null ) if( currentItem.isEmpty() && recipe.size() > x && this.recipe.get( x ) != null )
{ {
@@ -301,24 +302,25 @@ public class PacketJEIRecipe extends AppEngPacket
if( this.output != null && ( ( con instanceof ContainerPatternTerm && !( (ContainerPatternTerm) con ).isCraftingMode() ) || con instanceof ContainerExpandedProcessingPatternTerm ) ) if( this.output != null && ( ( con instanceof ContainerPatternTerm && !( (ContainerPatternTerm) con ).isCraftingMode() ) || con instanceof ContainerExpandedProcessingPatternTerm ) )
{ {
IItemHandler outputSlots = cct.getInventoryByName( "output" ); IItemHandler outputSlots = cct.getInventoryByName( "output" );
for( int i = 0; i < outputSlots.getSlots(); ++i )
for( int i = 0; i < this.output.size(); ++i )
{ {
if( this.output.get( i ) == null ) ItemHandlerUtil.setStackInSlot( outputSlots, i, ItemStack.EMPTY );
}
for( int i = 0; i < this.output.size() && i < outputSlots.getSlots(); ++i )
{
if( this.output.get( i ) == null || this.output.get( i ) == ItemStack.EMPTY )
{ {
continue; continue;
} }
ItemHandlerUtil.setStackInSlot( outputSlots, i, this.output.get( i ) ); ItemHandlerUtil.setStackInSlot( outputSlots, i, this.output.get( i ) );
} }
} }
} }
} }
/** /**
*
* @param slot * @param slot
* @param is itemstack * @param is itemstack
* @return is if it can be used, else EMPTY * @return is if it can be used, else EMPTY
*/ */
private ItemStack canUseInSlot( int slot, ItemStack is ) private ItemStack canUseInSlot( int slot, ItemStack is )
@@ -24,7 +24,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import appeng.client.gui.implementations.GuiPartOreDictStorageBus; import appeng.client.gui.implementations.GuiOreDictStorageBus;
import appeng.container.implementations.*; import appeng.container.implementations.*;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@@ -276,9 +276,10 @@ public class PacketValueConfig extends AppEngPacket
{ {
( (ContainerFluidStorageBus) c ).partition(); ( (ContainerFluidStorageBus) c ).partition();
} }
else if( c instanceof ContainerPartOreDictStorageBus ) else if( c instanceof ContainerOreDictStorageBus )
{ {
( (ContainerPartOreDictStorageBus) c ).partition(); ( (ContainerOreDictStorageBus) c ).partition();
( (ContainerOreDictStorageBus) c ).sendRegex();
} }
} }
else if( this.Value.equals( "Clear" ) ) else if( this.Value.equals( "Clear" ) )
@@ -296,15 +297,15 @@ public class PacketValueConfig extends AppEngPacket
} }
else if( this.Name.startsWith( "OreDictStorageBus" ) ) else if( this.Name.startsWith( "OreDictStorageBus" ) )
{ {
if( c instanceof ContainerPartOreDictStorageBus ) if( c instanceof ContainerOreDictStorageBus )
{ {
if( this.Name.equals( "OreDictStorageBus.save" ) ) if( this.Name.equals( "OreDictStorageBus.save" ) )
{ {
( (ContainerPartOreDictStorageBus) c ).saveOreMatch( this.Value ); ( (ContainerOreDictStorageBus) c ).saveOreMatch( this.Value );
} }
if( this.Name.equals( "OreDictStorageBus.getRegex" ) ) if( this.Name.equals( "OreDictStorageBus.getRegex" ) )
{ {
( (ContainerPartOreDictStorageBus) c ).sendRegex(); ( (ContainerOreDictStorageBus) c ).sendRegex();
} }
} }
} }
@@ -387,9 +388,9 @@ public class PacketValueConfig extends AppEngPacket
else if( this.Name.equals( "OreDictStorageBus.sendRegex" ) ) else if( this.Name.equals( "OreDictStorageBus.sendRegex" ) )
{ {
final GuiScreen gs = Minecraft.getMinecraft().currentScreen; final GuiScreen gs = Minecraft.getMinecraft().currentScreen;
if( gs instanceof GuiPartOreDictStorageBus ) if( gs instanceof GuiOreDictStorageBus )
{ {
( (GuiPartOreDictStorageBus) gs ).fillRegex( this.Value ); ( (GuiOreDictStorageBus) gs ).fillRegex( this.Value );
} }
} }
else if( c instanceof IConfigurableObject ) else if( c instanceof IConfigurableObject )
+64 -49
View File
@@ -19,15 +19,6 @@
package appeng.crafting; package appeng.crafting;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Stopwatch;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.networking.IGrid; import appeng.api.networking.IGrid;
@@ -46,20 +37,30 @@ import appeng.api.storage.data.IItemList;
import appeng.api.util.DimensionalCoord; import appeng.api.util.DimensionalCoord;
import appeng.core.AELog; import appeng.core.AELog;
import appeng.hooks.TickHandler; import appeng.hooks.TickHandler;
import appeng.me.cache.GridStorageCache;
import com.google.common.base.Stopwatch;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
public class CraftingJob implements Runnable, ICraftingJob public class CraftingJob implements Runnable, ICraftingJob
{ {
private static final String LOG_CRAFTING_JOB = "CraftingJob (%s) issued by %s requesting [%s] using %s bytes took %s ms"; private static final String LOG_CRAFTING_JOB = "CraftingJob (%s) issued by %s requesting [%s] using %s bytes took %s us";
private static final String LOG_MACHINE_SOURCE_DETAILS = "Machine[object=%s, %s]"; private static final String LOG_MACHINE_SOURCE_DETAILS = "Machine[object=%s, %s]";
private final MECraftingInventory original; private final MECraftingInventory original;
private final World world; private final World world;
private final IItemList<IAEItemStack> crafting = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private final IItemList<IAEItemStack> crafting = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private final IItemList<IAEItemStack> missing = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final HashMap<String, TwoIntegers> opsAndMultiplier = new HashMap<>(); private final HashMap<String, TwoIntegers> opsAndMultiplier = new HashMap<>();
private final Object monitor = new Object(); private final Object monitor = new Object();
private final Stopwatch watch = Stopwatch.createUnstarted(); private final Stopwatch tickSpreadingWatch = Stopwatch.createUnstarted();
private final Stopwatch craftingTreeWatch = Stopwatch.createUnstarted();
private final ICraftingGrid cc;
private CraftingTreeNode tree; private CraftingTreeNode tree;
private final IAEItemStack output; private final IAEItemStack output;
private boolean simulate = false; private boolean simulate = false;
@@ -84,10 +85,10 @@ public class CraftingJob implements Runnable, ICraftingJob
this.actionSrc = actionSrc; this.actionSrc = actionSrc;
this.callback = callback; this.callback = callback;
final ICraftingGrid cc = grid.getCache( ICraftingGrid.class );
final IStorageGrid sg = grid.getCache( IStorageGrid.class ); this.cc = grid.getCache( ICraftingGrid.class );
this.original = new MECraftingInventory( sg final GridStorageCache sg = grid.getCache( IStorageGrid.class );
.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), actionSrc, false, false, false ); this.original = sg.getExtractableList( actionSrc );
this.setTree( this.getCraftingTree( cc, what ) ); this.setTree( this.getCraftingTree( cc, what ) );
this.availableCheck = null; this.availableCheck = null;
@@ -108,9 +109,9 @@ public class CraftingJob implements Runnable, ICraftingJob
return this.availableCheck.extractItems( available, Actionable.MODULATE, this.actionSrc ); return this.availableCheck.extractItems( available, Actionable.MODULATE, this.actionSrc );
} }
public void writeToNBT( final NBTTagCompound out ) IAEItemStack checkAvailable( final IAEItemStack available )
{ {
return this.availableCheck.extractItems( available, Actionable.SIMULATE, this.actionSrc );
} }
void addTask( IAEItemStack what, final long crafts, final ICraftingPatternDetails details, final int depth ) void addTask( IAEItemStack what, final long crafts, final ICraftingPatternDetails details, final int depth )
@@ -139,13 +140,13 @@ public class CraftingJob implements Runnable, ICraftingJob
TickHandler.INSTANCE.registerCraftingSimulation( this.world, this ); TickHandler.INSTANCE.registerCraftingSimulation( this.world, this );
this.handlePausing(); this.handlePausing();
final Stopwatch timer = Stopwatch.createStarted();
final MECraftingInventory craftingInventory = new MECraftingInventory( this.original, true, false, true ); final MECraftingInventory craftingInventory = new MECraftingInventory( this.original, true, false, true );
craftingInventory.ignore( this.output ); craftingInventory.ignore( this.output );
this.availableCheck = new MECraftingInventory( this.original, false, false, false ); this.availableCheck = new MECraftingInventory( this.original, false, false, false );
craftingTreeWatch.start();
this.getTree().request( craftingInventory, this.output.getStackSize(), this.actionSrc ); this.getTree().request( craftingInventory, this.output.getStackSize(), this.actionSrc );
craftingTreeWatch.stop();
this.getTree().dive( this ); this.getTree().dive( this );
for( final String s : this.opsAndMultiplier.keySet() ) for( final String s : this.opsAndMultiplier.keySet() )
@@ -154,9 +155,14 @@ public class CraftingJob implements Runnable, ICraftingJob
AELog.crafting( s + " * " + ti.times + " = " + ( ti.perOp * ti.times ) ); AELog.crafting( s + " * " + ti.times + " = " + ( ti.perOp * ti.times ) );
} }
this.logCraftingJob( "real", timer ); if( actionSrc.player().isPresent() )
// if ( mode == Actionable.MODULATE ) {
// craftingInventory.moveItemsToStorage( storage ); this.logCraftingJob( "simulated, success", craftingTreeWatch );
}
else
{
this.logCraftingJob( "real, success", craftingTreeWatch );
}
} }
catch( final CraftBranchFailure e ) catch( final CraftBranchFailure e )
{ {
@@ -164,23 +170,30 @@ public class CraftingJob implements Runnable, ICraftingJob
try try
{ {
final Stopwatch timer = Stopwatch.createStarted(); if( actionSrc.player().isPresent() )
final MECraftingInventory craftingInventory = new MECraftingInventory( this.original, true, false, true );
craftingInventory.ignore( this.output );
this.availableCheck = new MECraftingInventory( this.original, false, false, false );
this.getTree().setSimulate();
this.getTree().request( craftingInventory, this.output.getStackSize(), this.actionSrc );
this.getTree().dive( this );
for( final String s : this.opsAndMultiplier.keySet() )
{ {
final TwoIntegers ti = this.opsAndMultiplier.get( s ); final MECraftingInventory craftingInventory = new MECraftingInventory( this.original, true, false, true );
AELog.crafting( s + " * " + ti.times + " = " + ( ti.perOp * ti.times ) ); craftingInventory.ignore( this.output );
}
this.logCraftingJob( "simulate", timer ); this.getTree().setSimulate();
this.availableCheck = new MECraftingInventory( this.original, false, false, false );
craftingTreeWatch.reset().start();
this.getTree().request( craftingInventory, this.output.getStackSize(), this.actionSrc );
craftingTreeWatch.stop();
this.getTree().dive( this );
for( final String s : this.opsAndMultiplier.keySet() )
{
final TwoIntegers ti = this.opsAndMultiplier.get( s );
AELog.crafting( s + " * " + ti.times + " = " + ( ti.perOp * ti.times ) );
}
this.logCraftingJob( "simulated, failed", craftingTreeWatch );
}
else
{
this.logCraftingJob( "real, failed", craftingTreeWatch );
}
} }
catch( final CraftBranchFailure e1 ) catch( final CraftBranchFailure e1 )
{ {
@@ -226,10 +239,11 @@ public class CraftingJob implements Runnable, ICraftingJob
this.incTime = 0; this.incTime = 0;
synchronized ( this.monitor ) synchronized ( this.monitor )
{ {
if( this.watch.elapsed( TimeUnit.MICROSECONDS ) > this.time ) if( this.tickSpreadingWatch.elapsed( TimeUnit.MICROSECONDS ) > this.time )
{ {
this.running = false; this.running = false;
this.watch.stop(); this.craftingTreeWatch.stop();
this.tickSpreadingWatch.stop();
this.monitor.notify(); this.monitor.notify();
} }
@@ -245,12 +259,13 @@ public class CraftingJob implements Runnable, ICraftingJob
AELog.craftingDebug( "crafting job now active" ); AELog.craftingDebug( "crafting job now active" );
} }
} }
if( Thread.interrupted() )
{
throw new InterruptedException();
}
} }
if( Thread.interrupted() )
{
throw new InterruptedException();
}
this.incTime++; this.incTime++;
} }
@@ -263,7 +278,7 @@ public class CraftingJob implements Runnable, ICraftingJob
this.availableCheck = null; this.availableCheck = null;
synchronized( this.monitor ) synchronized ( this.monitor )
{ {
this.running = false; this.running = false;
this.done = true; this.done = true;
@@ -311,7 +326,7 @@ public class CraftingJob implements Runnable, ICraftingJob
/** /**
* @return true if this needs more simulation * @return true if this needs more simulation
*/ */
public boolean simulateFor(final int milli) public boolean simulateFor( final int milli )
{ {
this.time = milli; this.time = milli;
@@ -323,8 +338,8 @@ public class CraftingJob implements Runnable, ICraftingJob
} }
if( !this.actionSrc.player().isPresent() ) if( !this.actionSrc.player().isPresent() )
{ {
this.watch.reset(); this.tickSpreadingWatch.reset();
this.watch.start(); this.tickSpreadingWatch.start();
this.monitor.notify(); this.monitor.notify();
} }
this.running = true; this.running = true;
@@ -353,7 +368,7 @@ public class CraftingJob implements Runnable, ICraftingJob
if( AELog.isCraftingLogEnabled() ) if( AELog.isCraftingLogEnabled() )
{ {
final String itemToOutput = this.output.toString(); final String itemToOutput = this.output.toString();
final long elapsedTime = timer.elapsed( TimeUnit.MILLISECONDS ); final long elapsedTime = timer.elapsed( TimeUnit.MICROSECONDS );
final String actionSource; final String actionSource;
if( this.actionSrc.player().isPresent() ) if( this.actionSrc.player().isPresent() )
@@ -19,15 +19,6 @@
package appeng.crafting; package appeng.crafting;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Lists;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
@@ -37,9 +28,20 @@ import appeng.api.networking.security.IActionSource;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInformPlayer;
import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.util.Platform;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Optional;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Optional.Interface( iface = "gregtech.api.items.IToolItem", modid = "gregtech" )
public class CraftingTreeNode public class CraftingTreeNode
{ {
@@ -54,14 +56,14 @@ public class CraftingTreeNode
private final IAEItemStack what; private final IAEItemStack what;
// what are the crafting patterns for this? // what are the crafting patterns for this?
private final ArrayList<CraftingTreeProcess> nodes = new ArrayList<>(); private final ArrayList<CraftingTreeProcess> nodes = new ArrayList<>();
private final ICraftingGrid cc;
private final int depth;
private int bytes = 0; private int bytes = 0;
private boolean canEmit = false; private boolean canEmit = false;
private long missing = 0; private long missing = 0;
private long howManyEmitted = 0; private long howManyEmitted = 0;
private boolean exhausted = false; private boolean exhausted = false;
private boolean sim;
public CraftingTreeNode( final ICraftingGrid cc, final CraftingJob job, final IAEItemStack wat, final CraftingTreeProcess par, final int slot, final int depth ) public CraftingTreeNode( final ICraftingGrid cc, final CraftingJob job, final IAEItemStack wat, final CraftingTreeProcess par, final int slot, final int depth )
{ {
this.what = wat; this.what = wat;
@@ -69,9 +71,18 @@ public class CraftingTreeNode
this.slot = slot; this.slot = slot;
this.world = job.getWorld(); this.world = job.getWorld();
this.job = job; this.job = job;
this.sim = false; this.cc = cc;
this.depth = depth;
this.canEmit = cc.canEmitFor( this.what ); this.canEmit = cc.canEmitFor( this.what );
}
public void addNode()
{
if( !nodes.isEmpty() )
{
return;
}
if( this.canEmit ) if( this.canEmit )
{ {
@@ -81,108 +92,78 @@ public class CraftingTreeNode
for( final ICraftingPatternDetails details : cc.getCraftingFor( this.what, this.parent == null ? null : this.parent.details, slot, this.world ) )// in for( final ICraftingPatternDetails details : cc.getCraftingFor( this.what, this.parent == null ? null : this.parent.details, slot, this.world ) )// in
// order. // order.
{ {
if( this.parent == null || this.parent.notRecursive( details ) ) if( this.parent == null || notRecursive( details ) && this.parent.details != details )
{ {
this.nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1 ) ); this.nodes.add( new CraftingTreeProcess( cc, job, details, this, depth + 1 ) );
} }
} }
} }
boolean notRecursive( final ICraftingPatternDetails details )
{
IAEItemStack[] o = details.getCondensedOutputs();
for( final IAEItemStack i : o )
{
if( i.equals( this.what ) )
{
return false;
}
}
o = details.getCondensedInputs();
for( final IAEItemStack i : o )
{
if( i.equals( this.what ) )
{
return false;
}
}
if( this.parent == null )
{
return true;
}
return this.parent.notRecursive( details );
}
IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException IAEItemStack request( final MECraftingInventory inv, long l, final IActionSource src ) throws CraftBranchFailure, InterruptedException
{ {
addNode();
this.job.handlePausing(); this.job.handlePausing();
if( this.canEmit )
{
final IAEItemStack wat = this.what.copy();
wat.setStackSize( l );
this.howManyEmitted = wat.getStackSize();
this.bytes += wat.getStackSize();
return wat;
}
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
final List<IAEItemStack> thingsUsed = new ArrayList<>(); final List<IAEItemStack> thingsUsed = new ArrayList<>();
this.what.setStackSize( l ); this.what.setStackSize( l );
IAEItemStack available = inv.extractItems( this.what, Actionable.MODULATE, src );
if( available != null ) if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() )
{ {
if( !this.exhausted ) Collection<IAEItemStack> itemList = new ArrayList<>();
{
final IAEItemStack is = this.job.checkUse( available );
if( is != null ) boolean damageableItem = this.what.getItem().isDamageable() || Platform.isGTDamageableItem( this.what.getItem() );
{
thingsUsed.add( is.copy() );
this.used.add( is );
}
}
this.bytes += available.getStackSize();
l -= available.getStackSize();
if( l == 0 )
{
return available;
}
}
else if( this.getSlot() >= 0 && this.parent != null && this.parent.details.isCraftable() )
{
final Collection<IAEItemStack> itemList;
final IItemList<IAEItemStack> inventoryList = inv.getItemList();
if( this.parent.details.canSubstitute() ) if( this.parent.details.canSubstitute() )
{ {
final List<IAEItemStack> substitutes = this.parent.details.getSubstituteInputs( this.slot ); for( IAEItemStack subs : this.parent.details.getSubstituteInputs( this.slot ) )
itemList = new ArrayList<>( substitutes.size() );
for( IAEItemStack stack : substitutes )
{ {
itemList.addAll( inventoryList.findFuzzy( stack, FuzzyMode.IGNORE_ALL ) ); if( damageableItem )
{
itemList.addAll( inventoryList.findFuzzy( subs, FuzzyMode.IGNORE_ALL ) );
}
subs = inventoryList.findPrecise( subs );
if( subs != null )
{
itemList.add( subs );
}
} }
} }
else else
{ {
itemList = Lists.newArrayList(); if( damageableItem )
final IAEItemStack item = inventoryList.findPrecise( this.what );
if( item != null )
{ {
itemList.add( item ); itemList.addAll( inventoryList.findFuzzy( this.what, FuzzyMode.IGNORE_ALL ) );
}
else
{
final IAEItemStack item = inventoryList.findPrecise( this.what );
if( item != null )
{
itemList.add( item );
}
} }
} }
for( IAEItemStack fuzz : itemList ) for( IAEItemStack fuzz : itemList )
{ {
if( this.parent.details.isValidItemForSlot( this.getSlot(), fuzz.copy().setStackSize( 1 ).createItemStack(), this.world ) ) if( this.parent.details.isValidItemForSlot( this.getSlot(), fuzz.copy().getCachedItemStack( 1 ), this.world ) )
{ {
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize( l ); fuzz.setStackSize( l );
available = inv.extractItems( fuzz, Actionable.MODULATE, src ); final IAEItemStack available = inv.extractItems( fuzz, Actionable.MODULATE, src );
if( available != null ) if( available != null )
{ {
@@ -208,16 +189,31 @@ public class CraftingTreeNode
} }
} }
} }
else
if( this.canEmit )
{ {
final IAEItemStack wat = this.what.copy(); final IAEItemStack available = inv.extractItems( this.what, Actionable.MODULATE, src );
wat.setStackSize( l );
this.howManyEmitted = wat.getStackSize(); if( available != null )
this.bytes += wat.getStackSize(); {
if( !this.exhausted )
{
final IAEItemStack is = this.job.checkUse( available );
return wat; if( is != null )
{
thingsUsed.add( is.copy() );
this.used.add( is );
}
}
this.bytes += available.getStackSize();
l -= available.getStackSize();
if( l == 0 )
{
return available;
}
}
} }
this.exhausted = true; this.exhausted = true;
@@ -229,12 +225,10 @@ public class CraftingTreeNode
while ( pro.possible && l > 0 ) while ( pro.possible && l > 0 )
{ {
final IAEItemStack madeWhat = pro.getAmountCrafted( this.what ); final IAEItemStack madeWhat = pro.getAmountCrafted( this.what );
pro.request( inv, pro.getTimes( l, madeWhat.getStackSize() ), src ); pro.request( inv, pro.getTimes( l, madeWhat.getStackSize() ), src );
madeWhat.setStackSize( l ); madeWhat.setStackSize( l );
final IAEItemStack available = inv.extractItems( madeWhat, Actionable.MODULATE, src );
available = inv.extractItems( madeWhat, Actionable.MODULATE, src );
if( available != null ) if( available != null )
{ {
@@ -264,7 +258,7 @@ public class CraftingTreeNode
pro.request( subInv, 1, src ); pro.request( subInv, 1, src );
this.what.setStackSize( l ); this.what.setStackSize( l );
available = subInv.extractItems( this.what, Actionable.MODULATE, src ); final IAEItemStack available = subInv.extractItems( this.what, Actionable.MODULATE, src );
if( available != null ) if( available != null )
{ {
@@ -294,10 +288,10 @@ public class CraftingTreeNode
} }
} }
if( this.sim ) if( job.isSimulation() )
{ {
this.missing += l;
this.bytes += l; this.bytes += l;
this.missing += l;
final IAEItemStack rv = this.what.copy(); final IAEItemStack rv = this.what.copy();
rv.setStackSize( l ); rv.setStackSize( l );
return rv; return rv;
@@ -313,6 +307,19 @@ public class CraftingTreeNode
throw new CraftBranchFailure( this.what, l ); throw new CraftBranchFailure( this.what, l );
} }
boolean notRecursive( ICraftingPatternDetails details )
{
if( this.parent == null )
{
return true;
}
if( this.parent.details == details )
{
return false;
}
return this.parent.notRecursive( details );
}
void dive( final CraftingJob job ) void dive( final CraftingJob job )
{ {
if( this.missing > 0 ) if( this.missing > 0 )
@@ -338,7 +345,6 @@ public class CraftingTreeNode
void setSimulate() void setSimulate()
{ {
this.sim = true;
this.missing = 0; this.missing = 0;
this.bytes = 0; this.bytes = 0;
this.used.resetStatus(); this.used.resetStatus();
@@ -354,18 +360,32 @@ public class CraftingTreeNode
{ {
for( final IAEItemStack i : this.used ) for( final IAEItemStack i : this.used )
{ {
final IAEItemStack ex = storage.extractItems( i, Actionable.MODULATE, src ); final IAEItemStack actuallyExtracted = storage.extractItems( i, Actionable.MODULATE, src );
if( ex == null || ex.getStackSize() != i.getStackSize() ) if( actuallyExtracted == null || actuallyExtracted.getStackSize() != i.getStackSize() )
{ {
if( src.player().isPresent() ) if( src.player().isPresent() )
{ {
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + i.getStackSize() + " " + i.getDefinition().getItem().getItemStackDisplayName( i.getDefinition() ) + " available but could not extract anything" ), false ); try
{
if( actuallyExtracted == null )
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( i, null, PacketInformPlayer.InfoType.NO_ITEMS_EXTRACTED ), (EntityPlayerMP) src.player().get() );
}
else
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( i, actuallyExtracted, PacketInformPlayer.InfoType.PARTIAL_ITEM_EXTRACTION ), (EntityPlayerMP) src.player().get() );
}
}
catch( IOException e )
{
e.printStackTrace();
}
} }
throw new CraftBranchFailure( i, i.getStackSize() ); throw new CraftBranchFailure( i, i.getStackSize() );
} }
craftingCPUCluster.addStorage( ex ); craftingCPUCluster.addStorage( actuallyExtracted );
} }
if( this.howManyEmitted > 0 ) if( this.howManyEmitted > 0 )
@@ -19,43 +19,37 @@
package appeng.crafting; package appeng.crafting;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.networking.crafting.ICraftingGrid; import appeng.api.networking.crafting.ICraftingGrid;
import appeng.api.networking.crafting.ICraftingPatternDetails; import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.security.IActionSource; import appeng.api.networking.security.IActionSource;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.container.ContainerNull; import appeng.core.AEConfig;
import appeng.me.cluster.implementations.CraftingCPUCluster; import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import com.google.common.collect.ImmutableCollection;
import it.unimi.dsi.fastutil.objects.Object2LongArrayMap;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
public class CraftingTreeProcess public class CraftingTreeProcess
{ {
private final CraftingTreeNode parent; private final CraftingTreeNode parent;
final ICraftingPatternDetails details; final ICraftingPatternDetails details;
private final CraftingJob job; private final CraftingJob job;
private final Map<CraftingTreeNode, Long> nodes = new HashMap<>(); private final Object2LongArrayMap<CraftingTreeNode> nodes = new Object2LongArrayMap<>();
private final int depth; private final int depth;
private final ICraftingGrid cc;
private final World world;
boolean possible = true; boolean possible = true;
private World world;
private long crafts = 0; private long crafts = 0;
private boolean containerItems;
private boolean limitQty;
private boolean fullSimulation;
private long bytes = 0; private long bytes = 0;
public CraftingTreeProcess( final ICraftingGrid cc, final CraftingJob job, final ICraftingPatternDetails details, final CraftingTreeNode craftingTreeNode, final int depth ) public CraftingTreeProcess( final ICraftingGrid cc, final CraftingJob job, final ICraftingPatternDetails details, final CraftingTreeNode craftingTreeNode, final int depth )
@@ -64,171 +58,221 @@ public class CraftingTreeProcess
this.details = details; this.details = details;
this.job = job; this.job = job;
this.depth = depth; this.depth = depth;
final World world = job.getWorld(); this.cc = cc;
this.world = job.getWorld();
}
if( details.isCraftable() ) public void addProcess()
{
if( !nodes.isEmpty() )
{ {
final IAEItemStack[] list = details.getInputs(); return;
}
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 ); final IAEItemStack[] list = details.getInputs();
final IAEItemStack[] is = details.getInputs();
for( int x = 0; x < ic.getSizeInventory(); x++ ) // this is minor different then below, this slot uses the pattern, but kinda fudges it.
for( IAEItemStack part : details.getCondensedInputs() )
{
if( part == null )
{ {
ic.setInventorySlotContents( x, is[x] == null ? ItemStack.EMPTY : is[x].createItemStack() ); continue;
} }
for( int x = 0; x < list.length; x++ )
for( int x = 0; x < ic.getSizeInventory(); x++ )
{ {
final ItemStack g = ic.getStackInSlot( x ); final IAEItemStack comparePart = list[x];
if( !g.isEmpty() && g.getCount() > 1 ) if( part.equals( comparePart ) )
{ {
this.fullSimulation = true; boolean isPartContainer = false;
} if( part.getItem().hasContainerItem( part.getDefinition() ) )
}
for( final IAEItemStack part : details.getCondensedInputs() )
{
final ItemStack g = part.createItemStack();
boolean isAnInput = false;
for( final IAEItemStack a : details.getCondensedOutputs() )
{
if( !g.isEmpty() && a != null && a.equals( g ) )
{ {
isAnInput = true; part = list[x];
isPartContainer = true;
} }
}
if( isAnInput ) long wantedSize = part.getStackSize();
{
this.limitQty = true;
}
if( g.getItem().hasContainerItem( g ) ) if( AEConfig.instance().getEnableCraftingSubstitutes() )
{
this.limitQty = this.containerItems = true;
}
}
final boolean complicated = false;
if( this.containerItems || complicated )
{
for( int x = 0; x < list.length; x++ )
{
final IAEItemStack part = list[x];
if( part != null )
{ {
this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() ); IAEItemStack found;
} long remaining;
} long requestAmount;
}
else if( details.canSubstitute() )
{
// this is minor different then below, this slot uses the pattern, but kinda fudges it.
for( final IAEItemStack part : details.getCondensedInputs() )
{
for( int x = 0; x < list.length; x++ )
{
final IAEItemStack comparePart = list[x];
if( part != null && part.equals( comparePart ) )
{ {
// use the first slot... for( IAEItemStack subs : details.getSubstituteInputs( x ) )
this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, x, depth + 1 ), part.getStackSize() ); {
break; found = job.checkAvailable( subs );
if( found != null )
{
remaining = found.getStackSize();
}
else
{
remaining = 0;
}
if( remaining > 0 )
{
if( remaining >= wantedSize )
{
requestAmount = wantedSize;
wantedSize = 0;
//we have the items
}
else
{
requestAmount = remaining;
wantedSize -= remaining;
}
subs = subs.copy().setStackSize( requestAmount );
CraftingTreeNode node = new CraftingTreeNode( cc, job, subs, this, x, depth + 1 );
this.nodes.put( node, requestAmount );
if( wantedSize == 0 )
{
break;
}
}
}
}
else
{
found = job.checkAvailable( part );
if( found != null )
{
remaining = found.getStackSize();
}
else
{
remaining = 0;
}
if( remaining > 0 )
{
if( remaining >= wantedSize )
{
requestAmount = wantedSize;
wantedSize = 0;
//we have the items
}
else
{
requestAmount = remaining;
wantedSize -= remaining;
}
part = part.copy().setStackSize( requestAmount );
this.nodes.put( new CraftingTreeNode( cc, job, part, this, x, depth + 1 ), requestAmount );
}
}
if( wantedSize > 0 )
{
if( details.canSubstitute() && cc.getCraftingFor( part, details, x, world ).isEmpty() )
{
//try to order the crafting of a substitute
ICraftingPatternDetails prioritizedPattern = null;
IAEItemStack prioritizedIAE = null;
for( IAEItemStack subs : details.getSubstituteInputs( x ) )
{
ImmutableCollection<ICraftingPatternDetails> detailCollection = cc.getCraftingFor( subs, details, x, world );
for( ICraftingPatternDetails sp : detailCollection )
{
if( prioritizedPattern == null )
{
prioritizedPattern = sp;
prioritizedIAE = subs;
}
else
{
if( sp.getPriority() > prioritizedPattern.getPriority() )
{
prioritizedPattern = sp;
}
}
}
if( prioritizedIAE != null )
{
subs = subs.copy().setStackSize( wantedSize );
CraftingTreeNode node = new CraftingTreeNode( cc, job, subs, this, x, depth + 1 );
this.nodes.put( node, wantedSize );
wantedSize = 0;
break;
}
}
}
} }
} }
} if( wantedSize > 0 )
}
}
else
{
for( final IAEItemStack part : details.getCondensedInputs() )
{
final ItemStack g = part.createItemStack();
boolean isAnInput = false;
for( final IAEItemStack a : details.getCondensedOutputs() )
{
if( !g.isEmpty() && a != null && a.equals( g ) )
{ {
isAnInput = true; part = part.copy().setStackSize( wantedSize );
// use the first slot...
this.nodes.put( new CraftingTreeNode( cc, job, part, this, x, depth + 1 ), wantedSize );
wantedSize = 0;
}
if( !isPartContainer && wantedSize == 0 )
{
break;
} }
} }
if( isAnInput )
{
this.limitQty = true;
}
}
for( final IAEItemStack part : details.getCondensedInputs() )
{
this.nodes.put( new CraftingTreeNode( cc, job, part.copy(), this, -1, depth + 1 ), part.getStackSize() );
} }
} }
} }
boolean notRecursive( final ICraftingPatternDetails details ) boolean notRecursive( ICraftingPatternDetails details )
{ {
return this.parent == null || this.parent.notRecursive( details ); return this.parent == null || this.parent.notRecursive( details );
} }
long getTimes( final long remaining, final long stackSize ) long getTimes( final long remaining, final long stackSize )
{ {
if( this.limitQty || this.fullSimulation ) for( final IAEItemStack part : details.getCondensedOutputs() )
{ {
return 1; for( final IAEItemStack o : details.getCondensedInputs() )
{
if( part.equals( o ) || o.getItem().hasContainerItem( part.getDefinition() ) )
{
return 1;
}
}
} }
return ( remaining / stackSize ) + ( remaining % stackSize != 0 ? 1 : 0 ); return ( remaining / stackSize ) + ( remaining % stackSize != 0 ? 1 : 0 );
} }
void request( final MECraftingInventory inv, final long i, final IActionSource src ) throws CraftBranchFailure, InterruptedException void request( final MECraftingInventory inv, final long amountOfTimes, final IActionSource src ) throws CraftBranchFailure, InterruptedException
{ {
addProcess();
this.job.handlePausing(); this.job.handlePausing();
if( this.fullSimulation ) List<IAEItemStack> containerItems = null;
// request and remove inputs...
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
final InventoryCrafting ic = new InventoryCrafting( new ContainerNull(), 3, 3 ); final IAEItemStack stack = entry.getKey().request( inv, entry.getValue() * amountOfTimes, src );
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.entrySet() ) if( this.details.isCraftable() && stack.getItem().hasContainerItem( stack.getDefinition() ) )
{ {
final IAEItemStack item = entry.getKey().getStack( entry.getValue() ); final ItemStack is = Platform.getContainerItem( stack.createItemStack() );
final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize(), src ); final IAEItemStack o = AEItemStack.fromItemStack( is );
ic.setInventorySlotContents( entry.getKey().getSlot(), stack.createItemStack() );
}
for( int x = 0; x < ic.getSizeInventory(); x++ )
{
ItemStack is = ic.getStackInSlot( x );
is = Platform.getContainerItem( is );
final IAEItemStack o = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( is );
if( o != null ) if( o != null )
{ {
if( containerItems == null )
{
containerItems = new ArrayList<>();
}
this.bytes++; this.bytes++;
inv.injectItems( o, Actionable.MODULATE, src ); o.setCachedItemStack( is );
containerItems.add( o );
} }
} }
} }
else
{
// request and remove inputs...
for( final Entry<CraftingTreeNode, Long> entry : this.nodes.entrySet() )
{
final IAEItemStack item = entry.getKey().getStack( entry.getValue() );
final IAEItemStack stack = entry.getKey().request( inv, item.getStackSize() * i, src );
if( this.containerItems ) if( containerItems != null )
{ {
final ItemStack is = Platform.getContainerItem( stack.createItemStack() ); for( IAEItemStack i : containerItems )
final IAEItemStack o = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( is ); {
if( o != null ) inv.injectItems( i, Actionable.MODULATE, src );
{
this.bytes++;
inv.injectItems( o, Actionable.MODULATE, src );
}
}
} }
} }
@@ -238,21 +282,21 @@ public class CraftingTreeProcess
for( final IAEItemStack out : this.details.getCondensedOutputs() ) for( final IAEItemStack out : this.details.getCondensedOutputs() )
{ {
final IAEItemStack o = out.copy(); final IAEItemStack o = out.copy();
o.setStackSize( o.getStackSize() * i ); o.setStackSize( o.getStackSize() * amountOfTimes );
inv.injectItems( o, Actionable.MODULATE, src ); inv.injectItems( o, Actionable.MODULATE, src );
} }
this.crafts += i; this.crafts += amountOfTimes;
} }
void dive( final CraftingJob job ) void dive( final CraftingJob job )
{ {
job.addTask( this.getAmountCrafted( this.parent.getStack( 1 ) ), this.crafts, this.details, this.depth ); job.addTask( this.getAmountCrafted( this.parent.getStack( 1 ) ), this.crafts, this.details, this.depth );
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.dive( job ); entry.getKey().dive( job );
} }
job.addBytes( this.crafts + 8 + this.bytes ); job.addBytes( this.crafts * 8 + this.bytes );
} }
IAEItemStack getAmountCrafted( IAEItemStack what2 ) IAEItemStack getAmountCrafted( IAEItemStack what2 )
@@ -286,9 +330,9 @@ public class CraftingTreeProcess
this.crafts = 0; this.crafts = 0;
this.bytes = 0; this.bytes = 0;
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.setSimulate(); entry.getKey().setSimulate();
} }
} }
@@ -296,9 +340,9 @@ public class CraftingTreeProcess
{ {
craftingCPUCluster.addCrafting( this.details, this.crafts ); craftingCPUCluster.addCrafting( this.details, this.crafts );
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.setJob( storage, craftingCPUCluster, src ); entry.getKey().setJob( storage, craftingCPUCluster, src );
} }
} }
@@ -311,9 +355,9 @@ public class CraftingTreeProcess
plan.addRequestable( i ); plan.addRequestable( i );
} }
for( final CraftingTreeNode pro : this.nodes.keySet() ) for( final Entry<CraftingTreeNode, Long> entry : this.nodes.object2LongEntrySet() )
{ {
pro.getPlan( plan ); entry.getKey().getPlan( plan );
} }
} }
} }
@@ -28,10 +28,14 @@ import appeng.api.storage.IStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
import appeng.me.helpers.PlayerSource; import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketInformPlayer;
import appeng.util.inv.ItemListIgnoreCrafting; import appeng.util.inv.ItemListIgnoreCrafting;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import java.io.IOException;
public class MECraftingInventory implements IMEInventory<IAEItemStack> public class MECraftingInventory implements IMEInventory<IAEItemStack>
{ {
@@ -97,8 +101,7 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
this.injectedCache = null; this.injectedCache = null;
} }
this.localCache = this.target this.localCache = this.target.getAvailableItems( new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) );
.getAvailableItems( new ItemListIgnoreCrafting<>( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList() ) );
this.par = parent; this.par = parent;
} }
@@ -311,17 +314,23 @@ public class MECraftingInventory implements IMEInventory<IAEItemStack>
{ {
if( src.player().isPresent() ) if( src.player().isPresent() )
{ {
if( result == null ) try
{ {
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getItem().getItemStackDisplayName( extra.getDefinition() ) + " available but could not extract anything" ), false ); if( result == null )
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( null, extra, PacketInformPlayer.InfoType.NO_ITEMS_EXTRACTED ), (EntityPlayerMP) src.player().get() );
}
else
{
NetworkHandler.instance().sendTo( new PacketInformPlayer( result, extra, PacketInformPlayer.InfoType.PARTIAL_ITEM_EXTRACTION ), (EntityPlayerMP) src.player().get() );
}
} }
else catch( IOException e )
{ {
src.player().get().sendStatusMessage( new TextComponentString( "System reported " + extra.getStackSize() + " " + extra.getDefinition().getItem().getItemStackDisplayName( extra.getDefinition() ) + " available but could only extract " + result.getStackSize() ), false ); e.printStackTrace();
} }
} }
failed = true; failed = true;
if( !src.player().isPresent() ) break;
} }
} }
} }
@@ -68,7 +68,7 @@ public class GuiFluidInterface extends GuiUpgradeable implements IConfigManagerH
for( int i = 0; i < DualityFluidInterface.NUMBER_OF_TANKS; ++i ) for( int i = 0; i < DualityFluidInterface.NUMBER_OF_TANKS; ++i )
{ {
this.guiSlots.add( new GuiFluidTank( fluidTank, i, DualityFluidInterface.NUMBER_OF_TANKS + i, 36 + 18 * i, 53, 16, 68 ) ); this.guiSlots.add( new GuiFluidTank( fluidTank, i, DualityFluidInterface.NUMBER_OF_TANKS + i, 36 + 18 * i, 57, 16, 64 ) );
this.guiSlots.add( new GuiFluidSlot( configFluids, i, i, 35 + 18 * i, 35 ) ); this.guiSlots.add( new GuiFluidSlot( configFluids, i, i, 35 + 18 * i, 35 ) );
} }
@@ -77,14 +77,14 @@ public class GuiFluidTank extends GuiCustomSlot implements ITooltip
TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( fluid.getFluid().getStill().toString() ); TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( fluid.getFluid().getStill().toString() );
final int scaledHeight = (int) ( this.height * ( (float) fluid.getStackSize() / this.tank.getTankProperties()[this.slot].getCapacity() ) ); final int scaledHeight = (int) ( this.height * ( (float) fluid.getStackSize() / this.tank.getTankProperties()[this.slot].getCapacity() ) );
int iconHeightRemainder = scaledHeight % this.getHeight(); int iconHeightRemainder = scaledHeight % 16;
if( iconHeightRemainder > 0 ) if( iconHeightRemainder > 0 )
{ {
this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder, sprite, this.getWidth(), iconHeightRemainder ); this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder, sprite, 16, iconHeightRemainder );
} }
for( int i = 0; i < scaledHeight / this.getHeight(); i++ ) for( int i = 0; i < scaledHeight / 16; i++ )
{ {
this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder - ( i + 1 ) * 16, sprite, this.getWidth(), this.getHeight() ); this.drawTexturedModalRect( this.xPos(), this.yPos() + this.getHeight() - iconHeightRemainder - ( i + 1 ) * 16, sprite, 16, 16 );
} }
} }
} }
@@ -113,7 +113,7 @@ public class GuiFluidTank extends GuiCustomSlot implements ITooltip
@Override @Override
public int yPos() public int yPos()
{ {
return this.y - 1; return this.y - 4;
} }
@Override @Override
@@ -125,7 +125,7 @@ public class GuiFluidTank extends GuiCustomSlot implements ITooltip
@Override @Override
public int getHeight() public int getHeight()
{ {
return this.height + 1; return this.height + 4;
} }
@Override @Override
@@ -414,7 +414,7 @@ public class ContainerFluidTerminal extends AEBaseContainer implements IConfigMa
} }
} }
if( notInserted == null ) if( notInserted == null || notInserted.getStackSize() == 0 )
{ {
if( !player.inventory.addItemStackToInventory( fh.getContainer() ) ) if( !player.inventory.addItemStackToInventory( fh.getContainer() ) )
{ {
+336 -172
View File
@@ -19,39 +19,6 @@
package appeng.helpers; package appeng.helpers;
import java.util.*;
import javax.annotation.Nullable;
import appeng.integration.modules.gregtech.GTCEInventoryAdaptor;
import appeng.util.*;
import appeng.util.inv.*;
import com.google.common.collect.ImmutableSet;
import de.ellpeck.actuallyadditions.api.tile.IPhantomTile;
import gregtech.api.block.machines.BlockMachine;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.MetaTileEntityHolder;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.RangedWrapper;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
import appeng.api.config.Settings; import appeng.api.config.Settings;
@@ -75,11 +42,7 @@ import appeng.api.networking.ticking.IGridTickable;
import appeng.api.networking.ticking.TickRateModulation; import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest; import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.IPart; import appeng.api.parts.IPart;
import appeng.api.storage.IMEInventory; import appeng.api.storage.*;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IStorageChannel;
import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.api.storage.channels.IFluidStorageChannel; import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.channels.IItemStorageChannel; import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEFluidStack; import appeng.api.storage.data.IAEFluidStack;
@@ -99,23 +62,54 @@ import appeng.me.storage.MEMonitorPassThrough;
import appeng.me.storage.NullInventory; import appeng.me.storage.NullInventory;
import appeng.parts.automation.StackUpgradeInventory; import appeng.parts.automation.StackUpgradeInventory;
import appeng.parts.automation.UpgradeInventory; import appeng.parts.automation.UpgradeInventory;
import appeng.parts.misc.PartInterface;
import appeng.tile.inventory.AppEngInternalAEInventory; import appeng.tile.inventory.AppEngInternalAEInventory;
import appeng.tile.inventory.AppEngInternalInventory; import appeng.tile.inventory.AppEngInternalInventory;
import appeng.tile.networking.TileCableBus;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.inv.*;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import de.ellpeck.actuallyadditions.api.tile.IPhantomTile;
import gregtech.api.block.machines.BlockMachine;
import gregtech.api.metatileentity.MetaTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Items;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.RangedWrapper;
import static gregtech.api.block.machines.BlockMachine.getMetaTileEntity; import javax.annotation.Nullable;
import java.util.*;
public class DualityInterface implements IGridTickable, IStorageMonitorable, IInventoryDestination, IAEAppEngInventory, IConfigManagerHost, ICraftingProvider, IUpgradeableHost public class DualityInterface implements IGridTickable, IStorageMonitorable, IInventoryDestination, IAEAppEngInventory, IConfigManagerHost, ICraftingProvider, IUpgradeableHost
{ {
private int[] failedCraftTriesSlot = {0,0,0,0,0,0,0,0,0};
public static final int NUMBER_OF_STORAGE_SLOTS = 9; public static final int NUMBER_OF_STORAGE_SLOTS = 9;
public static final int NUMBER_OF_CONFIG_SLOTS = 9; public static final int NUMBER_OF_CONFIG_SLOTS = 9;
public static final int NUMBER_OF_PATTERN_SLOTS = 36; public static final int NUMBER_OF_PATTERN_SLOTS = 36;
private static final Collection<Block> BAD_BLOCKS = new HashSet<>( 100 ); private static final Collection<Block> BAD_BLOCKS = new HashSet<>( 100 );
private final IAEItemStack[] requireWork = { null, null, null, null, null, null, null, null, null }; private final IAEItemStack[] requireWork = {null, null, null, null, null, null, null, null, null};
private final MultiCraftingTracker craftingTracker; private final MultiCraftingTracker craftingTracker;
private final AENetworkProxy gridProxy; private final AENetworkProxy gridProxy;
private final IInterfaceHost iHost; private final IInterfaceHost iHost;
@@ -125,23 +119,18 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private final AppEngInternalAEInventory config = new AppEngInternalAEInventory( this, NUMBER_OF_CONFIG_SLOTS ); private final AppEngInternalAEInventory config = new AppEngInternalAEInventory( this, NUMBER_OF_CONFIG_SLOTS );
private final AppEngInternalInventory storage = new AppEngInternalInventory( this, NUMBER_OF_STORAGE_SLOTS ); private final AppEngInternalInventory storage = new AppEngInternalInventory( this, NUMBER_OF_STORAGE_SLOTS );
private final AppEngInternalInventory patterns = new AppEngInternalInventory( this, NUMBER_OF_PATTERN_SLOTS ); private final AppEngInternalInventory patterns = new AppEngInternalInventory( this, NUMBER_OF_PATTERN_SLOTS );
private final MEMonitorPassThrough<IAEItemStack> items = new MEMonitorPassThrough<>( new NullInventory<IAEItemStack>(), AEApi.instance() private final MEMonitorPassThrough<IAEItemStack> items = new MEMonitorPassThrough<>( new NullInventory<IAEItemStack>(), AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
.storage() private final MEMonitorPassThrough<IAEFluidStack> fluids = new MEMonitorPassThrough<>( new NullInventory<IAEFluidStack>(), AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) );
.getStorageChannel( IItemStorageChannel.class ) );
private final MEMonitorPassThrough<IAEFluidStack> fluids = new MEMonitorPassThrough<>( new NullInventory<IAEFluidStack>(), AEApi.instance()
.storage()
.getStorageChannel( IFluidStorageChannel.class ) );
private final UpgradeInventory upgrades; private final UpgradeInventory upgrades;
private final Accessor accessor = new Accessor();
private boolean hasConfig = false; private boolean hasConfig = false;
private int priority; private int priority;
private List<ICraftingPatternDetails> craftingList = null; private List<ICraftingPatternDetails> craftingList = null;
private List<ItemStack> waitingToSend = null; private List<ItemStack> waitingToSend = null;
private IMEInventory<IAEItemStack> destination; private IMEInventory<IAEItemStack> destination;
private int isWorking = -1; private int isWorking = -1;
private final Accessor accessor = new Accessor();
private EnumSet<EnumFacing> visitedFaces = EnumSet.noneOf( EnumFacing.class ); private EnumSet<EnumFacing> visitedFaces = EnumSet.noneOf( EnumFacing.class );
private EnumMap<EnumFacing, List<ItemStack>> waitingToSendFacing = new EnumMap<>( EnumFacing.class ); private EnumMap<EnumFacing, List<ItemStack>> waitingToSendFacing = new EnumMap<>( EnumFacing.class );
private GTCEInventoryAdaptor GTad;
private boolean resetConfigCache = true; private boolean resetConfigCache = true;
private IMEMonitor<IAEItemStack> configCachedHandler; private IMEMonitor<IAEItemStack> configCachedHandler;
@@ -165,6 +154,11 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
this.interfaceRequestSource = new InterfaceRequestSource( this.iHost ); this.interfaceRequestSource = new InterfaceRequestSource( this.iHost );
} }
private static boolean invIsCustomBlocking( BlockingInventoryAdaptor inv )
{
return ( inv.containsBlockingItems() );
}
@Override @Override
public void saveChanges() public void saveChanges()
{ {
@@ -245,12 +239,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
NBTTagCompound sidedWaitList = new NBTTagCompound(); NBTTagCompound sidedWaitList = new NBTTagCompound();
if (this.waitingToSendFacing != null) if( this.waitingToSendFacing != null )
{ {
for( EnumFacing s : this.iHost.getTargets() ) for( EnumFacing s : this.iHost.getTargets() )
{ {
NBTTagList waitingListSided = new NBTTagList(); NBTTagList waitingListSided = new NBTTagList();
if (this.waitingToSendFacing.containsKey( s )) if( this.waitingToSendFacing.containsKey( s ) )
{ {
for( final ItemStack is : this.waitingToSendFacing.get( s ) ) for( final ItemStack is : this.waitingToSendFacing.get( s ) )
{ {
@@ -286,6 +280,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final NBTTagCompound waitingListSided = data.getCompoundTag( "sidedWaitList" ); final NBTTagCompound waitingListSided = data.getCompoundTag( "sidedWaitList" );
for( EnumFacing s : EnumFacing.values() ) for( EnumFacing s : EnumFacing.values() )
{
if( waitingListSided.hasKey( s.name() ) ) if( waitingListSided.hasKey( s.name() ) )
{ {
NBTTagList w = waitingListSided.getTagList( s.name(), 10 ); NBTTagList w = waitingListSided.getTagList( s.name(), 10 );
@@ -299,6 +294,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
} }
}
this.craftingTracker.readFromNBT( data ); this.craftingTracker.readFromNBT( data );
@@ -358,8 +354,9 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
{ {
return; return;
} }
if (this.waitingToSendFacing == null){ if( this.waitingToSendFacing == null )
this.waitingToSendFacing = new EnumMap<>(EnumFacing.class); {
this.waitingToSendFacing = new EnumMap<>( EnumFacing.class );
} }
this.waitingToSendFacing.computeIfAbsent( f, k -> new ArrayList<>() ); this.waitingToSendFacing.computeIfAbsent( f, k -> new ArrayList<>() );
@@ -416,7 +413,6 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
// :P // :P
} }
} }
this.notifyNeighbors(); this.notifyNeighbors();
} }
@@ -430,15 +426,17 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return; return;
} }
boolean removed = false;
if( this.craftingList != null ) if( this.craftingList != null )
{ {
final Iterator<ICraftingPatternDetails> i = this.craftingList.iterator(); final Iterator<ICraftingPatternDetails> i = this.craftingList.iterator();
while( i.hasNext() ) while ( i.hasNext() )
{ {
final ICraftingPatternDetails details = i.next(); final ICraftingPatternDetails details = i.next();
boolean found = false; boolean found = false;
for( int x = 0; x < accountedFor.length ; x++ ) for( int x = 0; x < accountedFor.length; x++ )
{ {
final ItemStack is = this.patterns.getStackInSlot( x ); final ItemStack is = this.patterns.getStackInSlot( x );
if( details.getPattern() == is ) if( details.getPattern() == is )
@@ -449,41 +447,49 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( !found ) if( !found )
{ {
removed = true;
i.remove(); i.remove();
} }
} }
} }
for( int x = 0; x < accountedFor.length ; x++ ) boolean newPattern = false;
for( int x = 0; x < accountedFor.length; x++ )
{ {
if( !accountedFor[x] ) if( !accountedFor[x] )
{ {
newPattern = true;
this.addToCraftingList( this.patterns.getStackInSlot( x ) ); this.addToCraftingList( this.patterns.getStackInSlot( x ) );
} }
} }
try try
{ {
this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) ); this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) );
} }
catch( final GridAccessException e ) catch( GridAccessException e )
{ {
// :P e.printStackTrace();
} }
} }
private boolean hasWorkToDo() { private boolean hasWorkToDo()
{
if (hasItemsToSend()){ if( hasItemsToSend() )
{
return true; return true;
} }
if(hasItemsToSendFacing()){ if( hasItemsToSendFacing() )
{
return true; return true;
} }
for (final IAEItemStack requiredWork : this.requireWork) { for( final IAEItemStack requiredWork : this.requireWork )
if (requiredWork != null) { {
if( requiredWork != null )
{
return true; return true;
} }
} }
@@ -594,7 +600,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private boolean hasItemsToSendFacing() private boolean hasItemsToSendFacing()
{ {
if (waitingToSendFacing != null) if( waitingToSendFacing != null )
{ {
for( EnumFacing enumFacing : waitingToSendFacing.keySet() ) for( EnumFacing enumFacing : waitingToSendFacing.keySet() )
{ {
@@ -614,10 +620,13 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
List<ItemStack> dropList = new ArrayList<>(); List<ItemStack> dropList = new ArrayList<>();
for( int invSlot = 0; invSlot < patterns.getSlots(); invSlot++ ) for( int invSlot = 0; invSlot < patterns.getSlots(); invSlot++ )
{ {
if( invSlot > 8 + this.getInstalledUpgrades( Upgrades.PATTERN_EXPANSION ) * 9 ) if( invSlot > 8 + this.getInstalledUpgrades( Upgrades.PATTERN_EXPANSION ) * 9 )
{ {
ItemStack is = patterns.getStackInSlot( invSlot ); ItemStack is = patterns.getStackInSlot( invSlot );
if( is.isEmpty() ) continue; if( is.isEmpty() )
{
continue;
}
dropList.add( patterns.extractItem( invSlot, Integer.MAX_VALUE, false ) ); dropList.add( patterns.extractItem( invSlot, Integer.MAX_VALUE, false ) );
} }
} }
@@ -634,17 +643,12 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
@Override @Override
public boolean canInsert( final ItemStack stack ) public boolean canInsert( final ItemStack stack )
{ {
final IAEItemStack out = this.destination.injectItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( stack ), final IAEItemStack out = this.destination.injectItems( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createStack( stack ), Actionable.SIMULATE, null );
Actionable.SIMULATE, null );
if( out == null ) if( out == null )
{ {
return true; return true;
} }
return out.getStackSize() != stack.getCount(); return out.getStackSize() != stack.getCount();
// ItemStack after = adaptor.simulateAdd( stack );
// if ( after == null )
// return true;
// return after.stackSize != stack.stackSize;
} }
public IItemHandler getConfig() public IItemHandler getConfig()
@@ -709,7 +713,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
this.pushItemsOut( this.iHost.getTargets() ); this.pushItemsOut( this.iHost.getTargets() );
} }
if (hasItemsToSendFacing()) if( hasItemsToSendFacing() )
{ {
for( EnumFacing enumFacing : waitingToSendFacing.keySet() ) for( EnumFacing enumFacing : waitingToSendFacing.keySet() )
{ {
@@ -732,7 +736,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final World w = tile.getWorld(); final World w = tile.getWorld();
final Iterator<ItemStack> i = this.waitingToSend.iterator(); final Iterator<ItemStack> i = this.waitingToSend.iterator();
while( i.hasNext() ) while ( i.hasNext() )
{ {
ItemStack whatToSend = i.next(); ItemStack whatToSend = i.next();
@@ -779,8 +783,8 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private void pushItemsOut( final EnumFacing s ) private void pushItemsOut( final EnumFacing s )
{ {
if (!this.waitingToSendFacing.containsKey(s) || if( !this.waitingToSendFacing.containsKey( s ) || ( this.waitingToSendFacing.containsKey( s ) && this.waitingToSendFacing.get( s ).isEmpty() ) )
(this.waitingToSendFacing.containsKey(s) && this.waitingToSendFacing.get( s ).isEmpty())) { {
return; return;
} }
@@ -793,17 +797,77 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return; return;
} }
if( te instanceof IInterfaceHost || ( te instanceof TileCableBus && ( (TileCableBus) te ).getPart( s.getOpposite() ) instanceof PartInterface ) )
{
try
{
IInterfaceHost targetTE;
if( te instanceof IInterfaceHost )
{
targetTE = (IInterfaceHost) te;
}
else
{
targetTE = (IInterfaceHost) ( (TileCableBus) te ).getPart( s.getOpposite() );
}
if( !targetTE.getInterfaceDuality().sameGrid( this.gridProxy.getGrid() ) )
{
IStorageMonitorableAccessor mon = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, s.getOpposite() );
if( mon != null )
{
IStorageMonitorable sm = mon.getInventory( this.mySource );
if( sm != null && Platform.canAccess( targetTE.getInterfaceDuality().gridProxy, this.mySource ) )
{
IMEMonitor<IAEItemStack> inv = sm.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
if( inv != null )
{
final Iterator<ItemStack> i = this.waitingToSendFacing.get( s ).iterator();
while ( i.hasNext() )
{
ItemStack whatToSend = i.next();
final IAEItemStack result = inv.injectItems( AEItemStack.fromItemStack( whatToSend ), Actionable.MODULATE, this.mySource );
if( result != null )
{
whatToSend.setCount( (int) result.getStackSize() );
}
else
{
i.remove();
}
}
if( this.waitingToSendFacing.get( s ).isEmpty() )
{
this.waitingToSendFacing.remove( s );
}
}
}
}
}
else
{
return;
}
}
catch( GridAccessException e )
{
throw new RuntimeException( e );
}
return;
}
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
final Iterator<ItemStack> i = this.waitingToSendFacing.get( s ).iterator(); final Iterator<ItemStack> i = this.waitingToSendFacing.get( s ).iterator();
while ( i.hasNext() ) while ( i.hasNext() )
{ {
ItemStack whatToSend = i.next(); ItemStack whatToSend = i.next();
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( ad != null ) if( ad != null )
{ {
final ItemStack result = ad.addItems( whatToSend ); final ItemStack result = ad.addItems( whatToSend );
if( !result.isEmpty() ) if( !result.isEmpty() )
{ {
whatToSend.setCount( whatToSend.getCount() - ( whatToSend.getCount() - result.getCount() ) ); whatToSend.setCount( result.getCount() );
} }
else else
{ {
@@ -844,42 +908,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
this.destination = this.gridProxy.getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ); this.destination = this.gridProxy.getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
final IEnergySource src = this.gridProxy.getEnergy(); final IEnergySource src = this.gridProxy.getEnergy();
if( this.craftingTracker.isBusy( x ) ) if( itemStack.getStackSize() < 0 )
{
changed = this.handleCrafting( x, adaptor, itemStack ) || changed;
}
else if( itemStack.getStackSize() > 0 )
{
// make sure strange things didn't happen...
if( !adaptor.simulateAdd( itemStack.createItemStack() ).isEmpty() )
{
changed = true;
throw new GridAccessException();
}
IAEItemStack storedStack = this.gridProxy.getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findPrecise( itemStack );
if( storedStack != null )
{
if( storedStack.getStackSize() > 0 )
{
final IAEItemStack acquired = Platform.poweredExtraction( src, this.destination, itemStack, this.interfaceRequestSource );
if( acquired != null )
{
changed = true;
final ItemStack issue = adaptor.addItems( acquired.createItemStack() );
if( !issue.isEmpty() )
{
throw new IllegalStateException( "bad attempt at managing inventory. ( addItems )" );
}
}
}
else if( storedStack.isCraftable() )
{
changed = this.handleCrafting( x, adaptor, itemStack ) || changed;
}
}
}
else if( itemStack.getStackSize() < 0 )
{ {
IAEItemStack toStore = itemStack.copy(); IAEItemStack toStore = itemStack.copy();
toStore.setStackSize( -toStore.getStackSize() ); toStore.setStackSize( -toStore.getStackSize() );
@@ -917,6 +946,51 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
} }
if( this.craftingTracker.isBusy( x ) )
{
changed = this.handleCrafting( x, adaptor, itemStack ) || changed;
}
else if( itemStack.getStackSize() > 0 )
{
// make sure strange things didn't happen...
ItemStack inputStack = itemStack.getCachedItemStack( itemStack.getStackSize() );
ItemStack remaining = adaptor.simulateAdd( inputStack );
if( !remaining.isEmpty() )
{
itemStack.setCachedItemStack( remaining );
changed = true;
throw new GridAccessException();
}
IAEItemStack storedStack = this.gridProxy.getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().findPrecise( itemStack );
if( storedStack != null )
{
final IAEItemStack acquired = Platform.poweredExtraction( src, this.destination, itemStack, this.interfaceRequestSource );
if( acquired != null )
{
changed = true;
inputStack.setCount( Ints.saturatedCast( acquired.getStackSize() ) );
final ItemStack issue = adaptor.addItems( inputStack );
if( !issue.isEmpty() )
{
throw new IllegalStateException( "bad attempt at managing inventory. ( addItems )" );
}
}
else if( storedStack.isCraftable() )
{
itemStack.setCachedItemStack( inputStack );
changed = this.handleCrafting( x, adaptor, itemStack ) || changed;
}
if( acquired == null )
{
itemStack.setCachedItemStack( inputStack );
}
}
}
// else wtf? // else wtf?
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
@@ -944,17 +1018,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
{ {
if( this.getInstalledUpgrades( Upgrades.CRAFTING ) > 0 && itemStack != null ) if( this.getInstalledUpgrades( Upgrades.CRAFTING ) > 0 && itemStack != null )
{ {
if (this.failedCraftTriesSlot[x] <= 0) return this.craftingTracker.handleCrafting( x, itemStack.getStackSize(), itemStack, d, this.iHost.getTileEntity().getWorld(), this.gridProxy.getGrid(), this.gridProxy.getCrafting(), this.mySource );
{
boolean crafted = this.craftingTracker.handleCrafting( x, itemStack.getStackSize(), itemStack, d, this.iHost.getTileEntity().getWorld(),
this.gridProxy.getGrid(), this.gridProxy.getCrafting(), this.mySource );
if (crafted) this.failedCraftTriesSlot[x] = 0;
else{
this.failedCraftTriesSlot[x] += 2;
}
}
this.failedCraftTriesSlot[x] -= 1;
} }
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
@@ -1094,12 +1158,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
private boolean invIsBlocked( InventoryAdaptor inv ) private boolean invIsBlocked( InventoryAdaptor inv )
{ {
return (inv.containsItems()); return ( inv.containsItems() );
}
private static boolean invIsBlockedGTCE( GTCEInventoryAdaptor inv )
{
return ( !inv.canRemoveAllExceptCircuits() );
} }
@Override @Override
@@ -1121,20 +1180,73 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
for( final EnumFacing s : visitedFaces ) for( final EnumFacing s : visitedFaces )
{ {
final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) ); final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) );
if( te instanceof IInterfaceHost ) if( te instanceof IInterfaceHost || ( te instanceof TileCableBus && ( (TileCableBus) te ).getPart( s.getOpposite() ) instanceof PartInterface ) )
{ {
visitedFaces.remove( s );
try try
{ {
if( ( (IInterfaceHost) te ).getInterfaceDuality().sameGrid( this.gridProxy.getGrid() ) ) IInterfaceHost targetTE;
if( te instanceof IInterfaceHost )
{
targetTE = (IInterfaceHost) te;
}
else
{
targetTE = (IInterfaceHost) ( (TileCableBus) te ).getPart( s.getOpposite() );
}
if( targetTE.getInterfaceDuality().sameGrid( this.gridProxy.getGrid() ) )
{ {
visitedFaces.remove( s );
continue; continue;
} }
else
{
IStorageMonitorableAccessor mon = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, s.getOpposite() );
if( mon != null )
{
IStorageMonitorable sm = mon.getInventory( this.mySource );
if( sm != null && Platform.canAccess( targetTE.getInterfaceDuality().gridProxy, this.mySource ) )
{
if( this.isBlocking() && sm.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().size() > 0 )
{
continue;
}
else
{
IMEMonitor<IAEItemStack> inv = sm.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
for( int x = 0; x < table.getSizeInventory(); x++ )
{
final ItemStack is = table.getStackInSlot( x );
if( is.isEmpty() )
{
continue;
}
IAEItemStack result = inv.injectItems( AEItemStack.fromItemStack( is ), Actionable.SIMULATE, this.mySource );
if( result != null )
{
return false;
}
}
for( int x = 0; x < table.getSizeInventory(); x++ )
{
final ItemStack is = table.getStackInSlot( x );
if( !is.isEmpty() )
{
addToSendListFacing( is, s );
}
}
pushItemsOut( s );
return true;
}
}
}
}
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
{ {
continue; continue;
} }
continue;
} }
if( te instanceof ICraftingMachine ) if( te instanceof ICraftingMachine )
@@ -1151,35 +1263,36 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() ); InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( ad != null ) if( ad != null )
{ {
if( this.isBlocking() ) if( this.isBlocking() )
{ {
IPhantomTile phantomTE = null; IPhantomTile phantomTE;
if( Loader.isModLoaded( "actuallyadditions" ) && Loader.isModLoaded( "gregtech" ) && te instanceof IPhantomTile ) if( Loader.isModLoaded( "actuallyadditions" ) && te instanceof IPhantomTile )
{ {
phantomTE = ( (IPhantomTile) te ); phantomTE = ( (IPhantomTile) te );
if( phantomTE.hasBoundPosition() ) if( phantomTE.hasBoundPosition() )
{ {
TileEntity phantom = w.getTileEntity( phantomTE.getBoundPosition() ); TileEntity phantom = w.getTileEntity( phantomTE.getBoundPosition() );
if( phantom instanceof MetaTileEntityHolder && isGTCEblocked( phantom, s ) ) if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( phantomTE.getBoundPosition() ).getBlock().getRegistryName().getResourceDomain() ) )
{ {
visitedFaces.remove( s ); if( isCustomInvBlocking( phantom, s ) )
continue; {
visitedFaces.remove( s );
continue;
}
} }
} }
} }
else if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( tile.getPos().offset( s ) ).getBlock().getRegistryName().getResourceDomain() ) )
else if( Loader.isModLoaded( "gregtech" ) && te instanceof MetaTileEntityHolder )
{ {
if( isGTCEblocked( te, s ) ) if( isCustomInvBlocking( te, s ) )
{ {
visitedFaces.remove( s ); visitedFaces.remove( s );
continue; continue;
} }
} }
else if( invIsBlocked( ad ) ) else if( invIsBlocked( ad ) )
{ {
visitedFaces.remove( s ); visitedFaces.remove( s );
@@ -1228,38 +1341,83 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
for( final EnumFacing s : possibleDirections ) for( final EnumFacing s : possibleDirections )
{ {
final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) ); final TileEntity te = w.getTileEntity( tile.getPos().offset( s ) );
IPhantomTile phantomTE = null;
if( te instanceof IInterfaceHost || ( te instanceof TileCableBus && ( (TileCableBus) te ).getPart( s.getOpposite() ) instanceof PartInterface ) )
{
try
{
IInterfaceHost targetTE;
if( te instanceof IInterfaceHost )
{
targetTE = (IInterfaceHost) te;
}
else
{
targetTE = (IInterfaceHost) ( (TileCableBus) te ).getPart( s.getOpposite() );
}
if( targetTE.getInterfaceDuality().sameGrid( this.gridProxy.getGrid() ) )
{
continue;
}
else
{
IStorageMonitorableAccessor mon = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, s.getOpposite() );
if( mon != null )
{
IStorageMonitorable sm = mon.getInventory( this.mySource );
if( sm != null && Platform.canAccess( targetTE.getInterfaceDuality().gridProxy, this.mySource ) )
{
if( sm.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ).getStorageList().isEmpty() )
{
allAreBusy = false;
break;
}
}
}
}
}
catch( final GridAccessException e )
{
continue;
}
continue;
}
final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() ); final InventoryAdaptor ad = InventoryAdaptor.getAdaptor( te, s.getOpposite() );
if( ad != null ) if( ad != null )
{ {
if( Loader.isModLoaded( "actuallyadditions") && Loader.isModLoaded( "gregtech" ) && te instanceof IPhantomTile ) if( Loader.isModLoaded( "actuallyadditions" ) && Loader.isModLoaded( "gregtech" ) && te instanceof IPhantomTile )
{ {
phantomTE = ( (IPhantomTile) te ); IPhantomTile phantomTE = ( (IPhantomTile) te );
if( phantomTE.hasBoundPosition() ) if( phantomTE.hasBoundPosition() )
{ {
TileEntity phantom = w.getTileEntity( phantomTE.getBoundPosition() ); TileEntity phantom = w.getTileEntity( phantomTE.getBoundPosition() );
if( phantom instanceof MetaTileEntityHolder && !isGTCEblocked( phantom, s ) ) if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( phantomTE.getBoundPosition() ).getBlock().getRegistryName().getResourceDomain() ) )
{ {
allAreBusy = false; if( !isCustomInvBlocking( phantom, s ) )
break; {
allAreBusy = false;
break;
}
} }
} }
} }
else if( NonBlockingItems.INSTANCE.getMap().containsKey( w.getBlockState( tile.getPos().offset( s ) ).getBlock().getRegistryName().getResourceDomain() ) )
else if( Loader.isModLoaded( "gregtech" ) && te instanceof MetaTileEntityHolder )
{ {
if( !isGTCEblocked( te, s ) ) if( !isCustomInvBlocking( te, s ) )
{ {
allAreBusy = false; allAreBusy = false;
break; break;
} }
} }
else
else if( !invIsBlocked( ad ) )
{ {
allAreBusy = false; if( !invIsBlocked( ad ) )
break; {
allAreBusy = false;
break;
}
} }
} }
} }
@@ -1268,10 +1426,10 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
return busy; return busy;
} }
boolean isGTCEblocked(TileEntity te, EnumFacing s) boolean isCustomInvBlocking( TileEntity te, EnumFacing s )
{ {
GTad = GTCEInventoryAdaptor.getAdaptor( te, s.getOpposite() ); BlockingInventoryAdaptor blockingInventoryAdaptor = BlockingInventoryAdaptor.getAdaptor( te, s.getOpposite() );
return invIsBlockedGTCE( GTad ); return invIsCustomBlocking( blockingInventoryAdaptor );
} }
private boolean sameGrid( final IGrid grid ) throws GridAccessException private boolean sameGrid( final IGrid grid ) throws GridAccessException
@@ -1294,7 +1452,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
continue; continue;
} }
if( !ad.simulateAdd( is.copy() ).isEmpty() ) if( !ad.simulateAdd( is ).isEmpty() )
{ {
return false; return false;
} }
@@ -1331,13 +1489,13 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( this.waitingToSendFacing != null ) if( this.waitingToSendFacing != null )
{ {
for (List<ItemStack> itemList : waitingToSendFacing.values()) for( List<ItemStack> itemList : waitingToSendFacing.values() )
{ {
for (final ItemStack is : itemList) for( final ItemStack is : itemList )
{ {
if (!is.isEmpty()) if( !is.isEmpty() )
{ {
drops.add(is); drops.add( is );
} }
} }
} }
@@ -1467,10 +1625,13 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
final Block directedBlock = directedBlockState.getBlock(); final Block directedBlock = directedBlockState.getBlock();
ItemStack what = new ItemStack( directedBlock, 1, directedBlock.getMetaFromState( directedBlockState ) ); ItemStack what = new ItemStack( directedBlock, 1, directedBlock.getMetaFromState( directedBlockState ) );
if ( Loader.isModLoaded("gregtech") && directedBlock instanceof BlockMachine ) if( Loader.isModLoaded( "gregtech" ) && directedBlock instanceof BlockMachine )
{ {
MetaTileEntity metaTileEntity = getMetaTileEntity(hostWorld, targ); MetaTileEntity metaTileEntity = Platform.getMetaTileEntity( directedTile.getWorld(), directedTile.getPos() );
return metaTileEntity.getMetaFullName(); if( metaTileEntity != null )
{
return metaTileEntity.getMetaFullName();
}
} }
try try
@@ -1498,7 +1659,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
if( what.getItem() != Items.AIR ) if( what.getItem() != Items.AIR )
{ {
return what.getUnlocalizedName(); return what.getItem().getItemStackDisplayName( what );
} }
final Item item = Item.getItemFromBlock( directedBlock ); final Item item = Item.getItemFromBlock( directedBlock );
@@ -1585,6 +1746,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
private class InterfaceRequestContext implements Comparable<Integer> private class InterfaceRequestContext implements Comparable<Integer>
{ {
@@ -1595,6 +1757,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
private class InterfaceInventory extends MEMonitorIInventory private class InterfaceInventory extends MEMonitorIInventory
{ {
@@ -1632,6 +1795,7 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
} }
} }
private class Accessor implements IStorageMonitorableAccessor private class Accessor implements IStorageMonitorableAccessor
{ {
@@ -24,6 +24,7 @@ import java.util.concurrent.Future;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -83,57 +84,70 @@ public class MultiCraftingTracker
public boolean handleCrafting( final int x, final long itemToCraft, final IAEItemStack ais, final InventoryAdaptor d, final World w, final IGrid g, final ICraftingGrid cg, final IActionSource mySrc ) public boolean handleCrafting( final int x, final long itemToCraft, final IAEItemStack ais, final InventoryAdaptor d, final World w, final IGrid g, final ICraftingGrid cg, final IActionSource mySrc )
{ {
if( ais != null && d.simulateAdd( ais.createItemStack() ).isEmpty() ) if( ais != null )
{ {
final Future<ICraftingJob> craftingJob = this.getJob( x ); ItemStack inputStack = ais.getCachedItemStack( ais.getStackSize() );
if( this.getLink( x ) != null ) ItemStack remaining = d.simulateAdd( inputStack );
{
return false;
}
else if( craftingJob != null )
{
try if( remaining.isEmpty() )
{
ais.setCachedItemStack( inputStack );
final Future<ICraftingJob> craftingJob = this.getJob( x );
if( this.getLink( x ) != null )
{ {
ICraftingJob job = null; return false;
if( craftingJob.isDone() ) }
else if( craftingJob != null )
{
try
{ {
job = craftingJob.get(); ICraftingJob job = null;
} if( craftingJob.isDone() )
if( job != null )
{
final ICraftingLink link = cg.submitJob( job, this.owner, null, false, mySrc );
this.setJob( x, null );
if( link != null )
{ {
this.setLink( x, link ); job = craftingJob.get();
}
return true; if( job != null )
{
final ICraftingLink link = cg.submitJob( job, this.owner, null, false, mySrc );
this.setJob( x, null );
if( link != null )
{
this.setLink( x, link );
return true;
}
} }
} }
catch( final InterruptedException e )
{
// :P
}
catch( final ExecutionException e )
{
// :P
}
} }
catch( final InterruptedException e ) else
{ {
// :P if( this.getLink( x ) == null )
} {
catch( final ExecutionException e ) final IAEItemStack aisC = ais.copy();
{ aisC.setStackSize( itemToCraft );
// :P
this.setJob( x, cg.beginCraftingJob( w, g, mySrc, aisC, null ) );
}
} }
} }
else else
{ {
if( this.getLink( x ) == null ) ais.setCachedItemStack( remaining );
{
final IAEItemStack aisC = ais.copy();
aisC.setStackSize( itemToCraft );
this.setJob( x, cg.beginCraftingJob( w, g, mySrc, aisC, null ) );
}
} }
} }
return false; return false;
@@ -0,0 +1,133 @@
package appeng.helpers;
import appeng.core.AEConfig;
import appeng.core.AELog;
import appeng.util.Platform;
import gregtech.api.items.metaitem.MetaItem;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.*;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.oredict.OreDictionary;
import java.util.*;
public class NonBlockingItems
{
public static Map<String, Object2ObjectOpenHashMap<Item, IntSet>> NON_BLOCKING_MAP = new HashMap<>();
public static NonBlockingItems INSTANCE = new NonBlockingItems();
private NonBlockingItems()
{
String[] strings = AEConfig.instance().getNonBlockingItems();
String[] modids = new String[0];
if( strings.length > 0 )
{
for( String s : strings )
{
if( s.startsWith( "[" ) && s.endsWith( "]" ) )
{
modids = s.substring( 1, s.length() - 1 ).split( "\\|" );
}
else
{
for( String modid : modids )
{
if( !Loader.isModLoaded( modid ) )
{
continue;
}
NON_BLOCKING_MAP.putIfAbsent( modid, new Object2ObjectOpenHashMap<>() );
String[] ModItemMeta = s.split( ":" );
if( ModItemMeta.length < 2 || ModItemMeta.length > 3 )
{
AELog.error( "Invalid non blocking item entry: " + s );
continue;
}
if( ModItemMeta[0].equals( "gregtech" ) && Platform.isModLoaded( "gregtech" ) )
{
boolean found = false;
for( MetaItem<?> metaItem : MetaItem.getMetaItems() )
{
MetaItem<?>.MetaValueItem metaItem2 = metaItem.getItem( ModItemMeta[1] );
if( metaItem.getItem( ModItemMeta[1] ) != null )
{
found = true;
ItemStack itemStack = metaItem2.getStackForm();
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
}
else
{
ItemStack itemStack = GameRegistry.makeItemStack( ModItemMeta[0] + ":" + ModItemMeta[1], ModItemMeta.length == 3 ? Integer.parseInt( ModItemMeta[2] ) : 0, 1, null );
if( !itemStack.isEmpty() )
{
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
}
}
}
if( !found )
{
AELog.error( "Item not found on nonBlocking config: " + s );
}
}
else if( ModItemMeta[0].equals( "ore" ) )
{
OreDictionary.getOres( ModItemMeta[1] ).forEach( itemStack ->
{
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
} );
}
else
{
ItemStack itemStack = GameRegistry.makeItemStack( ModItemMeta[0] + ":" + ModItemMeta[1], ModItemMeta.length == 3 ? Integer.parseInt( ModItemMeta[2] ) : 0, 1, null );
if( !itemStack.isEmpty() )
{
NON_BLOCKING_MAP.get( modid ).putIfAbsent( itemStack.getItem(), new IntOpenHashSet() );
NON_BLOCKING_MAP.get( modid ).computeIfPresent( itemStack.getItem(), ( item, intSet ) ->
{
intSet.add( itemStack.getItemDamage() );
return intSet;
} );
}
else
{
AELog.error( "Item not found on nonBlocking config: " + s );
}
}
}
}
}
}
}
public Map<String, Object2ObjectOpenHashMap<Item, IntSet>> getMap()
{
return NON_BLOCKING_MAP;
}
public void init()
{
}
}
+53 -31
View File
@@ -40,6 +40,7 @@ import appeng.container.ContainerNull;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.AEItemStack; import appeng.util.item.AEItemStack;
import net.minecraftforge.common.crafting.IShapedRecipe; import net.minecraftforge.common.crafting.IShapedRecipe;
import net.minecraftforge.fml.common.Optional;
public class PatternHelper implements ICraftingPatternDetails, Comparable<PatternHelper> public class PatternHelper implements ICraftingPatternDetails, Comparable<PatternHelper>
@@ -247,7 +248,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
final TestStatus result = this.getStatus( slotIndex, i ); final TestStatus result = this.getStatus( slotIndex, i );
switch( result ) switch ( result )
{ {
case ACCEPT: case ACCEPT:
return true; return true;
@@ -266,9 +267,11 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
this.testFrame.setInventorySlotContents( slotIndex, i ); this.testFrame.setInventorySlotContents( slotIndex, i );
// If we cannot substitute, the items must match exactly // If we cannot substitute, the items must match exactly
if (!canSubstitute && slotIndex < inputs.length) { if( ( !( i.getItem().isDamageable() || Platform.isGTDamageableItem( i.getItem() ) ) && !canSubstitute ) && slotIndex < inputs.length )
if (!inputs[slotIndex].isSameType(i)) { {
this.markItemAs(slotIndex, i, TestStatus.DECLINE); if( !inputs[slotIndex].isSameType( i ) )
{
this.markItemAs( slotIndex, i, TestStatus.DECLINE );
return false; return false;
} }
} }
@@ -326,23 +329,26 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
} }
@Override @Override
public List<IAEItemStack> getSubstituteInputs(int slot) { public List<IAEItemStack> getSubstituteInputs( int slot )
if (this.inputs[slot] == null) { {
if( this.inputs[slot] == null )
{
return Collections.emptyList(); return Collections.emptyList();
} }
return this.substituteInputs.computeIfAbsent(slot, value -> { return this.substituteInputs.computeIfAbsent( slot, value -> {
ItemStack[] matchingStacks = getRecipeIngredient(slot).getMatchingStacks(); ItemStack[] matchingStacks = getRecipeIngredient( slot ).getMatchingStacks();
List<IAEItemStack> itemList = new ArrayList<>(matchingStacks.length + 1); List<IAEItemStack> itemList = new ArrayList<>( matchingStacks.length + 1 );
for (ItemStack matchingStack : matchingStacks) { for( ItemStack matchingStack : matchingStacks )
itemList.add(AEItemStack.fromItemStack(matchingStack)); {
itemList.add( AEItemStack.fromItemStack( matchingStack ) );
} }
// Ensure that the specific item put in by the user is at the beginning, // Ensure that the specific item put in by the user is at the beginning,
// so that it takes precedence over substitutions // so that it takes precedence over substitutions
itemList.add(0, this.inputs[slot]); itemList.add( 0, this.inputs[slot] );
return itemList; return itemList;
}); } );
} }
/** /**
@@ -352,31 +358,40 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
* ingredient list will be condensed to the actual recipe's grid size. In addition, in our 3x3 grid, the user can * ingredient list will be condensed to the actual recipe's grid size. In addition, in our 3x3 grid, the user can
* shift the actual recipe input to the right and down. * shift the actual recipe input to the right and down.
*/ */
private Ingredient getRecipeIngredient(int slot) { private Ingredient getRecipeIngredient( int slot )
{
if (standardRecipe instanceof IShapedRecipe ) { if( standardRecipe instanceof IShapedRecipe )
{
IShapedRecipe shapedRecipe = (IShapedRecipe) standardRecipe; IShapedRecipe shapedRecipe = (IShapedRecipe) standardRecipe;
return getShapedRecipeIngredient(slot, shapedRecipe.getRecipeWidth()); return getShapedRecipeIngredient( slot, shapedRecipe.getRecipeWidth() );
} else { }
return getShapelessRecipeIngredient(slot); else
{
return getShapelessRecipeIngredient( slot );
} }
} }
private Ingredient getShapedRecipeIngredient(int slot, int recipeWidth) { private Ingredient getShapedRecipeIngredient( int slot, int recipeWidth )
{
// Compute the offset of the user's input vs. crafting grid origin // Compute the offset of the user's input vs. crafting grid origin
// Which is >0 if they have empty rows above or to the left of their input // Which is >0 if they have empty rows above or to the left of their input
int topOffset = 0; int topOffset = 0;
if (inputs[0] == null && inputs[1] == null && inputs[2] == null) { if( inputs[0] == null && inputs[1] == null && inputs[2] == null )
{
topOffset++; // First row is fully empty topOffset++; // First row is fully empty
if (inputs[3] == null && inputs[4] == null && inputs[5] == null) { if( inputs[3] == null && inputs[4] == null && inputs[5] == null )
{
topOffset++; // Second row is fully empty topOffset++; // Second row is fully empty
} }
} }
int leftOffset = 0; int leftOffset = 0;
if (inputs[0] == null && inputs[3] == null && inputs[6] == null) { if( inputs[0] == null && inputs[3] == null && inputs[6] == null )
{
leftOffset++; // First column is fully empty leftOffset++; // First column is fully empty
if (inputs[1] == null && inputs[4] == null && inputs[7] == null) { if( inputs[1] == null && inputs[4] == null && inputs[7] == null )
{
leftOffset++; // Second column is fully empty leftOffset++; // Second column is fully empty
} }
} }
@@ -390,27 +405,32 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
NonNullList<Ingredient> ingredients = standardRecipe.getIngredients(); NonNullList<Ingredient> ingredients = standardRecipe.getIngredients();
if (ingredientIndex < 0 || ingredientIndex > ingredients.size()) { if( ingredientIndex < 0 || ingredientIndex > ingredients.size() )
{
return Ingredient.EMPTY; return Ingredient.EMPTY;
} }
return ingredients.get(ingredientIndex); return ingredients.get( ingredientIndex );
} }
private Ingredient getShapelessRecipeIngredient(int slot) { private Ingredient getShapelessRecipeIngredient( int slot )
{
// We map the list of *filled* sparse inputs to the shapeless (ergo unordered) // We map the list of *filled* sparse inputs to the shapeless (ergo unordered)
// ingredients. While these do not actually correspond to each other, // ingredients. While these do not actually correspond to each other,
// since both lists have the same length, the mapping is at least stable. // since both lists have the same length, the mapping is at least stable.
int ingredientIndex = 0; int ingredientIndex = 0;
for (int i = 0; i < slot; i++) { for( int i = 0; i < slot; i++ )
if (inputs[i] != null) { {
if( inputs[i] != null )
{
ingredientIndex++; ingredientIndex++;
} }
} }
NonNullList<Ingredient> ingredients = standardRecipe.getIngredients(); NonNullList<Ingredient> ingredients = standardRecipe.getIngredients();
if (ingredientIndex < ingredients.size()) { if( ingredientIndex < ingredients.size() )
return ingredients.get(ingredientIndex); {
return ingredients.get( ingredientIndex );
} }
return Ingredient.EMPTY; return Ingredient.EMPTY;
@@ -517,7 +537,9 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
private enum TestStatus private enum TestStatus
{ {
ACCEPT, DECLINE, TEST ACCEPT,
DECLINE,
TEST
} }
private static final class TestLookup private static final class TestLookup
+7 -10
View File
@@ -190,10 +190,11 @@ public class TickHandler
synchronized ( this.craftingJobs ) synchronized ( this.craftingJobs )
{ {
final Collection<CraftingJob> jobSet = this.craftingJobs.get( wte.world ); final Collection<CraftingJob> jobSet = this.craftingJobs.get( wte.world );
if (!jobSet.isEmpty()) { if( !jobSet.isEmpty() )
{
final int jobSize = jobSet.size(); final int jobSize = jobSet.size();
final int microSecondsPerTick = AEConfig.instance().getCraftingCalculationTimePerTick() * 1000; final int microSecondsPerTick = AEConfig.instance().getCraftingCalculationTimePerTick() * 1000;
final int simTime = Math.max(1, microSecondsPerTick / jobSize); final int simTime = Math.max( 1, microSecondsPerTick / jobSize );
jobSet.removeIf( cj -> !cj.simulateFor( simTime ) ); jobSet.removeIf( cj -> !cj.simulateFor( simTime ) );
} }
@@ -206,7 +207,7 @@ public class TickHandler
this.tickColors( this.srvPlayerColors ); this.tickColors( this.srvPlayerColors );
// ready tiles. // ready tiles.
final HandlerRep repo = this.getRepo(); final HandlerRep repo = this.getRepo();
while( !repo.tiles.isEmpty() ) while ( !repo.tiles.isEmpty() )
{ {
final AEBaseTile bt = repo.tiles.poll(); final AEBaseTile bt = repo.tiles.poll();
if( !bt.isInvalid() ) if( !bt.isInvalid() )
@@ -238,7 +239,7 @@ public class TickHandler
private void tickColors( final HashMap<Integer, PlayerColor> playerSet ) private void tickColors( final HashMap<Integer, PlayerColor> playerSet )
{ {
final Iterator<PlayerColor> i = playerSet.values().iterator(); final Iterator<PlayerColor> i = playerSet.values().iterator();
while( i.hasNext() ) while ( i.hasNext() )
{ {
final PlayerColor pc = i.next(); final PlayerColor pc = i.next();
if( pc.ticksLeft <= 0 ) if( pc.ticksLeft <= 0 )
@@ -259,7 +260,7 @@ public class TickHandler
final Stopwatch sw = Stopwatch.createStarted(); final Stopwatch sw = Stopwatch.createStarted();
IWorldCallable<?> c = null; IWorldCallable<?> c = null;
while( ( c = queue.poll() ) != null ) while ( ( c = queue.poll() ) != null )
{ {
try try
{ {
@@ -275,15 +276,11 @@ public class TickHandler
AELog.debug( e ); AELog.debug( e );
} }
} }
// long time = sw.elapsed( TimeUnit.MILLISECONDS );
// if ( time > 0 )
// AELog.info( "processQueue Time: " + time + "ms" );
} }
public void registerCraftingSimulation( final World world, final CraftingJob craftingJob ) public void registerCraftingSimulation( final World world, final CraftingJob craftingJob )
{ {
synchronized( this.craftingJobs ) synchronized ( this.craftingJobs )
{ {
this.craftingJobs.put( world, craftingJob ); this.craftingJobs.put( world, craftingJob );
} }
@@ -30,35 +30,37 @@ import appeng.integration.modules.waila.WailaModule;
public enum IntegrationType public enum IntegrationType
{ {
IC2( IntegrationSide.BOTH, "Industrial Craft 2", "ic2" ) IC2( IntegrationSide.BOTH, "Industrial Craft 2", "ic2" )
{ {
@Override @Override
public IIntegrationModule createInstance() public IIntegrationModule createInstance()
{ {
return Integrations.setIc2( new IC2Module() ); return Integrations.setIc2( new IC2Module() );
} }
}, },
GTCE( IntegrationSide.BOTH, "GregTech", "gregtech" ),
RC( IntegrationSide.BOTH, "Railcraft", "railcraft" ), RC( IntegrationSide.BOTH, "Railcraft", "railcraft" ),
MFR( IntegrationSide.BOTH, "Mine Factory Reloaded", "minefactoryreloaded" ), MFR( IntegrationSide.BOTH, "Mine Factory Reloaded", "minefactoryreloaded" ),
Waila( IntegrationSide.BOTH, "Waila", "waila" ) Waila( IntegrationSide.BOTH, "Waila", "waila" )
{ {
@Override @Override
public IIntegrationModule createInstance() public IIntegrationModule createInstance()
{ {
return new WailaModule(); return new WailaModule();
} }
}, },
InvTweaks( IntegrationSide.CLIENT, "Inventory Tweaks", "inventorytweaks" ) InvTweaks( IntegrationSide.CLIENT, "Inventory Tweaks", "inventorytweaks" )
{ {
@Override @Override
public IIntegrationModule createInstance() public IIntegrationModule createInstance()
{ {
return Integrations.setInvTweaks( new InventoryTweaksModule() ); return Integrations.setInvTweaks( new InventoryTweaksModule() );
} }
}, },
JEI( IntegrationSide.CLIENT, "Just Enough Items", "jei" ) JEI( IntegrationSide.CLIENT, "Just Enough Items", "jei" )
{ {
@@ -1,26 +0,0 @@
package appeng.integration.modules.gregtech;
import appeng.util.inv.ItemSlot;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public abstract class GTCEInventoryAdaptor implements Iterable<ItemSlot>
{
public static GTCEInventoryAdaptor getAdaptor(final TileEntity te, final EnumFacing d)
{
if (te != null && te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, d))
{
// Attempt getting an IItemHandler for the given side via caps
IItemHandler itemHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, d);
if (itemHandler != null)
{
return new GTCEItemHandler(itemHandler);
}
}
return null;
}
public abstract boolean canRemoveAllExceptCircuits();
}
@@ -1,58 +0,0 @@
package appeng.integration.modules.gregtech;
import appeng.util.inv.ItemHandlerIterator;
import appeng.util.inv.ItemSlot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
public class GTCEItemHandler extends GTCEInventoryAdaptor
{
ArrayList<Integer> GTCElenses = new ArrayList<>(Arrays.asList(15085,15214,15092,15111,15113,15219,15218,15243,15244,15209,15117,15206,15216,15331,15212,15213,15154,15122,15157,15190,15247));
ArrayList<Integer> GTCEmolds = new ArrayList<>(Arrays.asList(32301,32303,32304,32305,32306,32307,32308,32309,32313,32314,32315,32317,32350,32351,32352,32353,32354,32355,32356,32358,32359,32360,32361,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373));
Item smallGearExtruderShape = Item.getByNameOrId("contenttweaker:smallgearextrudershape");
Item creativePortableTankMold = Item.getByNameOrId("contenttweaker:creativeportabletankmold");
protected final IItemHandler itemHandler;
public GTCEItemHandler(IItemHandler itemHandler)
{
this.itemHandler = itemHandler;
}
boolean isBlockableItem(ItemStack stack)
{
if ( stack.getItem() == Item.getByNameOrId("gregtech:meta_item_1") ) {
int metadata = stack.getItemDamage();
if ( metadata == 32766 || GTCElenses.contains(metadata) || GTCEmolds.contains(metadata)) {
return false;
}
}
if ( stack.getItem() == smallGearExtruderShape ) return false;
if ( stack.getItem() == creativePortableTankMold) return false;
return true;
}
@Override
public boolean canRemoveAllExceptCircuits()
{
int slots = this.itemHandler.getSlots();
for ( int slot = 0; slot < slots; slot++ ) {
ItemStack is = this.itemHandler.getStackInSlot(slot);
if ( is.isEmpty() || !isBlockableItem(is) ) continue;
return false;
}
return true;
}
@Override
public Iterator<ItemSlot> iterator()
{
return new ItemHandlerIterator( this.itemHandler );
}
}
+93 -104
View File
@@ -29,6 +29,7 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import appeng.parts.misc.*; import appeng.parts.misc.*;
import appeng.parts.p2p.*;
import appeng.parts.reporting.*; import appeng.parts.reporting.*;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@@ -65,13 +66,6 @@ import appeng.parts.networking.PartCableSmart;
import appeng.parts.networking.PartDenseCableCovered; import appeng.parts.networking.PartDenseCableCovered;
import appeng.parts.networking.PartDenseCableSmart; import appeng.parts.networking.PartDenseCableSmart;
import appeng.parts.networking.PartQuartzFiber; import appeng.parts.networking.PartQuartzFiber;
import appeng.parts.p2p.PartP2PFEPower;
import appeng.parts.p2p.PartP2PFluids;
import appeng.parts.p2p.PartP2PIC2Power;
import appeng.parts.p2p.PartP2PItems;
import appeng.parts.p2p.PartP2PLight;
import appeng.parts.p2p.PartP2PRedstone;
import appeng.parts.p2p.PartP2PTunnelME;
import appeng.util.Platform; import appeng.util.Platform;
@@ -80,96 +74,84 @@ public enum PartType
INVALID_TYPE( -1, "invalid", EnumSet.of( AEFeature.CORE ), EnumSet.noneOf( IntegrationType.class ), null ), INVALID_TYPE( -1, "invalid", EnumSet.of( AEFeature.CORE ), EnumSet.noneOf( IntegrationType.class ), null ),
CABLE_GLASS( 0, "cable_glass", EnumSet.of( AEFeature.GLASS_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableGlass.class ) CABLE_GLASS( 0, "cable_glass", EnumSet.of( AEFeature.GLASS_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableGlass.class )
{ {
@Override @Override
public boolean isCable() public boolean isCable()
{ {
return true; return true;
} }
@Override @Override
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName ) protected List<ModelResourceLocation> createItemModels( String baseName )
{ {
return Arrays.stream( AEColor.values() ) return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ) }
.collect( Collectors.toList() ); },
}
},
CABLE_COVERED( 20, "cable_covered", EnumSet.of( AEFeature.COVERED_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableCovered.class ) CABLE_COVERED( 20, "cable_covered", EnumSet.of( AEFeature.COVERED_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableCovered.class )
{ {
@Override @Override
public boolean isCable() public boolean isCable()
{ {
return true; return true;
} }
@Override @Override
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName ) protected List<ModelResourceLocation> createItemModels( String baseName )
{ {
return Arrays.stream( AEColor.values() ) return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ) }
.collect( Collectors.toList() ); },
}
},
CABLE_SMART( 40, "cable_smart", EnumSet.of( AEFeature.CHANNELS, AEFeature.SMART_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableSmart.class ) CABLE_SMART( 40, "cable_smart", EnumSet.of( AEFeature.SMART_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartCableSmart.class )
{ {
@Override @Override
public boolean isCable() public boolean isCable()
{ {
return true; return true;
} }
@Override @Override
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName ) protected List<ModelResourceLocation> createItemModels( String baseName )
{ {
return Arrays.stream( AEColor.values() ) return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ) }
.collect( Collectors.toList() ); },
}
},
CABLE_DENSE_SMART( 60, "cable_dense_smart", EnumSet.of( AEFeature.CHANNELS, AEFeature.DENSE_CABLES ), EnumSet CABLE_DENSE_SMART( 60, "cable_dense_smart", EnumSet.of( AEFeature.DENSE_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartDenseCableSmart.class )
.noneOf( IntegrationType.class ), PartDenseCableSmart.class ) {
{ @Override
@Override public boolean isCable()
public boolean isCable() {
{ return true;
return true; }
}
@Override @Override
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName ) protected List<ModelResourceLocation> createItemModels( String baseName )
{ {
return Arrays.stream( AEColor.values() ) return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ) }
.collect( Collectors.toList() ); },
}
},
CABLE_DENSE_COVERED( 500, "cable_dense_covered", EnumSet.of( AEFeature.CHANNELS, AEFeature.DENSE_CABLES ), EnumSet CABLE_DENSE_COVERED( 500, "cable_dense_covered", EnumSet.of( AEFeature.DENSE_CABLES ), EnumSet.noneOf( IntegrationType.class ), PartDenseCableCovered.class )
.noneOf( IntegrationType.class ), PartDenseCableCovered.class ) {
{ @Override
@Override public boolean isCable()
public boolean isCable() {
{ return true;
return true; }
}
@Override @Override
@SideOnly( Side.CLIENT ) @SideOnly( Side.CLIENT )
protected List<ModelResourceLocation> createItemModels( String baseName ) protected List<ModelResourceLocation> createItemModels( String baseName )
{ {
return Arrays.stream( AEColor.values() ) return Arrays.stream( AEColor.values() ).map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ).collect( Collectors.toList() );
.map( color -> modelFromBaseName( baseName + "_" + color.name().toLowerCase() ) ) }
.collect( Collectors.toList() ); },
}
},
TOGGLE_BUS( 80, "toggle_bus", EnumSet.of( AEFeature.TOGGLE_BUS ), EnumSet.noneOf( IntegrationType.class ), PartToggleBus.class ), TOGGLE_BUS( 80, "toggle_bus", EnumSet.of( AEFeature.TOGGLE_BUS ), EnumSet.noneOf( IntegrationType.class ), PartToggleBus.class ),
@@ -275,27 +257,35 @@ public enum PartType
@Override @Override
String getUnlocalizedName() String getUnlocalizedName()
{ {
return "p2p_tunnel"; return "p2p_tunnel";
} }
}, },
P2P_TUNNEL_FE( 469, "p2p_tunnel_fe", EnumSet.of( AEFeature.P2P_TUNNEL, AEFeature.P2P_TUNNEL_FE ), EnumSet P2P_TUNNEL_FE( 469, "p2p_tunnel_fe", EnumSet.of( AEFeature.P2P_TUNNEL, AEFeature.P2P_TUNNEL_FE ), EnumSet.noneOf( IntegrationType.class ), PartP2PFEPower.class, GuiText.FETunnel )
.noneOf( IntegrationType.class ), PartP2PFEPower.class, GuiText.FETunnel ) {
{ @Override
@Override String getUnlocalizedName()
String getUnlocalizedName() {
{ return "p2p_tunnel";
return "p2p_tunnel"; }
} },
},
P2P_TUNNEL_GTEU( 470, "p2p_tunnel_gteu", EnumSet.of( AEFeature.P2P_TUNNEL, AEFeature.P2P_TUNNEL_GTEU ), EnumSet.of( IntegrationType.GTCE ), PartP2PGTCEPower.class, GuiText.GTEUTunnel )
{
@Override
String getUnlocalizedName()
{
return "p2p_tunnel";
}
},
// P2PTunnelOpenComputers( 468, EnumSet.of( AEFeature.P2PTunnel, AEFeature.P2PTunnelOpenComputers ), EnumSet.of( // P2PTunnelOpenComputers( 468, EnumSet.of( AEFeature.P2PTunnel, AEFeature.P2PTunnelOpenComputers ), EnumSet.of(
// IntegrationType.OpenComputers ), PartP2POpenComputers.class, GuiText.OCTunnel ), // IntegrationType.OpenComputers ), PartP2POpenComputers.class, GuiText.OCTunnel ),
INTERFACE_TERMINAL( 480, "interface_terminal", EnumSet.of( AEFeature.INTERFACE_TERMINAL ), EnumSet INTERFACE_TERMINAL( 480, "interface_terminal", EnumSet.of( AEFeature.INTERFACE_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartInterfaceTerminal.class ),
.noneOf( IntegrationType.class ), PartInterfaceTerminal.class ),
FLUID_TERMINAL( 520, "fluid_terminal", EnumSet.of( AEFeature.FLUID_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartFluidTerminal.class ); FLUID_TERMINAL( 520, "fluid_terminal", EnumSet.of( AEFeature.FLUID_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartFluidTerminal.class ),
INTERFACE_CONFIGURATION_TERMINAL( 521, "interface_configuration_terminal", EnumSet.of( AEFeature.INTERFACE_TERMINAL ), EnumSet.noneOf( IntegrationType.class ), PartInterfaceConfigurationTerminal.class );
private final int baseDamage; private final int baseDamage;
private final Set<AEFeature> features; private final Set<AEFeature> features;
@@ -334,8 +324,7 @@ public enum PartType
this.oreName = oreDict; this.oreName = oreDict;
// The part is enabled if all features + integrations it needs are enabled // The part is enabled if all features + integrations it needs are enabled
this.enabled = features.stream().allMatch( AEConfig.instance()::isFeatureEnabled ) && integrations.stream() this.enabled = features.stream().allMatch( AEConfig.instance()::isFeatureEnabled ) && integrations.stream().allMatch( IntegrationRegistry.INSTANCE::isEnabled );
.allMatch( IntegrationRegistry.INSTANCE::isEnabled );
if( this.enabled ) if( this.enabled )
{ {
+1 -7
View File
@@ -19,12 +19,8 @@
package appeng.me; package appeng.me;
import java.util.Collection; import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.networking.IGrid; import appeng.api.networking.IGrid;
@@ -220,9 +216,7 @@ public class Grid implements IGrid
@Override @Override
public MENetworkEvent postEvent( final MENetworkEvent ev ) public MENetworkEvent postEvent( final MENetworkEvent ev )
{ {
CraftingGridCache.pauseRebuilds();
final MENetworkEvent ret = this.eventBus.postEvent( this, ev ); final MENetworkEvent ret = this.eventBus.postEvent( this, ev );
CraftingGridCache.unpauseRebuilds();
return ret; return ret;
} }
+6 -9
View File
@@ -65,7 +65,7 @@ import net.minecraftforge.common.util.Constants;
public class GridNode implements IGridNode, IPathItem public class GridNode implements IGridNode, IPathItem
{ {
private static final MENetworkChannelsChanged EVENT = new MENetworkChannelsChanged(); private static final MENetworkChannelsChanged EVENT = new MENetworkChannelsChanged();
private static final int[] CHANNEL_COUNT = { 0, 8, 32 }; private static final int[] CHANNEL_COUNT = {0, 8, 32};
private final List<IGridConnection> connections = new ArrayList<>(); private final List<IGridConnection> connections = new ArrayList<>();
private final IGridBlock gridProxy; private final IGridBlock gridProxy;
@@ -166,8 +166,6 @@ public class GridNode implements IGridNode, IPathItem
{ {
final Object tracker = new Object(); final Object tracker = new Object();
CraftingGridCache.pauseRebuilds();
Deque<GridNode> nextRun = new ArrayDeque<>(); Deque<GridNode> nextRun = new ArrayDeque<>();
nextRun.add( this ); nextRun.add( this );
@@ -178,9 +176,9 @@ public class GridNode implements IGridNode, IPathItem
final Deque<IGridConnection> nextConn = new ArrayDeque<>(); final Deque<IGridConnection> nextConn = new ArrayDeque<>();
final IGridConnectionVisitor gcv = (IGridConnectionVisitor) g; final IGridConnectionVisitor gcv = (IGridConnectionVisitor) g;
while( !nextRun.isEmpty() ) while ( !nextRun.isEmpty() )
{ {
while( !nextConn.isEmpty() ) while ( !nextConn.isEmpty() )
{ {
gcv.visitConnection( nextConn.poll() ); gcv.visitConnection( nextConn.poll() );
} }
@@ -196,7 +194,7 @@ public class GridNode implements IGridNode, IPathItem
} }
else else
{ {
while( !nextRun.isEmpty() ) while ( !nextRun.isEmpty() )
{ {
final Iterable<GridNode> thisRun = nextRun; final Iterable<GridNode> thisRun = nextRun;
nextRun = new ArrayDeque<>(); nextRun = new ArrayDeque<>();
@@ -207,7 +205,6 @@ public class GridNode implements IGridNode, IPathItem
} }
} }
} }
CraftingGridCache.unpauseRebuilds();
} }
@Override @Override
@@ -269,7 +266,7 @@ public class GridNode implements IGridNode, IPathItem
@Override @Override
public void destroy() public void destroy()
{ {
while( !this.connections.isEmpty() ) while ( !this.connections.isEmpty() )
{ {
// not part of this network for real anymore. // not part of this network for real anymore.
if( this.connections.size() == 1 ) if( this.connections.size() == 1 )
@@ -378,7 +375,7 @@ public class GridNode implements IGridNode, IPathItem
@Override @Override
public boolean meetsChannelRequirements() public boolean meetsChannelRequirements()
{ {
return( !this.gridProxy.getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || this.getUsedChannels() > 0 ); return ( !this.gridProxy.getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || this.getUsedChannels() > 0 );
} }
@Override @Override
+34 -63
View File
@@ -113,9 +113,9 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
private final GenericInterestManager<CraftingWatcher> interestManager = new GenericInterestManager<>( this.interests ); private final GenericInterestManager<CraftingWatcher> interestManager = new GenericInterestManager<>( this.interests );
private IStorageGrid storageGrid; private IStorageGrid storageGrid;
private IEnergyGrid energyGrid; private IEnergyGrid energyGrid;
int i;
private boolean updateList = false; private boolean updateList = false;
private static int pauseRebuilds = 0; private boolean updatePatterns = false;
private static Set<CraftingGridCache> rebuildNeeded = new HashSet<>();
public CraftingGridCache( final IGrid grid ) public CraftingGridCache( final IGrid grid )
{ {
@@ -140,8 +140,14 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
this.updateCPUClusters(); this.updateCPUClusters();
} }
if( updatePatterns )
{
this.recalculateCraftingPatterns();
this.updatePatterns = false;
}
final Iterator<CraftingLinkNexus> craftingLinkIterator = this.craftingLinks.values().iterator(); final Iterator<CraftingLinkNexus> craftingLinkIterator = this.craftingLinks.values().iterator();
while( craftingLinkIterator.hasNext() ) while ( craftingLinkIterator.hasNext() )
{ {
if( craftingLinkIterator.next().isDead( this.grid, this ) ) if( craftingLinkIterator.next().isDead( this.grid, this ) )
{ {
@@ -187,7 +193,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( machine instanceof ICraftingProvider ) if( machine instanceof ICraftingProvider )
{ {
this.craftingProviders.remove( machine ); this.craftingProviders.remove( machine );
this.updatePatterns(); this.updatePatterns = true;
} }
} }
@@ -221,7 +227,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( machine instanceof ICraftingProvider ) if( machine instanceof ICraftingProvider )
{ {
this.craftingProviders.add( (ICraftingProvider) machine ); this.craftingProviders.add( (ICraftingProvider) machine );
this.updatePatterns(); this.updatePatterns = true;
} }
} }
@@ -242,36 +248,15 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
// nothing! // nothing!
} }
public static void pauseRebuilds()
{
pauseRebuilds++;
}
public static void unpauseRebuilds()
{
pauseRebuilds--;
if (pauseRebuilds == 0 && rebuildNeeded.size() > 0)
{
ImmutableSet<CraftingGridCache> needed = ImmutableSet.copyOf(rebuildNeeded);
rebuildNeeded.clear();
for ( CraftingGridCache cache: needed )
{
cache.updatePatterns();
}
}
}
private void updatePatterns() private void updatePatterns()
{ {
// coalesce change events during a grid traversal to a single rebuild this.updatePatterns = true;
if (pauseRebuilds != 0) }
{
rebuildNeeded.add(this);
return;
}
final Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> oldItems = new Object2ObjectOpenHashMap<>(this.craftableItems); private void recalculateCraftingPatterns()
final Set<IAEItemStack> oldEmitableItems = new HashSet<>(this.emitableItems); {
final Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> oldItems = new Object2ObjectOpenHashMap<>( this.craftableItems );
final Set<IAEItemStack> oldEmitableItems = new HashSet<>( this.emitableItems );
// erase list. // erase list.
this.craftingMethods.clear(); this.craftingMethods.clear();
@@ -312,25 +297,29 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
this.craftableItems.put( e.getKey(), ImmutableList.copyOf( e.getValue() ) ); this.craftableItems.put( e.getKey(), ImmutableList.copyOf( e.getValue() ) );
} }
Object2ObjectMap<IAEItemStack, ImmutableList<ICraftingPatternDetails>> craftablesChanged = new Object2ObjectArrayMap<>(); List<IAEItemStack> craftablesChanged = new ArrayList<>();
ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> i = oldItems.entrySet(); ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> i = oldItems.entrySet();
for ( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : i) { for( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : i )
if (!this.craftableItems.containsKey( ais.getKey() )) { {
if( !this.craftableItems.containsKey( ais.getKey() ) )
{
IAEItemStack changedStack = ais.getKey().copy(); IAEItemStack changedStack = ais.getKey().copy();
changedStack.reset(); changedStack.reset();
changedStack.setCraftable( false ); changedStack.setCraftable( false );
craftablesChanged.put( changedStack, ais.getValue() ); craftablesChanged.add( changedStack );
} }
} }
ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> j = this.craftableItems.entrySet(); ObjectSet<Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>>> j = this.craftableItems.entrySet();
for ( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : j) { for( Entry<IAEItemStack, ImmutableList<ICraftingPatternDetails>> ais : j )
if (!oldItems.containsKey( ais )){ {
if( !oldItems.containsKey( ais ) )
{
IAEItemStack changedStack = ais.getKey().copy(); IAEItemStack changedStack = ais.getKey().copy();
changedStack.reset(); changedStack.reset();
changedStack.setCraftable( true ); changedStack.setCraftable( true );
craftablesChanged.put( changedStack, ais.getValue() ); craftablesChanged.add( changedStack );
} }
} }
@@ -341,7 +330,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
IAEItemStack changedStack = st.copy(); IAEItemStack changedStack = st.copy();
changedStack.reset(); changedStack.reset();
changedStack.setCraftable( false ); changedStack.setCraftable( false );
craftablesChanged.put( changedStack, null ); craftablesChanged.add( changedStack );
} }
} }
@@ -352,12 +341,11 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
IAEItemStack changedStack = st.copy(); IAEItemStack changedStack = st.copy();
changedStack.reset(); changedStack.reset();
changedStack.setCraftable( true ); changedStack.setCraftable( true );
craftablesChanged.put( changedStack, null ); craftablesChanged.add( changedStack );
} }
} }
this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), craftablesChanged.keySet(), this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), craftablesChanged, new BaseActionSource() );
new BaseActionSource() );
} }
private void updateCPUClusters() private void updateCPUClusters()
@@ -535,22 +523,6 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
if( res == null ) if( res == null )
{ {
if( details != null && details.isCraftable() )
{
for( final IAEItemStack ais : this.craftableItems.keySet() )
{
if( ais.getItem() == whatToCraft.getItem() && ( !ais.getItem().getHasSubtypes() || ais.getItemDamage() == whatToCraft.getItemDamage() ) )
{
// TODO: check if OK
// TODO: this is slightly hacky, but fine as long as we only deal with itemstacks
if( details.isValidItemForSlot( slotIndex, ais.asItemStackRepresentation(), world ) )
{
return this.craftableItems.get( ais );
}
}
}
}
return ImmutableSet.of(); return ImmutableSet.of();
} }
@@ -596,8 +568,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
} }
} }
Collections.sort( validCpusClusters, ( firstCluster, nextCluster ) -> Collections.sort( validCpusClusters, ( firstCluster, nextCluster ) -> {
{
if( prioritizePower ) if( prioritizePower )
{ {
final int comparison1 = Long.compare( nextCluster.getCoProcessors(), firstCluster.getCoProcessors() ); final int comparison1 = Long.compare( nextCluster.getCoProcessors(), firstCluster.getCoProcessors() );
@@ -676,7 +647,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
public boolean hasCpu( final ICraftingCPU cpu ) public boolean hasCpu( final ICraftingCPU cpu )
{ {
if (cpu instanceof CraftingCPUCluster) if( cpu instanceof CraftingCPUCluster )
{ {
return this.craftingCPUClusters.contains( (CraftingCPUCluster) cpu ); return this.craftingCPUClusters.contains( (CraftingCPUCluster) cpu );
} }
@@ -710,7 +681,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper
private void findNext() private void findNext()
{ {
while( this.iterator.hasNext() && this.cpuCluster == null ) while ( this.iterator.hasNext() && this.cpuCluster == null )
{ {
this.cpuCluster = this.iterator.next(); this.cpuCluster = this.iterator.next();
if( !this.cpuCluster.isActive() || this.cpuCluster.isDestroyed() ) if( !this.cpuCluster.isActive() || this.cpuCluster.isDestroyed() )
+40 -21
View File
@@ -19,13 +19,12 @@
package appeng.me.cache; package appeng.me.cache;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.crafting.MECraftingInventory;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.IPriorityHost;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap; import com.google.common.collect.SetMultimap;
@@ -55,6 +54,8 @@ import appeng.me.helpers.GenericInterestManager;
import appeng.me.helpers.MachineSource; import appeng.me.helpers.MachineSource;
import appeng.me.storage.ItemWatcher; import appeng.me.storage.ItemWatcher;
import appeng.me.storage.NetworkInventoryHandler; import appeng.me.storage.NetworkInventoryHandler;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class GridStorageCache implements IStorageGrid public class GridStorageCache implements IStorageGrid
@@ -66,8 +67,10 @@ public class GridStorageCache implements IStorageGrid
private final SetMultimap<IAEStack, ItemWatcher> interests = HashMultimap.create(); private final SetMultimap<IAEStack, ItemWatcher> interests = HashMultimap.create();
private final GenericInterestManager<ItemWatcher> interestManager = new GenericInterestManager<>( this.interests ); private final GenericInterestManager<ItemWatcher> interestManager = new GenericInterestManager<>( this.interests );
private final HashMap<IGridNode, IStackWatcher> watchers = new HashMap<>(); private final HashMap<IGridNode, IStackWatcher> watchers = new HashMap<>();
private Map<IStorageChannel<? extends IAEStack>, NetworkInventoryHandler<?>> storageNetworks; private final Map<IStorageChannel<? extends IAEStack>, NetworkInventoryHandler<?>> storageNetworks;
private Map<IStorageChannel<? extends IAEStack>, NetworkMonitor<?>> storageMonitors; private final Map<IStorageChannel<? extends IAEStack>, NetworkMonitor<?>> storageMonitors;
private MECraftingInventory localCache = null;
private int localDepth;
public GridStorageCache( final IGrid g ) public GridStorageCache( final IGrid g )
{ {
@@ -81,6 +84,7 @@ public class GridStorageCache implements IStorageGrid
@Override @Override
public void onUpdateTick() public void onUpdateTick()
{ {
this.localCache = null;
this.storageMonitors.forEach( ( channel, monitor ) -> monitor.onTick() ); this.storageMonitors.forEach( ( channel, monitor ) -> monitor.onTick() );
} }
@@ -168,6 +172,15 @@ public class GridStorageCache implements IStorageGrid
return (IMEMonitor<T>) this.storageMonitors.get( channel ); return (IMEMonitor<T>) this.storageMonitors.get( channel );
} }
public MECraftingInventory getExtractableList( IActionSource src )
{
if( localCache == null )
{
localCache = new MECraftingInventory( getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ), src, false, false, false );
}
return localCache;
}
private CellChangeTracker addCellProvider( final ICellProvider cc, final CellChangeTracker tracker ) private CellChangeTracker addCellProvider( final ICellProvider cc, final CellChangeTracker tracker )
{ {
if( this.inactiveCellProviders.contains( cc ) ) if( this.inactiveCellProviders.contains( cc ) )
@@ -177,12 +190,13 @@ public class GridStorageCache implements IStorageGrid
final IActionSource actionSrc = cc instanceof IActionHost ? new MachineSource( (IActionHost) cc ) : new BaseActionSource(); final IActionSource actionSrc = cc instanceof IActionHost ? new MachineSource( (IActionHost) cc ) : new BaseActionSource();
this.storageMonitors.forEach( ( channel, monitor ) -> { this.storageMonitors.forEach( ( channel, monitor ) ->
for( final IMEInventoryHandler<?> h : cc.getCellArray( channel ) ) {
{ for( final IMEInventoryHandler<?> h : cc.getCellArray( channel ) )
tracker.postChanges( channel, 1, h, actionSrc ); {
} tracker.postChanges( channel, 1, h, actionSrc );
} ); }
} );
} }
return tracker; return tracker;
@@ -198,12 +212,12 @@ public class GridStorageCache implements IStorageGrid
final IActionSource actionSrc = cc instanceof IActionHost ? new MachineSource( (IActionHost) cc ) : new BaseActionSource(); final IActionSource actionSrc = cc instanceof IActionHost ? new MachineSource( (IActionHost) cc ) : new BaseActionSource();
this.storageMonitors.forEach( ( channel, monitor ) -> this.storageMonitors.forEach( ( channel, monitor ) ->
{ {
for( final IMEInventoryHandler<IAEItemStack> h : cc.getCellArray( channel ) ) for( final IMEInventoryHandler<IAEItemStack> h : cc.getCellArray( channel ) )
{ {
tracker.postChanges( channel, -1, h, actionSrc ); tracker.postChanges( channel, -1, h, actionSrc );
} }
} ); } );
} }
return tracker; return tracker;
@@ -212,6 +226,11 @@ public class GridStorageCache implements IStorageGrid
@MENetworkEventSubscribe @MENetworkEventSubscribe
public void cellUpdate( final MENetworkCellArrayUpdate ev ) public void cellUpdate( final MENetworkCellArrayUpdate ev )
{ {
if( localDepth > 0 )
{
return;
}
localDepth++;
this.storageNetworks.clear(); this.storageNetworks.clear();
final List<ICellProvider> ll = new ArrayList<ICellProvider>(); final List<ICellProvider> ll = new ArrayList<ICellProvider>();
@@ -247,7 +266,7 @@ public class GridStorageCache implements IStorageGrid
} }
} }
tracker.applyChanges(); tracker.applyChanges();
localDepth--;
this.storageMonitors.forEach( ( channel, monitor ) -> monitor.setForceUpdate( true ) ); this.storageMonitors.forEach( ( channel, monitor ) -> monitor.setForceUpdate( true ) );
} }
@@ -239,7 +239,8 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
// also stop accepting items when the job is complete, i.e. to prevent re-insertion when pushing out // also stop accepting items when the job is complete, i.e. to prevent re-insertion when pushing out
// items during storeItems // items during storeItems
if (input == null || isComplete) { if( input == null || isComplete )
{
return input; return input;
} }
@@ -375,7 +376,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
final ImmutableList<IAEItemStack> single = ImmutableList.of( diff.copy() ); final ImmutableList<IAEItemStack> single = ImmutableList.of( diff.copy() );
while( i.hasNext() ) while ( i.hasNext() )
{ {
final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> o = i.next(); final Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> o = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> receiver = o.getKey(); final IMEMonitorHandlerReceiver<IAEItemStack> receiver = o.getKey();
@@ -495,15 +496,14 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
return null; return null;
} }
private boolean canCraft(final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs) private boolean canCraft( final ICraftingPatternDetails details, final IAEItemStack[] condensedInputs )
{ {
if( !details.isCraftable() ) if( !details.isCraftable() )
{ {
// Processing patterns are relatively easy // Processing patterns are relatively easy
for ( IAEItemStack input : condensedInputs ) for( IAEItemStack input : condensedInputs )
{ {
final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE, final IAEItemStack ais = this.inventory.extractItems( input.copy(), Actionable.SIMULATE, this.machineSrc );
this.machineSrc );
if( ais == null || ais.getStackSize() < input.getStackSize() ) if( ais == null || ais.getStackSize() < input.getStackSize() )
{ {
@@ -516,7 +516,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
// When substitutions are allowed, we have to keep track of which items we've reserved // When substitutions are allowed, we have to keep track of which items we've reserved
IAEItemStack[] inputs = details.getInputs(); IAEItemStack[] inputs = details.getInputs();
Map<IAEItemStack, Integer> consumedCount = new HashMap<>(); Map<IAEItemStack, Integer> consumedCount = new HashMap<>();
for ( int i = 0; i < inputs.length; i++ ) for( int i = 0; i < inputs.length; i++ )
{ {
List<IAEItemStack> substitutes = details.getSubstituteInputs( i ); List<IAEItemStack> substitutes = details.getSubstituteInputs( i );
if( substitutes.isEmpty() ) if( substitutes.isEmpty() )
@@ -525,9 +525,9 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
} }
boolean found = false; boolean found = false;
for ( IAEItemStack substitute : substitutes ) for( IAEItemStack substitute : substitutes )
{ {
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( substitute, FuzzyMode.IGNORE_ALL ) ) for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( substitute, FuzzyMode.IGNORE_ALL ) )
{ {
int alreadyConsumed = consumedCount.getOrDefault( fuzz, 0 ); int alreadyConsumed = consumedCount.getOrDefault( fuzz, 0 );
if( fuzz.getStackSize() - alreadyConsumed <= 0 ) if( fuzz.getStackSize() - alreadyConsumed <= 0 )
@@ -537,8 +537,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize( 1 ); // We're iterating over non condensed inputs which means there's 1 of each needed fuzz.setStackSize( 1 ); // We're iterating over non condensed inputs which means there's 1 of each needed
final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.SIMULATE, this.machineSrc );
this.machineSrc );
if( ais != null && ais.getStackSize() > 0 ) if( ais != null && ais.getStackSize() > 0 )
{ {
@@ -565,11 +564,11 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
// When no substitutions can occur, we can simply check that all items are accounted since // When no substitutions can occur, we can simply check that all items are accounted since
// each type of item should only occur once // each type of item should only occur once
for ( IAEItemStack g : condensedInputs ) for( IAEItemStack g : condensedInputs )
{ {
boolean found = false; boolean found = false;
for ( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) ) for( IAEItemStack fuzz : this.inventory.getItemList().findFuzzy( g, FuzzyMode.IGNORE_ALL ) )
{ {
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize( g.getStackSize() ); fuzz.setStackSize( g.getStackSize() );
@@ -675,8 +674,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
this.somethingChanged = false; this.somethingChanged = false;
this.executeCrafting( eg, cc ); this.executeCrafting( eg, cc );
} } while ( this.somethingChanged && this.remainingOperations > 0 );
while( this.somethingChanged && this.remainingOperations > 0 );
} }
this.usedOps[2] = this.usedOps[1]; this.usedOps[2] = this.usedOps[1];
this.usedOps[1] = this.usedOps[0]; this.usedOps[1] = this.usedOps[0];
@@ -692,7 +690,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
final Iterator<Entry<ICraftingPatternDetails, TaskProgress>> i = this.tasks.entrySet().iterator(); final Iterator<Entry<ICraftingPatternDetails, TaskProgress>> i = this.tasks.entrySet().iterator();
while( i.hasNext() ) while ( i.hasNext() )
{ {
final Entry<ICraftingPatternDetails, TaskProgress> e = i.next(); final Entry<ICraftingPatternDetails, TaskProgress> e = i.next();
@@ -708,12 +706,12 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
InventoryCrafting ic = null; InventoryCrafting ic = null;
if (!visitedMediums.containsKey( details ) || visitedMediums.get( details ).isEmpty()) if( !visitedMediums.containsKey( details ) || visitedMediums.get( details ).isEmpty() )
{ {
visitedMediums.put( details, new ArrayDeque<>( cc.getMediums( details ).stream().filter( Objects::nonNull ).collect( Collectors.toList()) ) ); visitedMediums.put( details, new ArrayDeque<>( cc.getMediums( details ).stream().filter( Objects::nonNull ).collect( Collectors.toList() ) ) );
} }
while (!visitedMediums.get( details ).isEmpty()) while ( !visitedMediums.get( details ).isEmpty() )
{ {
ICraftingMedium m = visitedMediums.get( details ).poll(); ICraftingMedium m = visitedMediums.get( details ).poll();
@@ -773,52 +771,58 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
itemList.addAll( this.inventory.getItemList().findFuzzy( stack, FuzzyMode.IGNORE_ALL ) ); itemList.addAll( this.inventory.getItemList().findFuzzy( stack, FuzzyMode.IGNORE_ALL ) );
} }
} else { }
itemList = new ArrayList<>(1); else
{
itemList = new ArrayList<>( 1 );
final IAEItemStack item = this.inventory.getItemList() final IAEItemStack item = this.inventory.getItemList().findPrecise( input[x] );
.findPrecise(input[x]);
if (item != null) { if( item != null )
itemList.add(item); {
itemList.add( item );
} }
} }
for (IAEItemStack fuzz : itemList) { for( IAEItemStack fuzz : itemList )
{
fuzz = fuzz.copy(); fuzz = fuzz.copy();
fuzz.setStackSize(input[x].getStackSize()); fuzz.setStackSize( input[x].getStackSize() );
if (details.isValidItemForSlot(x, fuzz.createItemStack(), if( details.isValidItemForSlot( x, fuzz.createItemStack(), this.getWorld() ) )
this.getWorld())) { {
final IAEItemStack ais = this.inventory.extractItems(fuzz, final IAEItemStack ais = this.inventory.extractItems( fuzz, Actionable.MODULATE, this.machineSrc );
Actionable.MODULATE, this.machineSrc); final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
final ItemStack is = ais == null ? ItemStack.EMPTY
: ais.createItemStack();
if (!is.isEmpty()) { if( !is.isEmpty() )
this.postChange(AEItemStack.fromItemStack(is), this.machineSrc); {
ic.setInventorySlotContents(x, is); this.postChange( AEItemStack.fromItemStack( is ), this.machineSrc );
ic.setInventorySlotContents( x, is );
found = true; found = true;
break; break;
} }
} }
} }
} else { }
final IAEItemStack ais = this.inventory.extractItems(input[x].copy(), else
Actionable.MODULATE, this.machineSrc); {
final IAEItemStack ais = this.inventory.extractItems( input[x].copy(), Actionable.MODULATE, this.machineSrc );
final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack(); final ItemStack is = ais == null ? ItemStack.EMPTY : ais.createItemStack();
if (!is.isEmpty()) { if( !is.isEmpty() )
this.postChange(input[x], this.machineSrc); {
ic.setInventorySlotContents(x, is); this.postChange( input[x], this.machineSrc );
if (is.getCount() == input[x].getStackSize()) { ic.setInventorySlotContents( x, is );
if( is.getCount() == input[x].getStackSize() )
{
found = true; found = true;
continue; continue;
} }
} }
} }
if (!found) { if( !found )
{
break; break;
} }
} }
@@ -902,7 +906,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
private void storeItems() private void storeItems()
{ {
Preconditions.checkState(isComplete, "CPU should be complete to prevent re-insertion when dumping items"); Preconditions.checkState( isComplete, "CPU should be complete to prevent re-insertion when dumping items" );
final IGrid g = this.getGrid(); final IGrid g = this.getGrid();
if( g == null ) if( g == null )
@@ -1016,8 +1020,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
public boolean isBusy() public boolean isBusy()
{ {
this.tasks.entrySet().removeIf( this.tasks.entrySet().removeIf( taskProgressEntry -> taskProgressEntry.getValue().value <= 0 );
taskProgressEntry -> taskProgressEntry.getValue().value <= 0 );
if( !this.waitingFor.isEmpty() || !this.tasks.isEmpty() ) if( !this.waitingFor.isEmpty() || !this.tasks.isEmpty() )
{ {
@@ -1075,8 +1078,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
final int hash = System.identityHashCode( this ); final int hash = System.identityHashCode( this );
final int hmm = this.finalOutput == null ? 0 : this.finalOutput.hashCode(); final int hmm = this.finalOutput == null ? 0 : this.finalOutput.hashCode();
return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm, return Long.toString( now, Character.MAX_RADIX ) + '-' + Integer.toString( hash, Character.MAX_RADIX ) + '-' + Integer.toString( hmm, Character.MAX_RADIX );
Character.MAX_RADIX );
} }
private NBTTagCompound generateLinkData( final String craftingID, final boolean standalone, final boolean req ) private NBTTagCompound generateLinkData( final String craftingID, final boolean standalone, final boolean req )
@@ -1103,7 +1105,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
public void getListOfItem( final IItemList<IAEItemStack> list, final CraftingItemList whichList ) public void getListOfItem( final IItemList<IAEItemStack> list, final CraftingItemList whichList )
{ {
switch( whichList ) switch ( whichList )
{ {
case ACTIVE: case ACTIVE:
for( final IAEItemStack ais : this.waitingFor ) for( final IAEItemStack ais : this.waitingFor )
@@ -1174,7 +1176,7 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU
{ {
IAEItemStack is; IAEItemStack is;
switch( storage2 ) switch ( storage2 )
{ {
case STORAGE: case STORAGE:
is = this.inventory.getItemList().findPrecise( what ); is = this.inventory.getItemList().findPrecise( what );
@@ -177,7 +177,7 @@ public class PartPlacement
; ;
if( held.getCount() == 0 ) if( held.getCount() == 0 )
{ {
player.inventory.mainInventory.set( player.inventory.currentItem, ItemStack.EMPTY ); player.setHeldItem( hand, ItemStack.EMPTY );
MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( player, held, hand ) ); MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( player, held, hand ) );
} }
} }
@@ -22,6 +22,7 @@ package appeng.parts.automation;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
@@ -70,8 +71,6 @@ import appeng.util.item.AEItemStack;
public class PartExportBus extends PartSharedItemBus implements ICraftingRequester public class PartExportBus extends PartSharedItemBus implements ICraftingRequester
{ {
private final int[] failedCraftTriesSlot = {0,0,0,0,0,0,0,0,0};
public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/export_bus_base" ); public static final ResourceLocation MODEL_BASE = new ResourceLocation( AppEng.MOD_ID, "part/export_bus_base" );
@PartModels @PartModels
@@ -131,10 +130,7 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
try try
{ {
final InventoryAdaptor destination = this.getHandler(); final InventoryAdaptor destination = this.getHandler();
final IMEMonitor<IAEItemStack> inv = this.getProxy() final IMEMonitor<IAEItemStack> inv = this.getProxy().getStorage().getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
.getStorage()
.getInventory(
AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
final IEnergyGrid energy = this.getProxy().getEnergy(); final IEnergyGrid energy = this.getProxy().getEnergy();
final ICraftingGrid cg = this.getProxy().getCrafting(); final ICraftingGrid cg = this.getProxy().getCrafting();
final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE ); final FuzzyMode fzMode = (FuzzyMode) this.getConfigManager().getSetting( Settings.FUZZY_MODE );
@@ -150,21 +146,17 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
final IAEItemStack ais = this.getConfig().getAEStackInSlot( slotToExport ); final IAEItemStack ais = this.getConfig().getAEStackInSlot( slotToExport );
if( ais == null || this.itemToSend <= 0 ) continue; if( ais == null || this.itemToSend <= 0 )
{
if ( this.craftOnly() ) {
if (this.failedCraftTriesSlot[x] <= 0) {
this.didSomething = this.craftingTracker.handleCrafting(slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(),
this.getProxy().getGrid(), cg, this.mySrc) || this.didSomething;
if (this.didSomething) this.failedCraftTriesSlot[x] = 0;
else this.failedCraftTriesSlot[x] += 2;
}
this.failedCraftTriesSlot[x] -= 1;
continue; continue;
} }
if( this.craftOnly() )
{
this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc ) || this.didSomething;
}
final long before = this.itemToSend; final long before = this.itemToSend;
if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 ) if( this.getInstalledUpgrades( Upgrades.FUZZY ) > 0 )
@@ -188,15 +180,7 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
if( this.itemToSend == before && this.isCraftingEnabled() ) if( this.itemToSend == before && this.isCraftingEnabled() )
{ {
if (this.failedCraftTriesSlot[x] <= 0) { this.didSomething = this.craftingTracker.handleCrafting( slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(), this.getProxy().getGrid(), cg, this.mySrc ) || this.didSomething;
this.didSomething = this.craftingTracker.handleCrafting(slotToExport, this.itemToSend, ais, destination, this.getTile().getWorld(),
this.getProxy().getGrid(), cg, this.mySrc) || this.didSomething;
if (this.didSomething) this.failedCraftTriesSlot[x] = 0;
else this.failedCraftTriesSlot[x] += 2;
}
this.failedCraftTriesSlot[x] -= 1;
} }
} }
@@ -278,11 +262,30 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
if( energy.extractAEPower( power, mode, PowerMultiplier.CONFIG ) > power - 0.01 ) if( energy.extractAEPower( power, mode, PowerMultiplier.CONFIG ) > power - 0.01 )
{ {
if( mode == Actionable.MODULATE ) ItemStack inputStack = items.getCachedItemStack( items.getStackSize() );
ItemStack remaining;
if( mode == Actionable.SIMULATE )
{ {
return AEItemStack.fromItemStack( d.addItems( items.createItemStack() ) ); remaining = d.simulateAdd( inputStack );
items.setCachedItemStack( inputStack );
} }
return AEItemStack.fromItemStack( d.simulateAdd( items.createItemStack() ) ); else
{
remaining = d.addItems( inputStack );
if( !remaining.isEmpty() )
{
items.setCachedItemStack( remaining );
}
}
if( remaining == inputStack )
{
return items;
}
return AEItemStack.fromItemStack( remaining );
} }
} }
} }
@@ -316,17 +319,27 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
return this.getInstalledUpgrades( Upgrades.CRAFTING ) > 0; return this.getInstalledUpgrades( Upgrades.CRAFTING ) > 0;
} }
private void pushItemIntoTarget( final InventoryAdaptor d, final IEnergyGrid energy, final IMEInventory<IAEItemStack> inv, IAEItemStack ais ) private void pushItemIntoTarget( final InventoryAdaptor d, final IEnergyGrid energy, final IMEInventory<IAEItemStack> inv, IAEItemStack org )
{ {
final ItemStack is = ais.createItemStack(); ItemStack inputStack = org.getCachedItemStack( org.getStackSize() );
is.setCount( (int) this.itemToSend );
final ItemStack o = d.simulateAdd( is ); ItemStack remaining = d.simulateAdd( inputStack );
final long canFit = o.isEmpty() ? this.itemToSend : this.itemToSend - o.getCount();
// Store the stack in the cache for next time.
if( !remaining.isEmpty() )
{
org.setCachedItemStack( remaining );
if( remaining == inputStack )
{
return;
}
}
final long canFit = remaining.isEmpty() ? this.itemToSend : this.itemToSend - remaining.getCount();
if( canFit > 0 ) if( canFit > 0 )
{ {
ais = ais.copy(); IAEItemStack ais = org.copy();
ais.setStackSize( canFit ); ais.setStackSize( canFit );
final IAEItemStack itemsToAdd = Platform.poweredExtraction( energy, inv, ais, this.mySrc ); final IAEItemStack itemsToAdd = Platform.poweredExtraction( energy, inv, ais, this.mySrc );
@@ -334,7 +347,9 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
{ {
this.itemToSend -= itemsToAdd.getStackSize(); this.itemToSend -= itemsToAdd.getStackSize();
final ItemStack failed = d.addItems( itemsToAdd.createItemStack() ); inputStack.setCount( Ints.saturatedCast( itemsToAdd.getStackSize() ) );
final ItemStack failed = d.addItems( inputStack );
if( !failed.isEmpty() ) if( !failed.isEmpty() )
{ {
ais.setStackSize( failed.getCount() ); ais.setStackSize( failed.getCount() );
@@ -345,6 +360,10 @@ public class PartExportBus extends PartSharedItemBus implements ICraftingRequest
this.didSomething = true; this.didSomething = true;
} }
} }
else
{
org.setCachedItemStack( inputStack );
}
} }
} }
@@ -19,7 +19,6 @@
package appeng.parts.misc; package appeng.parts.misc;
import javax.annotation.Nullable;
import appeng.api.AEApi; import appeng.api.AEApi;
import appeng.api.config.AccessRestriction; import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable; import appeng.api.config.Actionable;
@@ -62,8 +61,6 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
private StorageFilter mode; private StorageFilter mode;
private AccessRestriction access; private AccessRestriction access;
private ItemStack stackCache = null;
ItemHandlerAdapter( IItemHandler itemHandler, IGridProxyable proxy ) ItemHandlerAdapter( IItemHandler itemHandler, IGridProxyable proxy )
{ {
this.itemHandler = itemHandler; this.itemHandler = itemHandler;
@@ -82,39 +79,31 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src ) public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src )
{ {
// Try to reuse the cached stack // Try to reuse the cached stack
@Nullable ItemStack currentCached = stackCache; ItemStack inputStack = iox.getCachedItemStack( iox.getStackSize() );
stackCache = null;
ItemStack remaining = inputStack;
ItemStack orgInput;
int slotCount = this.itemHandler.getSlots(); int slotCount = this.itemHandler.getSlots();
if( currentCached != null && iox.isSameType( currentCached ) )
{
// Cache is suitable, just update the count
orgInput = currentCached;
currentCached.setCount( Ints.saturatedCast( iox.getStackSize() ) );
}
else
{
// We need a new stack :-(
orgInput = iox.createItemStack();
}
ItemStack remaining = orgInput;
for( int i = 0; i < slotCount && !remaining.isEmpty(); i++ ) for( int i = 0; i < slotCount && !remaining.isEmpty(); i++ )
{ {
remaining = this.itemHandler.insertItem( i, remaining, type == Actionable.SIMULATE ); remaining = this.itemHandler.insertItem( i, remaining, type == Actionable.SIMULATE );
} }
// Store the stack in the cache for next time. // Store the stack in the cache for next time.
if( !remaining.isEmpty() && remaining != orgInput ) if( type == Actionable.SIMULATE )
{ {
stackCache = remaining; iox.setCachedItemStack( inputStack );
}
else
{
if( !remaining.isEmpty() )
{
iox.setCachedItemStack( remaining );
}
} }
// At this point, we still have some items left... // At this point, we still have some items left...
if( remaining == orgInput ) if( remaining == inputStack )
{ {
// The stack remained unmodified, target inventory is full // The stack remained unmodified, target inventory is full
return iox; return iox;
@@ -147,7 +136,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
ItemStack gathered = ItemStack.EMPTY; ItemStack gathered = ItemStack.EMPTY;
final boolean simulate = ( mode == Actionable.SIMULATE ); final boolean simulate = ( mode == Actionable.SIMULATE );
for ( int i = 0; i < this.itemHandler.getSlots(); i++ ) for( int i = 0; i < this.itemHandler.getSlots(); i++ )
{ {
ItemStack stackInInventorySlot = this.itemHandler.getStackInSlot( i ); ItemStack stackInInventorySlot = this.itemHandler.getStackInSlot( i );
@@ -157,6 +146,7 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
} }
ItemStack extracted; ItemStack extracted;
int stackSizeCurrentSlot = stackInInventorySlot.getCount(); int stackSizeCurrentSlot = stackInInventorySlot.getCount();
int remainingCurrentSlot = Math.min( remainingSize, stackSizeCurrentSlot ); int remainingCurrentSlot = Math.min( remainingSize, stackSizeCurrentSlot );
@@ -165,24 +155,36 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
do do
{ {
extracted = this.itemHandler.extractItem( i, remainingCurrentSlot, simulate ); extracted = this.itemHandler.extractItem( i, remainingCurrentSlot, simulate );
if( !extracted.isEmpty() ) if( !extracted.isEmpty() )
{ {
// In order to guard against broken IItemHandler implementations, we'll try to guess if the returned
// stack (especially in simulate mode) is the same that was returned by getStackInSlot. This is
// obviously not a precise science, but it would catch the previous Forge bug:
// https://github.com/MinecraftForge/MinecraftForge/pull/6580
if( extracted == stackInInventorySlot )
{
extracted = extracted.copy();
}
if( extracted.getCount() > remainingCurrentSlot ) if( extracted.getCount() > remainingCurrentSlot )
{ {
// Something broke. It should never return more than we requested... // Something broke. It should never return more than we requested...
// We're going to silently eat the remainder // We're going to silently eat the remainder
AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", this.itemHandler.getClass().getName(), extracted.toString(), remainingCurrentSlot );
this.itemHandler.getClass().getName(), extracted.toString(), remainingCurrentSlot ); extracted.setCount( remainingCurrentSlot );
}
// Heuristic for simulation: looping in case of simulations is pointless, since the state of the
// underlying inventory does not change after a simulated extraction. To still support inventories
// that report stacks that are larger than maxStackSize, we use this heuristic
if( simulate && extracted.getCount() == extracted.getMaxStackSize() && remainingCurrentSlot > extracted.getMaxStackSize() )
{
extracted.setCount( remainingCurrentSlot ); extracted.setCount( remainingCurrentSlot );
} }
// We're just gonna use the first stack we get our hands on as the template for the rest.
// In case some stupid itemhandler (aka forge) returns an internal state we have to do a second
// expensive copy again.
if( gathered.isEmpty() ) if( gathered.isEmpty() )
{ {
gathered = extracted.copy(); gathered = extracted;
} }
else else
{ {
@@ -190,11 +192,9 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
} }
remainingCurrentSlot -= extracted.getCount(); remainingCurrentSlot -= extracted.getCount();
} }
} while ( !extracted.isEmpty() && remainingCurrentSlot > 0 ); } while ( !simulate && !extracted.isEmpty() && remainingCurrentSlot > 0 );
remainingSize -= stackSizeCurrentSlot - remainingCurrentSlot; remainingSize -= stackSizeCurrentSlot - remainingCurrentSlot;
// Done?
if( remainingSize <= 0 ) if( remainingSize <= 0 )
{ {
break; break;
@@ -329,17 +329,17 @@ class ItemHandlerAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAE
currentlyOnStorage.add( is.getAEItemStack() ); currentlyOnStorage.add( is.getAEItemStack() );
} }
for ( final IAEItemStack is : currentlyCached ) for( final IAEItemStack is : currentlyCached )
{ {
is.setStackSize( -is.getStackSize() ); is.setStackSize( -is.getStackSize() );
} }
for ( final IAEItemStack is : currentlyOnStorage ) for( final IAEItemStack is : currentlyOnStorage )
{ {
currentlyCached.add( is ); currentlyCached.add( is );
} }
for ( final IAEItemStack is : currentlyCached ) for( final IAEItemStack is : currentlyCached )
{ {
if( is.getStackSize() != 0 ) if( is.getStackSize() != 0 )
{ {
@@ -35,232 +35,225 @@ import java.util.*;
class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor class ItemRepositoryAdapter implements IMEInventory<IAEItemStack>, IBaseMonitor<IAEItemStack>, ITickingMonitor
{ {
private final Object2ObjectMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new Object2ObjectOpenHashMap<>(); private final Object2ObjectMap<IMEMonitorHandlerReceiver<IAEItemStack>, Object> listeners = new Object2ObjectOpenHashMap<>();
private IActionSource mySource; private IActionSource mySource;
private final IItemRepository itemRepository; private final IItemRepository itemRepository;
private final IGridProxyable proxyable; private final IGridProxyable proxyable;
private final InventoryCache cache; private final InventoryCache cache;
private AccessRestriction access; private AccessRestriction access;
private ItemStack stackCache; ItemRepositoryAdapter( IItemRepository itemRepository, IGridProxyable proxy )
{
this.itemRepository = itemRepository;
this.proxyable = proxy;
this.cache = new InventoryCache( this.itemRepository );
if( this.proxyable instanceof PartStorageBus )
{
PartStorageBus partStorageBus = (PartStorageBus) this.proxyable;
this.access = ( (AccessRestriction) partStorageBus.getConfigManager().getSetting( Settings.ACCESS ) );
}
this.cache.update();
}
ItemRepositoryAdapter( IItemRepository itemRepository, IGridProxyable proxy ) @Override
{ public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src )
this.itemRepository = itemRepository; {
this.proxyable = proxy; // Try to reuse the cached stack
this.cache = new InventoryCache( this.itemRepository ); ItemStack inputStack = iox.getCachedItemStack( iox.getStackSize() );
if( this.proxyable instanceof PartStorageBus )
{
PartStorageBus partStorageBus = (PartStorageBus) this.proxyable;
this.access = ( (AccessRestriction) partStorageBus.getConfigManager().getSetting( Settings.ACCESS ) );
}
this.cache.update();
}
@Override ItemStack remaining;
public IAEItemStack injectItems( IAEItemStack iox, Actionable type, IActionSource src )
{
// Try to reuse the cached stack
@Nullable ItemStack currentCached = stackCache;
stackCache = null;
ItemStack orgInput; remaining = this.itemRepository.insertItem( inputStack, type == Actionable.SIMULATE );
if( currentCached != null && iox.isSameType( currentCached ) )
{
// Cache is suitable, just update the count
orgInput = currentCached;
currentCached.setCount( Ints.saturatedCast( iox.getStackSize() ) );
}
else
{
// We need a new stack :-(
orgInput = iox.createItemStack();
}
ItemStack remaining = this.itemRepository.insertItem( orgInput, type == Actionable.SIMULATE );
// Store the stack in the cache for next time. // Store the stack in the cache for next time.
if( !remaining.isEmpty() && remaining != orgInput ) if( type == Actionable.SIMULATE )
{ {
stackCache = remaining; iox.setCachedItemStack( inputStack );
} }
else
{
if( !remaining.isEmpty() )
{
iox.setCachedItemStack( remaining );
}
}
// At this point, we still have some items left... // At this point, we still have some items left...
if( remaining == orgInput ) if( remaining == inputStack )
{ {
// The stack remained unmodified, target inventory is full // The stack remained unmodified, target inventory is full
return iox; return iox;
} }
if( type == Actionable.MODULATE ) if( type == Actionable.MODULATE )
{ {
IAEItemStack added = iox.copy().setStackSize( iox.getStackSize() - remaining.getCount() ); IAEItemStack added = iox.copy().setStackSize( iox.getStackSize() - remaining.getCount() );
this.cache.currentlyCached.add( added ); this.cache.currentlyCached.add( added );
this.postDifference( Collections.singletonList( added ) ); this.postDifference( Collections.singletonList( added ) );
try try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
} }
catch( GridAccessException ex ) catch( GridAccessException ex )
{ {
// meh // meh
} }
} }
return AEItemStack.fromItemStack( remaining ); return AEItemStack.fromItemStack( remaining );
} }
@Override @Override
public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src ) public IAEItemStack extractItems( IAEItemStack request, Actionable mode, IActionSource src )
{ {
int remainingSize = Ints.saturatedCast( request.getStackSize() ); int remainingSize = Ints.saturatedCast( request.getStackSize() );
final boolean simulate = ( mode == Actionable.SIMULATE ); final boolean simulate = ( mode == Actionable.SIMULATE );
ItemStack extracted = this.itemRepository.extractItem( request.getDefinition(), remainingSize, simulate ); ItemStack extracted = this.itemRepository.extractItem( request.getDefinition(), remainingSize, simulate );
if( extracted.getCount() > remainingSize ) if( extracted.getCount() > remainingSize )
{ {
// Something broke. It should never return more than we requested... // Something broke. It should never return more than we requested...
// We're going to silently eat the remainder // We're going to silently eat the remainder
AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", AELog.warn( "Mod that provided item handler %s is broken. Returned %s items while only requesting %d.", this.itemRepository.getClass().getName(), extracted.toString(), remainingSize );
this.itemRepository.getClass().getName(), extracted.toString(), remainingSize ); extracted.setCount( remainingSize );
extracted.setCount( remainingSize ); }
}
if( !extracted.isEmpty() ) if( !extracted.isEmpty() )
{ {
IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted ); IAEItemStack extractedAEItemStack = AEItemStack.fromItemStack( extracted );
if( mode == Actionable.MODULATE ) if( mode == Actionable.MODULATE )
{ {
IAEItemStack cachedStack = this.cache.currentlyCached.findPrecise( request ); IAEItemStack cachedStack = this.cache.currentlyCached.findPrecise( request );
if (cachedStack != null) if( cachedStack != null )
{ {
cachedStack.decStackSize( extractedAEItemStack.getStackSize() ); cachedStack.decStackSize( extractedAEItemStack.getStackSize() );
this.postDifference( Collections.singletonList( extractedAEItemStack.copy().setStackSize( -extractedAEItemStack.getStackSize() ) ) ); this.postDifference( Collections.singletonList( extractedAEItemStack.copy().setStackSize( -extractedAEItemStack.getStackSize() ) ) );
} }
try try
{ {
this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() ); this.proxyable.getProxy().getTick().alertDevice( this.proxyable.getProxy().getNode() );
} }
catch( GridAccessException ex ) catch( GridAccessException ex )
{ {
// meh // meh
} }
} }
return extractedAEItemStack; return extractedAEItemStack;
} }
return null; return null;
} }
@Override @Override
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out ) public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{ {
return this.cache.getAvailableItems( out ); return this.cache.getAvailableItems( out );
} }
@Override @Override
public IStorageChannel<IAEItemStack> getChannel() public IStorageChannel<IAEItemStack> getChannel()
{ {
return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ); return AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class );
} }
@Override @Override
public void addListener( IMEMonitorHandlerReceiver<IAEItemStack> l, Object verificationToken ) public void addListener( IMEMonitorHandlerReceiver<IAEItemStack> l, Object verificationToken )
{ {
this.listeners.put( l, verificationToken ); this.listeners.put( l, verificationToken );
} }
@Override @Override
public void removeListener( IMEMonitorHandlerReceiver<IAEItemStack> l ) public void removeListener( IMEMonitorHandlerReceiver<IAEItemStack> l )
{ {
this.listeners.remove( l ); this.listeners.remove( l );
} }
private void postDifference( Iterable<IAEItemStack> a ) private void postDifference( Iterable<IAEItemStack> a )
{ {
final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator(); final Iterator<Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object>> i = this.listeners.entrySet().iterator();
while ( i.hasNext() ) while ( i.hasNext() )
{ {
final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next(); final Map.Entry<IMEMonitorHandlerReceiver<IAEItemStack>, Object> l = i.next();
final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey(); final IMEMonitorHandlerReceiver<IAEItemStack> key = l.getKey();
if( key.isValid( l.getValue() ) ) if( key.isValid( l.getValue() ) )
{ {
key.postChange( this, a, this.mySource ); key.postChange( this, a, this.mySource );
} }
else else
{ {
i.remove(); i.remove();
} }
} }
} }
@Override @Override
public TickRateModulation onTick() public TickRateModulation onTick()
{ {
List<IAEItemStack> changes = this.cache.update(); List<IAEItemStack> changes = this.cache.update();
if( !changes.isEmpty() && access.hasPermission( AccessRestriction.READ ) ) if( !changes.isEmpty() && access.hasPermission( AccessRestriction.READ ) )
{ {
this.postDifference( changes ); this.postDifference( changes );
return TickRateModulation.URGENT; return TickRateModulation.URGENT;
} }
else else
{ {
return TickRateModulation.SLOWER; return TickRateModulation.SLOWER;
} }
} }
@Override @Override
public void setActionSource( final IActionSource mySource ) public void setActionSource( final IActionSource mySource )
{ {
this.mySource = mySource; this.mySource = mySource;
} }
private static class InventoryCache private static class InventoryCache
{ {
private IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); private IItemList<IAEItemStack> currentlyCached = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
private final IItemRepository iItemRepository; private final IItemRepository iItemRepository;
public InventoryCache( IItemRepository iItemRepository ) public InventoryCache( IItemRepository iItemRepository )
{ {
this.iItemRepository = iItemRepository; this.iItemRepository = iItemRepository;
} }
public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out ) public IItemList<IAEItemStack> getAvailableItems( IItemList<IAEItemStack> out )
{ {
currentlyCached.iterator().forEachRemaining( out::add ); currentlyCached.iterator().forEachRemaining( out::add );
return out; return out;
} }
public List<IAEItemStack> update() public List<IAEItemStack> update()
{ {
final List<IAEItemStack> changes = new ArrayList<>(); final List<IAEItemStack> changes = new ArrayList<>();
IItemList<IAEItemStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList(); IItemList<IAEItemStack> currentlyOnStorage = AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ).createList();
this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).forEach( currentlyOnStorage::add ); this.iItemRepository.getAllItems().stream().map( s -> AEItemStack.fromItemStack( s.itemPrototype ).setStackSize( s.count ) ).forEach( currentlyOnStorage::add );
for ( final IAEItemStack is : currentlyCached ) for( final IAEItemStack is : currentlyCached )
{ {
is.setStackSize( -is.getStackSize() ); is.setStackSize( -is.getStackSize() );
} }
for ( final IAEItemStack is : currentlyOnStorage ) for( final IAEItemStack is : currentlyOnStorage )
{ {
currentlyCached.add( is ); currentlyCached.add( is );
} }
for ( final IAEItemStack is : currentlyCached ) for( final IAEItemStack is : currentlyCached )
{ {
if( is.getStackSize() != 0 ) if( is.getStackSize() != 0 )
{ {
changes.add( is ); changes.add( is );
} }
} }
currentlyCached = currentlyOnStorage; currentlyCached = currentlyOnStorage;
return changes; return changes;
} }
} }
} }
@@ -20,6 +20,7 @@ import appeng.parts.PartModel;
import appeng.util.ConfigManager; import appeng.util.ConfigManager;
import appeng.util.Platform; import appeng.util.Platform;
import appeng.util.item.OreHelper; import appeng.util.item.OreHelper;
import appeng.util.prioritylist.IPartitionList;
import appeng.util.prioritylist.OreDictPriorityList; import appeng.util.prioritylist.OreDictPriorityList;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -40,8 +41,7 @@ public class PartOreDicStorageBus extends PartStorageBus
@PartModels @PartModels
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/storage_bus_has_channel" ) ); public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, new ResourceLocation( AppEng.MOD_ID, "part/storage_bus_has_channel" ) );
public String oreExp = "";
public String oreMatch;
OreDictPriorityList<IAEItemStack> priorityList; OreDictPriorityList<IAEItemStack> priorityList;
public PartOreDicStorageBus( ItemStack is ) public PartOreDicStorageBus( ItemStack is )
@@ -53,15 +53,15 @@ public class PartOreDicStorageBus extends PartStorageBus
public void readFromNBT( NBTTagCompound data ) public void readFromNBT( NBTTagCompound data )
{ {
super.readFromNBT( data ); super.readFromNBT( data );
this.oreMatch = data.getString( "oreMatch" ); this.oreExp = data.getString( "oreMatch" );
this.priorityList = new OreDictPriorityList<>( OreHelper.INSTANCE.getMatchingOre( oreMatch ), oreMatch ); this.priorityList = new OreDictPriorityList<>( OreHelper.INSTANCE.getMatchingOre( oreExp ), oreExp );
} }
@Override @Override
public void writeToNBT( NBTTagCompound data ) public void writeToNBT( NBTTagCompound data )
{ {
super.writeToNBT( data ); super.writeToNBT( data );
data.setString( "oreMatch", getOreMatch() ); data.setString( "oreMatch", getOreExp() );
} }
@Override @Override
@@ -126,7 +126,7 @@ public class PartOreDicStorageBus extends PartStorageBus
this.handler.setWhitelist( this.getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST ); this.handler.setWhitelist( this.getInstalledUpgrades( Upgrades.INVERTER ) > 0 ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST );
this.handler.setPriority( this.priority ); this.handler.setPriority( this.priority );
this.handler.setPartitionList( priorityList ); this.handler.setPartitionList( this.getPriorityList() );
if( inv instanceof IBaseMonitor ) if( inv instanceof IBaseMonitor )
{ {
@@ -172,21 +172,31 @@ public class PartOreDicStorageBus extends PartStorageBus
return this.handler; return this.handler;
} }
public String getOreMatch() private IPartitionList<IAEItemStack> getPriorityList()
{ {
if( this.oreMatch == null ) if( priorityList == null )
{
this.priorityList = new OreDictPriorityList<>( OreHelper.INSTANCE.getMatchingOre( oreExp ), oreExp );
}
return priorityList;
}
public String getOreExp()
{
if( this.oreExp == null )
{ {
return ""; return "";
} }
return oreMatch; return oreExp;
} }
public void saveOreMatch( String oreMatch ) public void saveOreMatch( String oreMatch )
{ {
if( !this.oreMatch.equals( oreMatch ) ) if( !this.oreExp.equals( oreMatch ) )
{ {
this.oreMatch = oreMatch; this.oreExp = oreMatch;
this.priorityList = new OreDictPriorityList<>( OreHelper.INSTANCE.getMatchingOre( oreMatch ), oreMatch );
this.priorityList = new OreDictPriorityList<>( OreHelper.INSTANCE.getMatchingOre( oreExp ), oreExp );
if( this.handler != null ) if( this.handler != null )
{ {
handler.setPartitionList( this.priorityList ); handler.setPartitionList( this.priorityList );
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,255 @@
package appeng.parts.p2p;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import appeng.api.parts.IPartModel;
import appeng.items.parts.PartModels;
import appeng.me.GridAccessException;
import gregtech.api.capability.GregtechCapabilities;
import gregtech.api.capability.IEnergyContainer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.common.Optional;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;
public class PartP2PGTCEPower extends PartP2PTunnel<PartP2PGTCEPower>
{
private static final P2PModels MODELS = new P2PModels( "part/p2p/p2p_tunnel_gteu" );
private static final IEnergyContainer NULL_ENERGY_STORAGE = new NullEnergyStorage();
private final IEnergyContainer inputHandler = new InputEnergyStorage();
private final Queue<PartP2PGTCEPower> outputs = new ArrayDeque<>();
public PartP2PGTCEPower( ItemStack is )
{
super( is );
}
@PartModels
public static List<IPartModel> getModels()
{
return MODELS.getModels();
}
@Override
public IPartModel getStaticModels()
{
return MODELS.getModel( this.isPowered(), this.isActive() );
}
@Override
public void onTunnelNetworkChange()
{
this.getHost().notifyNeighbors();
}
private IEnergyContainer getAttachedEnergyStorage()
{
if( this.isActive() )
{
final TileEntity self = this.getTile();
final TileEntity te = self.getWorld().getTileEntity( self.getPos().offset( this.getSide().getFacing() ) );
if( te != null && te.hasCapability( GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, this.getSide().getOpposite().getFacing() ) )
{
return te.getCapability( GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, this.getSide().getOpposite().getFacing() );
}
}
return NULL_ENERGY_STORAGE;
}
@Override
public boolean hasCapability( @Nonnull Capability<?> capability )
{
if( !this.isOutput() )
{
if( capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER )
{
return true;
}
}
return super.hasCapability( capability );
}
@Nullable
@Override
public <T> T getCapability( @Nonnull Capability<T> capability )
{
if( capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER )
{
if( this.isOutput() )
{
return null;
}
return (T) this.inputHandler;
}
return super.getCapability( capability );
}
class InputEnergyStorage implements IEnergyContainer
{
@Override
public long getEnergyCanBeInserted()
{
long canInsert = 0;
if( outputs.isEmpty() )
{
try
{
for( PartP2PGTCEPower o : PartP2PGTCEPower.this.getOutputs() )
outputs.add( o );
}
catch( GridAccessException e )
{
e.printStackTrace();
}
}
while ( !outputs.isEmpty() )
{
PartP2PGTCEPower target = outputs.poll();
final IEnergyContainer output = target.getAttachedEnergyStorage();
if( output == this )
{
return 0;
}
if( output == null || output.getEnergyCanBeInserted() <= 0 )
{
continue;
}
canInsert += output.getEnergyCanBeInserted();
}
return canInsert;
}
@Override
public long acceptEnergyFromNetwork( EnumFacing facing, long voltage, long amperage )
{
long amperesUsed = 0L;
if( outputs.isEmpty() )
{
try
{
for( PartP2PGTCEPower o : PartP2PGTCEPower.this.getOutputs() )
outputs.add( o );
}
catch( GridAccessException e )
{
e.printStackTrace();
}
}
voltage = (long) ( voltage * 0.95 );
if( voltage > 0 )
{
while ( !outputs.isEmpty() )
{
PartP2PGTCEPower target = outputs.poll();
final IEnergyContainer output = target.getAttachedEnergyStorage();
if( output == null || !output.inputsEnergy( facing ) || output.getEnergyCanBeInserted() <= 0 )
{
continue;
}
amperesUsed += output.acceptEnergyFromNetwork( facing, voltage, amperage - amperesUsed );
if( amperage >= amperesUsed )
{
break;
}
}
}
return amperesUsed;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return true;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
}
static class NullEnergyStorage implements IEnergyContainer
{
@Override
public long acceptEnergyFromNetwork( EnumFacing enumFacing, long l, long l1 )
{
return 0;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return false;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long getEnergyStored()
{
return 0;
}
@Override
public long getEnergyCapacity()
{
return 0;
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
}
}
@@ -208,7 +208,8 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
boolean pasteAsOutput = true; boolean pasteAsOutput = true;
ItemStack is = player.getHeldItem( hand ); ItemStack is = player.getHeldItem( hand );
if (is.isEmpty()) { if( is.isEmpty() )
{
pasteAsOutput = false; pasteAsOutput = false;
is = player.getHeldItemOffhand(); is = player.getHeldItemOffhand();
} }
@@ -282,7 +283,7 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
final IParts parts = AEApi.instance().definitions().parts(); final IParts parts = AEApi.instance().definitions().parts();
switch( tt ) switch ( tt )
{ {
case LIGHT: case LIGHT:
newType = parts.p2PTunnelLight().maybeStack( 1 ).orElse( ItemStack.EMPTY ); newType = parts.p2PTunnelLight().maybeStack( 1 ).orElse( ItemStack.EMPTY );
@@ -292,6 +293,10 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
newType = parts.p2PTunnelFE().maybeStack( 1 ).orElse( ItemStack.EMPTY ); newType = parts.p2PTunnelFE().maybeStack( 1 ).orElse( ItemStack.EMPTY );
break; break;
case GTEU_POWER:
newType = parts.p2PTunnelGTEU().maybeStack( 1 ).orElse( ItemStack.EMPTY );
break;
case FLUID: case FLUID:
newType = parts.p2PTunnelFluids().maybeStack( 1 ).orElse( ItemStack.EMPTY ); newType = parts.p2PTunnelFluids().maybeStack( 1 ).orElse( ItemStack.EMPTY );
break; break;
@@ -451,8 +456,10 @@ public abstract class PartP2PTunnel<T extends PartP2PTunnel> extends PartBasicSt
final AEColor[] colors = Platform.p2p().toColors( this.getFrequency() ); final AEColor[] colors = Platform.p2p().toColors( this.getFrequency() );
final int[] colorCode = new int[]{ final int[] colorCode = new int[]{
colors[0].ordinal(), colors[0].ordinal(), colors[1].ordinal(), colors[1].ordinal(), colors[0].ordinal(), colors[0].ordinal(),
colors[2].ordinal(), colors[2].ordinal(), colors[3].ordinal(), colors[3].ordinal(), colors[1].ordinal(), colors[1].ordinal(),
colors[2].ordinal(), colors[2].ordinal(),
colors[3].ordinal(), colors[3].ordinal(),
}; };
data.setIntArray( "colorCode", colorCode ); data.setIntArray( "colorCode", colorCode );
@@ -17,6 +17,8 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import java.util.List;
import static appeng.helpers.PatternHelper.PROCESSING_INPUT_LIMIT; import static appeng.helpers.PatternHelper.PROCESSING_INPUT_LIMIT;
import static appeng.helpers.PatternHelper.PROCESSING_OUTPUT_LIMIT; import static appeng.helpers.PatternHelper.PROCESSING_OUTPUT_LIMIT;
@@ -43,6 +45,18 @@ public class PartExpandedProcessingPatternTerminal extends AbstractPartTerminal
super( is ); super( is );
} }
@Override
public void getDrops( final List<ItemStack> drops, final boolean wrenched )
{
for( final ItemStack is : this.pattern )
{
if( !is.isEmpty() )
{
drops.add( is );
}
}
}
@Override @Override
public void readFromNBT( NBTTagCompound data ) public void readFromNBT( NBTTagCompound data )
{ {
@@ -0,0 +1,77 @@
/*
* 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.parts.reporting;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import appeng.api.parts.IPartModel;
import appeng.core.AppEng;
import appeng.core.sync.GuiBridge;
import appeng.items.parts.PartModels;
import appeng.parts.PartModel;
import appeng.util.Platform;
public class PartInterfaceConfigurationTerminal extends AbstractPartDisplay
{
@PartModels
public static final ResourceLocation MODEL_OFF = new ResourceLocation( AppEng.MOD_ID, "part/interface_configuration_terminal_off" );
@PartModels
public static final ResourceLocation MODEL_ON = new ResourceLocation( AppEng.MOD_ID, "part/interface_configuration_terminal_on" );
public static final IPartModel MODELS_OFF = new PartModel( MODEL_BASE, MODEL_OFF, MODEL_STATUS_OFF );
public static final IPartModel MODELS_ON = new PartModel( MODEL_BASE, MODEL_ON, MODEL_STATUS_ON );
public static final IPartModel MODELS_HAS_CHANNEL = new PartModel( MODEL_BASE, MODEL_ON, MODEL_STATUS_HAS_CHANNEL );
public String in = "";
public PartInterfaceConfigurationTerminal( final ItemStack is )
{
super( is );
}
@Override
public boolean onPartActivate( final EntityPlayer player, final EnumHand hand, final Vec3d pos )
{
if( !super.onPartActivate( player, hand, pos ) )
{
if( Platform.isServer() )
{
Platform.openGUI( player, this.getHost().getTile(), this.getSide(), GuiBridge.GUI_INTERFACE_CONFIGURATION_TERMINAL );
}
}
return true;
}
@Override
public IPartModel getStaticModels()
{
return this.selectModel( MODELS_OFF, MODELS_ON, MODELS_HAS_CHANNEL );
}
public void saveSearchStrings( String in )
{
this.in = in;
}
}
@@ -20,8 +20,18 @@ package appeng.tile.crafting;
import java.io.IOException; import java.io.IOException;
import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map;
import appeng.api.networking.security.IActionSource;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IStorageMonitorable;
import appeng.api.storage.IStorageMonitorableAccessor;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.capabilities.Capabilities;
import appeng.helpers.PatternHelper;
import appeng.me.helpers.MachineSource;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.InventoryCrafting;
@@ -30,6 +40,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLCommonHandler;
@@ -86,6 +97,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
private final AppEngInternalInventory patternInv = new AppEngInternalInventory( this, 1, 1 ); private final AppEngInternalInventory patternInv = new AppEngInternalInventory( this, 1, 1 );
private final IItemHandler gridInvExt = new WrapperFilteredItemHandler( this.gridInv, new CraftingGridFilter() ); private final IItemHandler gridInvExt = new WrapperFilteredItemHandler( this.gridInv, new CraftingGridFilter() );
private final IItemHandler internalInv = new WrapperChainedItemHandler( this.gridInv, this.patternInv ); private final IItemHandler internalInv = new WrapperChainedItemHandler( this.gridInv, this.patternInv );
private final EnumMap<EnumFacing, Object> neighbors = new EnumMap<>( EnumFacing.class );
private final IConfigManager settings; private final IConfigManager settings;
private final UpgradeInventory upgrades; private final UpgradeInventory upgrades;
private boolean isPowered = false; private boolean isPowered = false;
@@ -96,6 +108,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
private boolean isAwake = false; private boolean isAwake = false;
private boolean forcePlan = false; private boolean forcePlan = false;
private boolean reboot = true; private boolean reboot = true;
private final IActionSource mySrc = new MachineSource( this );
public TileMolecularAssembler() public TileMolecularAssembler()
{ {
@@ -114,6 +127,126 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
return 5; return 5;
} }
public void updateNeighbors()
{
for( EnumFacing f : EnumFacing.VALUES )
{
TileEntity te = world.getTileEntity( pos.offset( f ) );
Object capability = null;
if( te != null )
{
// Prioritize a handler to directly link to another ME network
IStorageMonitorableAccessor accessor = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, f.getOpposite() );
if( accessor != null )
{
IStorageMonitorable inventory = accessor.getInventory( this.mySrc );
if( inventory != null )
{
capability = inventory;
}
}
if( capability == null )
{
capability = InventoryAdaptor.getAdaptor( te, f.getOpposite() );
}
}
if( capability != null )
{
neighbors.put( f, capability );
}
else
{
neighbors.remove( f );
}
}
}
@Override
public void onReady()
{
super.onReady();
updateNeighbors();
}
public void updateNeighbors( IBlockAccess w, BlockPos pos, BlockPos neighbor )
{
EnumFacing updateFromFacing;
if( pos.getX() != neighbor.getX() )
{
if( pos.getX() > neighbor.getX() )
{
updateFromFacing = EnumFacing.WEST;
}
else
{
updateFromFacing = EnumFacing.EAST;
}
}
else if( pos.getY() != neighbor.getY() )
{
if( pos.getY() > neighbor.getY() )
{
updateFromFacing = EnumFacing.DOWN;
}
else
{
updateFromFacing = EnumFacing.UP;
}
}
else if( pos.getZ() != neighbor.getZ() )
{
if( pos.getZ() > neighbor.getZ() )
{
updateFromFacing = EnumFacing.NORTH;
}
else
{
updateFromFacing = EnumFacing.SOUTH;
}
}
else
{
return;
}
if( pos.offset( updateFromFacing ).equals( neighbor ) )
{
TileEntity te = w.getTileEntity( neighbor );
Object capability = null;
if( te != null )
{
// Prioritize a handler to directly link to another ME network
IStorageMonitorableAccessor accessor = te.getCapability( Capabilities.STORAGE_MONITORABLE_ACCESSOR, updateFromFacing.getOpposite() );
if( accessor != null )
{
IStorageMonitorable inventory = accessor.getInventory( this.mySrc );
if( inventory != null )
{
capability = inventory;
}
}
if( capability == null )
{
capability = InventoryAdaptor.getAdaptor( te, updateFromFacing.getOpposite() );
}
}
if( capability != null )
{
neighbors.put( updateFromFacing, capability );
}
else
{
neighbors.remove( updateFromFacing );
}
}
}
@Override @Override
public boolean pushPattern( final ICraftingPatternDetails patternDetails, final InventoryCrafting table, final EnumFacing where ) public boolean pushPattern( final ICraftingPatternDetails patternDetails, final InventoryCrafting table, final EnumFacing where )
{ {
@@ -143,7 +276,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
private void updateSleepiness() private void updateSleepiness()
{ {
final boolean wasEnabled = this.isAwake; final boolean wasEnabled = this.isAwake;
this.isAwake = this.myPlan != null && this.hasMats() || this.canPush(); this.isAwake = this.canPush() || this.myPlan != null && this.hasMats();
if( wasEnabled != this.isAwake ) if( wasEnabled != this.isAwake )
{ {
try try
@@ -179,9 +312,13 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
for( int x = 0; x < this.craftingInv.getSizeInventory(); x++ ) for( int x = 0; x < this.craftingInv.getSizeInventory(); x++ )
{ {
this.craftingInv.setInventorySlotContents( x, this.gridInv.getStackInSlot( x ) ); this.craftingInv.setInventorySlotContents( x, this.gridInv.getStackInSlot( x ) );
if( !myPlan.isValidItemForSlot( x, craftingInv.getStackInSlot( x ), world ) )
{
return false;
}
} }
return !this.myPlan.getOutput( this.craftingInv, this.getWorld() ).isEmpty(); return this.myPlan.getOutputs().length > 0;
} }
@Override @Override
@@ -425,7 +562,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
this.reboot = false; this.reboot = false;
int speed = 10; int speed = 10;
switch( this.upgrades.getInstalledUpgrades( Upgrades.SPEED ) ) switch ( this.upgrades.getInstalledUpgrades( Upgrades.SPEED ) )
{ {
case 0: case 0:
this.progress += this.userPower( ticksSinceLastCall, speed = 10, 1.0 ); this.progress += this.userPower( ticksSinceLastCall, speed = 10, 1.0 );
@@ -458,7 +595,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
final ItemStack output = this.myPlan.getOutput( this.craftingInv, this.getWorld() ); final ItemStack output = this.myPlan.getOutput( this.craftingInv, this.getWorld() );
if( !output.isEmpty() ) if( !output.isEmpty() )
{ {
this.pushOut( output.copy() ); this.pushOut( output );
for( int x = 0; x < this.craftingInv.getSizeInventory(); x++ ) for( int x = 0; x < this.craftingInv.getSizeInventory(); x++ )
{ {
@@ -519,10 +656,7 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
{ {
try try
{ {
return (int) ( this.getProxy() return (int) ( this.getProxy().getEnergy().extractAEPower( ticksPassed * bonusValue * acceleratorTax, Actionable.MODULATE, PowerMultiplier.CONFIG ) / acceleratorTax );
.getEnergy()
.extractAEPower( ticksPassed * bonusValue * acceleratorTax, Actionable.MODULATE,
PowerMultiplier.CONFIG ) / acceleratorTax );
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
{ {
@@ -534,9 +668,13 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
{ {
if( this.pushDirection == AEPartLocation.INTERNAL ) if( this.pushDirection == AEPartLocation.INTERNAL )
{ {
for( final EnumFacing d : EnumFacing.VALUES ) for( final Map.Entry<EnumFacing, Object> d : neighbors.entrySet() )
{ {
output = this.pushTo( output, d ); output = this.pushTo( output, d.getKey() );
if( output.isEmpty() )
{
break;
}
} }
} }
else else
@@ -560,27 +698,42 @@ public class TileMolecularAssembler extends AENetworkInvTile implements IUpgrade
return output; return output;
} }
final TileEntity te = this.getWorld().getTileEntity( this.pos.offset( d ) ); Object capability = neighbors.get( d );
if( capability instanceof IStorageMonitorable )
if( te == null )
{ {
return output; // Prioritize a handler to directly link to another ME network
IStorageMonitorable inventory = (IStorageMonitorable) capability;
IAEItemStack toInsert = AEItemStack.fromItemStack( output );
IMEMonitor<IAEItemStack> inv = inventory.getInventory( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) );
IAEItemStack remainder = inv.injectItems( toInsert, Actionable.SIMULATE, this.mySrc );
if( remainder == null )
{
inv.injectItems( toInsert, Actionable.MODULATE, this.mySrc );
return ItemStack.EMPTY;
}
else
{
if( remainder.getStackSize() == toInsert.getStackSize() )
{
return output;
}
inv.injectItems( toInsert.setStackSize( toInsert.getStackSize() - remainder.getStackSize() ), Actionable.MODULATE, this.mySrc );
this.saveChanges();
return remainder.createItemStack();
}
} }
else if( capability instanceof InventoryAdaptor )
final InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor( te, d.getOpposite() );
if( adaptor == null )
{ {
return output; InventoryAdaptor adaptor = (InventoryAdaptor) capability;
}
final int size = output.getCount(); final int size = output.getCount();
output = adaptor.addItems( output ); output = adaptor.addItems( output );
final int newSize = output.isEmpty() ? 0 : output.getCount(); final int newSize = output.isEmpty() ? 0 : output.getCount();
if( size != newSize ) if( size != newSize )
{ {
this.saveChanges(); this.saveChanges();
}
} }
return output; return output;
@@ -77,6 +77,10 @@ public class AppEngInternalInventory extends ItemStackHandler implements Iterabl
@Override @Override
public void setStackInSlot( int slot, @Nonnull ItemStack stack ) public void setStackInSlot( int slot, @Nonnull ItemStack stack )
{ {
if( stack == this.getStackInSlot( slot ) )
{
return;
}
this.previousStack = this.getStackInSlot( slot ).copy(); this.previousStack = this.getStackInSlot( slot ).copy();
super.setStackInSlot( slot, stack ); super.setStackInSlot( slot, stack );
} }
@@ -119,14 +123,15 @@ public class AppEngInternalInventory extends ItemStackHandler implements Iterabl
if( this.getTileEntity() != null && this.eventsEnabled() && !this.dirtyFlag ) if( this.getTileEntity() != null && this.eventsEnabled() && !this.dirtyFlag )
{ {
this.dirtyFlag = true; this.dirtyFlag = true;
ItemStack newStack = this.getStackInSlot( slot ).copy(); ItemStack newStack = this.getStackInSlot( slot );
ItemStack oldStack = this.previousStack; ItemStack oldStack = this.previousStack;
InvOperation op = InvOperation.SET; InvOperation op = InvOperation.SET;
if( newStack.isEmpty() || oldStack.isEmpty() || ( oldStack.getCount() < oldStack.getMaxStackSize() && oldStack.getCount() < this.getSlotLimit( slot ) && ItemStack.areItemsEqual( newStack, oldStack ) ) ) if( newStack.isEmpty() || oldStack.isEmpty() || oldStack.getCount() != newStack.getCount() && ItemStack.areItemsEqual( newStack, oldStack ) )
{ {
if( newStack.getCount() > oldStack.getCount() ) if( newStack.getCount() > oldStack.getCount() )
{ {
newStack = newStack.copy();
newStack.shrink( oldStack.getCount() ); newStack.shrink( oldStack.getCount() );
oldStack = ItemStack.EMPTY; oldStack = ItemStack.EMPTY;
op = InvOperation.INSERT; op = InvOperation.INSERT;
@@ -24,6 +24,10 @@ import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import appeng.core.AEConfig;
import appeng.core.features.AEFeature;
import appeng.util.item.OreHelper;
import appeng.util.item.OreReference;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -184,11 +188,17 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid
if( myItem.isEmpty() ) if( myItem.isEmpty() )
{ {
ItemStack held = player.inventory.getCurrentItem(); ItemStack held = player.inventory.getCurrentItem();
if( !held.isEmpty() )
if( AEApi.instance().definitions().materials().certusQuartzCrystal().isSameAs( held ) || Platform.isChargeable( held ) )
{ {
held = player.inventory.decrStackSize( player.inventory.currentItem, 1 ); if( AEConfig.instance().isFeatureEnabled( AEFeature.CERTUS ) )
this.inv.setStackInSlot( 0, held ); {
final IMaterials materials = AEApi.instance().definitions().materials();
if( AEItemStack.fromItemStack( held ).sameOre( AEItemStack.fromItemStack( materials.certusQuartzCrystal().maybeStack( 1 ).orElse( ItemStack.EMPTY ) ) ) || Platform.isChargeable( held ) )
{
held = player.inventory.decrStackSize( player.inventory.currentItem, 1 );
this.inv.setStackInSlot( 0, held );
}
}
} }
} }
else else
@@ -254,7 +264,7 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid
} }
} }
} }
else if( this.getInternalCurrentPower() > POWER_THRESHOLD && materials.certusQuartzCrystal().isSameAs( myItem ) ) else if( this.getInternalCurrentPower() > POWER_THRESHOLD && ( materials.certusQuartzCrystal().isSameAs( myItem ) || AEItemStack.fromItemStack( myItem ).sameOre( AEItemStack.fromItemStack( materials.certusQuartzCrystal().maybeStack( 1 ).orElse( ItemStack.EMPTY ) ) ) ) )
{ {
if( Platform.getRandomFloat() > 0.8f ) // simulate wait if( Platform.getRandomFloat() > 0.8f ) // simulate wait
{ {
@@ -298,9 +308,7 @@ public class TileCharger extends AENetworkPowerTile implements ICrankable, IGrid
@Override @Override
public boolean allowInsert( IItemHandler inv, final int i, final ItemStack itemstack ) public boolean allowInsert( IItemHandler inv, final int i, final ItemStack itemstack )
{ {
final IItemDefinition cert = AEApi.instance().definitions().materials().certusQuartzCrystal(); return AEItemStack.fromItemStack( itemstack ).sameOre( AEItemStack.fromItemStack( AEApi.instance().definitions().materials().certusQuartzCrystal().maybeStack( 1 ).orElse( ItemStack.EMPTY ) ) ) || Platform.isChargeable( itemstack );
return Platform.isChargeable( itemstack ) || cert.isSameAs( itemstack );
} }
@Override @Override
@@ -125,7 +125,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
final double requiredPower = this.getRequiredPower(); final double requiredPower = this.getRequiredPower();
final ItemStack output = this.getOutput(); final ItemStack output = this.getOutput();
while( requiredPower <= this.getStoredPower() && !output.isEmpty() && requiredPower > 0 ) while ( requiredPower <= this.getStoredPower() && !output.isEmpty() && requiredPower > 0 )
{ {
if( this.canAddOutput( output ) ) if( this.canAddOutput( output ) )
{ {
@@ -163,7 +163,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
{ {
final IMaterials materials = AEApi.instance().definitions().materials(); final IMaterials materials = AEApi.instance().definitions().materials();
switch( (CondenserOutput) this.cm.getSetting( Settings.CONDENSER_OUTPUT ) ) switch ( (CondenserOutput) this.cm.getSetting( Settings.CONDENSER_OUTPUT ) )
{ {
case MATTER_BALLS: case MATTER_BALLS:
return materials.matterBall().maybeStack( 1 ).orElse( ItemStack.EMPTY ); return materials.matterBall().maybeStack( 1 ).orElse( ItemStack.EMPTY );
@@ -193,6 +193,24 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
{ {
if( inv == this.outputSlot ) if( inv == this.outputSlot )
{ {
if( !removed.isEmpty() )
{
final double requiredPower = this.getRequiredPower();
final ItemStack output = this.getOutput();
while ( requiredPower <= this.getStoredPower() && !output.isEmpty() && requiredPower > 0 )
{
if( this.canAddOutput( output ) )
{
this.setStoredPower( this.getStoredPower() - requiredPower );
this.addOutput( output );
}
else
{
break;
}
removed.shrink( output.getCount() );
}
}
this.meHandler.outputChanged( added, removed ); this.meHandler.outputChanged( added, removed );
} }
} }
@@ -296,7 +314,7 @@ public class TileCondenser extends AEBaseInvTile implements IConfigManagerHost,
} }
} }
private static final IFluidTankProperties[] EMPTY = { new FluidTankProperties( null, Fluid.BUCKET_VOLUME, true, false ) }; private static final IFluidTankProperties[] EMPTY = {new FluidTankProperties( null, Fluid.BUCKET_VOLUME, true, false )};
/** /**
* A fluid handler that exposes a 1 bucket tank that can only be filled, and - when filled - will add power * A fluid handler that exposes a 1 bucket tank that can only be filled, and - when filled - will add power
@@ -57,10 +57,16 @@ public class TileEnergyAcceptor extends AENetworkPowerTile
} }
catch( final GridAccessException e ) catch( final GridAccessException e )
{ {
return this.getInternalMaxPower(); return 0;
} }
} }
@Override
public double getInternalMaxPower()
{
return getFunnelPowerDemand( Long.MAX_VALUE );
}
@Override @Override
protected double funnelPowerIntoStorage( final double power, final Actionable mode ) protected double funnelPowerIntoStorage( final double power, final Actionable mode )
{ {
@@ -53,7 +53,7 @@ public abstract class AEBasePoweredTile extends AEBaseInvTile implements IAEPowe
private EnumSet<EnumFacing> internalPowerSides = EnumSet.allOf( EnumFacing.class ); private EnumSet<EnumFacing> internalPowerSides = EnumSet.allOf( EnumFacing.class );
private final IEnergyStorage forgeEnergyAdapter; private final IEnergyStorage forgeEnergyAdapter;
private Object teslaEnergyAdapter; private Object teslaEnergyAdapter;
private GTCEEnergyAdapter gtceEnergyAdapter = null;
private IC2PowerSink ic2Sink; private IC2PowerSink ic2Sink;
public AEBasePoweredTile() public AEBasePoweredTile()
@@ -63,6 +63,11 @@ public abstract class AEBasePoweredTile extends AEBaseInvTile implements IAEPowe
{ {
this.teslaEnergyAdapter = new TeslaEnergyAdapter( this ); this.teslaEnergyAdapter = new TeslaEnergyAdapter( this );
} }
if( Capabilities.GTCE_ENERGY != null )
{
this.gtceEnergyAdapter = new GTCEEnergyAdapter( this );
}
this.ic2Sink = Integrations.ic2().createPowerSink( this, this ); this.ic2Sink = Integrations.ic2().createPowerSink( this, this );
this.ic2Sink.setValidFaces( this.internalPowerSides ); this.ic2Sink.setValidFaces( this.internalPowerSides );
} }
@@ -284,6 +289,13 @@ public abstract class AEBasePoweredTile extends AEBaseInvTile implements IAEPowe
return true; return true;
} }
} }
else if( capability == Capabilities.GTCE_ENERGY )
{
if( this.getPowerSides().contains( facing ) )
{
return true;
}
}
return super.hasCapability( capability, facing ); return super.hasCapability( capability, facing );
} }
@@ -306,6 +318,13 @@ public abstract class AEBasePoweredTile extends AEBaseInvTile implements IAEPowe
return (T) this.teslaEnergyAdapter; return (T) this.teslaEnergyAdapter;
} }
} }
else if( capability == Capabilities.GTCE_ENERGY )
{
if( this.getPowerSides().contains( facing ) )
{
return (T) this.gtceEnergyAdapter;
}
}
return super.getCapability( capability, facing ); return super.getCapability( capability, facing );
} }
@@ -0,0 +1,89 @@
package appeng.tile.powersink;
import appeng.api.config.Actionable;
import appeng.api.config.PowerUnits;
import gregtech.api.capability.IEnergyContainer;
import net.minecraft.util.EnumFacing;
public class GTCEEnergyAdapter implements IEnergyContainer
{
private final IExternalPowerSink sink;
double EUBuffer;
GTCEEnergyAdapter( IExternalPowerSink sink )
{
this.sink = sink;
}
@Override
public long acceptEnergyFromNetwork( EnumFacing enumFacing, long voltage, long amperage )
{
final double power = voltage * amperage;
final double oldBuffer = EUBuffer;
EUBuffer = this.sink.injectExternalPower( PowerUnits.GTEU, power + EUBuffer, Actionable.MODULATE );
// if the overflow went down, all inputs were consumed
if( EUBuffer <= oldBuffer )
{
return amperage;
}
// if overflow is greater than the inputs, nothing was consumed
if( EUBuffer >= power )
{
EUBuffer -= power;
return 0;
}
// determine how many amps are being used
final double usedEU = power + oldBuffer - EUBuffer;
final long ampsUsed = (long) Math.ceil( usedEU / ( (double) voltage ) );
// adjust the overflow
EUBuffer += usedEU % voltage;
return ampsUsed;
}
@Override
public boolean inputsEnergy( EnumFacing enumFacing )
{
return true;
}
@Override
public long changeEnergy( long l )
{
return 0;
}
@Override
public long getEnergyStored()
{
return (long) Math.floor( PowerUnits.AE.convertTo( PowerUnits.GTEU, this.sink.getAECurrentPower() ) );
}
@Override
public long getEnergyCapacity()
{
return (long) Math.floor( PowerUnits.AE.convertTo( PowerUnits.GTEU, this.sink.getAEMaxPower() ) );
}
@Override
public long getInputAmperage()
{
return 0;
}
@Override
public long getInputVoltage()
{
return 0;
}
@Override
public long getEnergyCanBeInserted()
{
return this.getEnergyCapacity() - this.getEnergyStored();
}
}
@@ -128,7 +128,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
public TileChest() public TileChest()
{ {
this.setInternalMaxPower( PowerMultiplier.CONFIG.multiply( 40 ) ); this.setInternalMaxPower( PowerMultiplier.CONFIG.multiply( 128 ) );
this.getProxy().setFlags( GridFlags.REQUIRE_CHANNEL ); this.getProxy().setFlags( GridFlags.REQUIRE_CHANNEL );
this.config.registerSetting( Settings.SORT_BY, SortOrder.NAME ); this.config.registerSetting( Settings.SORT_BY, SortOrder.NAME );
this.config.registerSetting( Settings.VIEW_MODE, ViewItems.ALL ); this.config.registerSetting( Settings.VIEW_MODE, ViewItems.ALL );
@@ -541,7 +541,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
if( this.cellHandler != null && this.cellHandler.getChannel() == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) ) if( this.cellHandler != null && this.cellHandler.getChannel() == AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ) )
{ {
final IAEItemStack returns = Platform.poweredInsert( this, this.cellHandler, final IAEItemStack returns = Platform.poweredInsert( this, this.cellHandler,
AEItemStack.fromItemStack( this.inputInventory.getStackInSlot( 0 ) ), this.mySrc ); AEItemStack.fromItemStack( this.inputInventory.getStackInSlot( 0 ) ), this.mySrc );
if( returns == null ) if( returns == null )
{ {
@@ -698,7 +698,8 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
{ {
TileChest.this.getProxy().getStorage().postAlterationOfStoredItems( this.chan, change, TileChest.this.mySrc ); TileChest.this.getProxy().getStorage().postAlterationOfStoredItems( this.chan, change, TileChest.this.mySrc );
} }
} catch ( final GridAccessException e ) }
catch( final GridAccessException e )
{ {
// :( // :(
} }
@@ -738,11 +739,11 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
return input; return input;
} }
T injected = super.injectItems( input, mode, src ); T injected = super.injectItems( input, mode, src );
if (mode == Actionable.MODULATE && ( injected == null || injected.getStackSize() != input.getStackSize() )) if( mode == Actionable.MODULATE && ( injected == null || injected.getStackSize() != input.getStackSize() ) )
{ {
if( TileChest.this.getProxy().isActive() && this.getInternalHandler().getCellInv() != null ) if( TileChest.this.isPowered() && this.getInternalHandler().getCellInv() != null )
{ {
TileChest.this.cellHandler.postChangesToListeners(Collections.singletonList( input.copy().setStackSize( input.getStackSize() - ( injected == null ? 0 : injected.getStackSize() ) ) ), TileChest.this.mySrc ); TileChest.this.cellHandler.postChangesToListeners( Collections.singletonList( input.copy().setStackSize( input.getStackSize() - ( injected == null ? 0 : injected.getStackSize() ) ) ), TileChest.this.mySrc );
} }
} }
return injected; return injected;
@@ -792,9 +793,9 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
T extracted = super.extractItems( request, mode, src ); T extracted = super.extractItems( request, mode, src );
if( mode == Actionable.MODULATE && extracted != null ) if( mode == Actionable.MODULATE && extracted != null )
{ {
if( TileChest.this.getProxy().isActive() && this.getInternalHandler().getCellInv() != null ) if( TileChest.this.isPowered() && this.getInternalHandler().getCellInv() != null )
{ {
TileChest.this.cellHandler.postChangesToListeners(Collections.singletonList( request.copy().setStackSize( -extracted.getStackSize() ) ), TileChest.this.mySrc ); TileChest.this.cellHandler.postChangesToListeners( Collections.singletonList( request.copy().setStackSize( -extracted.getStackSize() ) ), TileChest.this.mySrc );
} }
} }
return extracted; return extracted;
@@ -848,7 +849,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
private class FluidHandler implements IFluidHandler private class FluidHandler implements IFluidHandler
{ {
private final IFluidTankProperties[] TANK_PROPS = new IFluidTankProperties[] { new FluidTankProperties( null, Fluid.BUCKET_VOLUME ) }; private final IFluidTankProperties[] TANK_PROPS = new IFluidTankProperties[]{new FluidTankProperties( null, Fluid.BUCKET_VOLUME )};
@Override @Override
public int fill( final FluidStack resource, final boolean doFill ) public int fill( final FluidStack resource, final boolean doFill )
@@ -858,7 +859,7 @@ public class TileChest extends AENetworkPowerTile implements IMEChest, ITerminal
.getChannel() == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) ) .getChannel() == AEApi.instance().storage().getStorageChannel( IFluidStorageChannel.class ) )
{ {
final IAEFluidStack results = Platform.poweredInsert( TileChest.this, TileChest.this.cellHandler, AEFluidStack.fromFluidStack( resource ), final IAEFluidStack results = Platform.poweredInsert( TileChest.this, TileChest.this.cellHandler, AEFluidStack.fromFluidStack( resource ),
TileChest.this.mySrc, doFill ? Actionable.MODULATE : Actionable.SIMULATE ); TileChest.this.mySrc, doFill ? Actionable.MODULATE : Actionable.SIMULATE );
if( results == null ) if( results == null )
{ {
+96 -52
View File
@@ -19,6 +19,8 @@
package appeng.util; package appeng.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.InvalidParameterException; import java.security.InvalidParameterException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
@@ -36,6 +38,11 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import gregtech.api.block.machines.BlockMachine;
import gregtech.api.items.IToolItem;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.util.GTUtility;
import ic2.api.item.ICustomDamageItem;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@@ -64,6 +71,7 @@ import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.RegistryNamespaced; import net.minecraft.util.registry.RegistryNamespaced;
import net.minecraft.util.text.translation.I18n; import net.minecraft.util.text.translation.I18n;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
@@ -73,6 +81,8 @@ import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.Optional;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary; import net.minecraftforge.oredict.OreDictionary;
@@ -134,6 +144,8 @@ import appeng.util.prioritylist.IPartitionList;
* @version rv2 * @version rv2
* @since rv0 * @since rv0
*/ */
@Optional.Interface( iface = "gregtech.api.items.IToolItem", modid = "gregtech" )
@Optional.Interface( iface = "ic2.api.item.ICustomDamageItem", modid = "IC2" )
public class Platform public class Platform
{ {
@@ -152,6 +164,7 @@ public class Platform
private static final ItemComparisonHelper ITEM_COMPARISON_HELPER = new ItemComparisonHelper(); private static final ItemComparisonHelper ITEM_COMPARISON_HELPER = new ItemComparisonHelper();
private static final P2PHelper P2P_HELPER = new P2PHelper(); private static final P2PHelper P2P_HELPER = new P2PHelper();
private static Method reflectGTgetMTE;
public static ItemComparisonHelper itemComparisons() public static ItemComparisonHelper itemComparisons()
{ {
@@ -176,9 +189,8 @@ public class Platform
/** /**
* This displays the value for encoded longs ( double *100 ) * This displays the value for encoded longs ( double *100 )
* *
* @param n to be formatted long value * @param n to be formatted long value
* @param isRate if true it adds a /t to the formatted string * @param isRate if true it adds a /t to the formatted string
*
* @return formatted long value * @return formatted long value
*/ */
public static String formatPowerLong( final long n, final boolean isRate ) public static String formatPowerLong( final long n, final boolean isRate )
@@ -188,12 +200,14 @@ public class Platform
final PowerUnits displayUnits = AEConfig.instance().selectedPowerUnit(); final PowerUnits displayUnits = AEConfig.instance().selectedPowerUnit();
p = PowerUnits.AE.convertTo( displayUnits, p ); p = PowerUnits.AE.convertTo( displayUnits, p );
final String[] preFixes = { "k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y" }; final String[] preFixes = {
"k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y"
};
String unitName = displayUnits.name(); String unitName = displayUnits.name();
String level = ""; String level = "";
int offset = 0; int offset = 0;
while( p > 1000 && offset < preFixes.length ) while ( p > 1000 && offset < preFixes.length )
{ {
p /= 1000; p /= 1000;
level = preFixes[offset]; level = preFixes[offset];
@@ -210,7 +224,7 @@ public class Platform
final int west_y = forward.zOffset * up.xOffset - forward.xOffset * up.zOffset; final int west_y = forward.zOffset * up.xOffset - forward.xOffset * up.zOffset;
final int west_z = forward.xOffset * up.yOffset - forward.yOffset * up.xOffset; final int west_z = forward.xOffset * up.yOffset - forward.yOffset * up.xOffset;
switch( west_x + west_y * 2 + west_z * 3 ) switch ( west_x + west_y * 2 + west_z * 3 )
{ {
case 1: case 1:
return AEPartLocation.EAST; return AEPartLocation.EAST;
@@ -237,7 +251,7 @@ public class Platform
final int west_y = forward.getFrontOffsetZ() * up.getFrontOffsetX() - forward.getFrontOffsetX() * up.getFrontOffsetZ(); final int west_y = forward.getFrontOffsetZ() * up.getFrontOffsetX() - forward.getFrontOffsetX() * up.getFrontOffsetZ();
final int west_z = forward.getFrontOffsetX() * up.getFrontOffsetY() - forward.getFrontOffsetY() * up.getFrontOffsetX(); final int west_z = forward.getFrontOffsetX() * up.getFrontOffsetY() - forward.getFrontOffsetY() * up.getFrontOffsetX();
switch( west_x + west_y * 2 + west_z * 3 ) switch ( west_x + west_y * 2 + west_z * 3 )
{ {
case 1: case 1:
return EnumFacing.EAST; return EnumFacing.EAST;
@@ -271,8 +285,7 @@ public class Platform
{ {
ce = nextEnum( ce ); ce = nextEnum( ce );
} }
} } while ( !validOptions.contains( ce ) || isNotValidSetting( ce ) );
while( !validOptions.contains( ce ) || isNotValidSetting( ce ) );
return ce; return ce;
} }
@@ -446,7 +459,7 @@ public class Platform
{ {
if( upAndDown ) if( upAndDown )
{ {
switch( dir ) switch ( dir )
{ {
case NORTH: case NORTH:
return AEPartLocation.SOUTH; return AEPartLocation.SOUTH;
@@ -466,7 +479,7 @@ public class Platform
} }
else else
{ {
switch( dir ) switch ( dir )
{ {
case UP: case UP:
return AEPartLocation.DOWN; return AEPartLocation.DOWN;
@@ -519,8 +532,7 @@ public class Platform
final double offset_x = ( getRandomInt() % 32 - 16 ) / 82; final double offset_x = ( getRandomInt() % 32 - 16 ) / 82;
final double offset_y = ( getRandomInt() % 32 - 16 ) / 82; final double offset_y = ( getRandomInt() % 32 - 16 ) / 82;
final double offset_z = ( getRandomInt() % 32 - 16 ) / 82; final double offset_z = ( getRandomInt() % 32 - 16 ) / 82;
final EntityItem ei = new EntityItem( w, 0.5 + offset_x + pos.getX(), 0.5 + offset_y + pos.getY(), 0.2 + offset_z + pos.getZ(), i final EntityItem ei = new EntityItem( w, 0.5 + offset_x + pos.getX(), 0.5 + offset_y + pos.getY(), 0.2 + offset_z + pos.getZ(), i.copy() );
.copy() );
w.spawnEntity( ei ); w.spawnEntity( ei );
} }
} }
@@ -592,8 +604,7 @@ public class Platform
try try
{ {
ITooltipFlag.TooltipFlags tooltipFlag = Minecraft ITooltipFlag.TooltipFlags tooltipFlag = Minecraft.getMinecraft().gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL;
.getMinecraft().gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL;
return itemStack.getTooltip( Minecraft.getMinecraft().player, tooltipFlag ); return itemStack.getTooltip( Minecraft.getMinecraft().player, tooltipFlag );
} }
catch( final Exception errB ) catch( final Exception errB )
@@ -764,7 +775,7 @@ public class Platform
public static int MC2MEColor( final int color ) public static int MC2MEColor( final int color )
{ {
switch( color ) switch ( color )
{ {
case 4: // "blue" case 4: // "blue"
return 0; return 0;
@@ -842,10 +853,10 @@ public class Platform
return forward; return forward;
} }
switch( forward ) switch ( forward )
{ {
case DOWN: case DOWN:
switch( axis ) switch ( axis )
{ {
case DOWN: case DOWN:
return forward; return forward;
@@ -864,7 +875,7 @@ public class Platform
} }
break; break;
case UP: case UP:
switch( axis ) switch ( axis )
{ {
case NORTH: case NORTH:
return AEPartLocation.WEST; return AEPartLocation.WEST;
@@ -879,7 +890,7 @@ public class Platform
} }
break; break;
case NORTH: case NORTH:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return AEPartLocation.WEST; return AEPartLocation.WEST;
@@ -894,7 +905,7 @@ public class Platform
} }
break; break;
case SOUTH: case SOUTH:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return AEPartLocation.EAST; return AEPartLocation.EAST;
@@ -909,7 +920,7 @@ public class Platform
} }
break; break;
case EAST: case EAST:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return AEPartLocation.NORTH; return AEPartLocation.NORTH;
@@ -923,7 +934,7 @@ public class Platform
break; break;
} }
case WEST: case WEST:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return AEPartLocation.SOUTH; return AEPartLocation.SOUTH;
@@ -944,10 +955,10 @@ public class Platform
public static EnumFacing rotateAround( final EnumFacing forward, final EnumFacing axis ) public static EnumFacing rotateAround( final EnumFacing forward, final EnumFacing axis )
{ {
switch( forward ) switch ( forward )
{ {
case DOWN: case DOWN:
switch( axis ) switch ( axis )
{ {
case DOWN: case DOWN:
return forward; return forward;
@@ -966,7 +977,7 @@ public class Platform
} }
break; break;
case UP: case UP:
switch( axis ) switch ( axis )
{ {
case NORTH: case NORTH:
return EnumFacing.WEST; return EnumFacing.WEST;
@@ -981,7 +992,7 @@ public class Platform
} }
break; break;
case NORTH: case NORTH:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return EnumFacing.WEST; return EnumFacing.WEST;
@@ -996,7 +1007,7 @@ public class Platform
} }
break; break;
case SOUTH: case SOUTH:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return EnumFacing.EAST; return EnumFacing.EAST;
@@ -1011,7 +1022,7 @@ public class Platform
} }
break; break;
case EAST: case EAST:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return EnumFacing.NORTH; return EnumFacing.NORTH;
@@ -1025,7 +1036,7 @@ public class Platform
break; break;
} }
case WEST: case WEST:
switch( axis ) switch ( axis )
{ {
case UP: case UP:
return EnumFacing.SOUTH; return EnumFacing.SOUTH;
@@ -1101,9 +1112,7 @@ public class Platform
final Vec3d vec31 = vec3.addVector( f7 * d3, f6 * d3, f8 * d3 ); final Vec3d vec31 = vec3.addVector( f7 * d3, f6 * d3, f8 * d3 );
final AxisAlignedBB bb = new AxisAlignedBB( Math.min( vec3.x, vec31.x ), Math.min( vec3.y, vec31.y ), Math.min( vec3.z, final AxisAlignedBB bb = new AxisAlignedBB( Math.min( vec3.x, vec31.x ), Math.min( vec3.y, vec31.y ), Math.min( vec3.z, vec31.z ), Math.max( vec3.x, vec31.x ), Math.max( vec3.y, vec31.y ), Math.max( vec3.z, vec31.z ) ).grow( 16, 16, 16 );
vec31.z ), Math.max( vec3.x, vec31.x ), Math.max( vec3.y, vec31.y ), Math.max( vec3.z, vec31.z ) ).grow(
16, 16, 16 );
Entity entity = null; Entity entity = null;
double closest = 9999999.0D; double closest = 9999999.0D;
@@ -1226,7 +1235,7 @@ public class Platform
Preconditions.checkNotNull( src ); Preconditions.checkNotNull( src );
Preconditions.checkNotNull( mode ); Preconditions.checkNotNull( mode );
final T possible = cell.injectItems( input.copy(), Actionable.SIMULATE, src ); final T possible = cell.injectItems( input, Actionable.SIMULATE, src );
long stored = input.getStackSize(); long stored = input.getStackSize();
if( possible != null ) if( possible != null )
@@ -1249,15 +1258,15 @@ public class Platform
final T leftover = input.copy(); final T leftover = input.copy();
final T split = input.copy(); final T split = input.copy();
leftover.decStackSize(itemToAdd); leftover.decStackSize( itemToAdd );
split.setStackSize(itemToAdd); split.setStackSize( itemToAdd );
leftover.add(cell.injectItems(split, Actionable.MODULATE, src)); leftover.add( cell.injectItems( split, Actionable.MODULATE, src ) );
src.player().ifPresent( player -> src.player().ifPresent( player ->
{ {
final long diff = original - leftover.getStackSize(); final long diff = original - leftover.getStackSize();
Stats.ItemsInserted.addToPlayer( player, (int) diff ); Stats.ItemsInserted.addToPlayer( player, (int) diff );
} ); } );
return leftover; return leftover;
} }
@@ -1265,10 +1274,10 @@ public class Platform
final T ret = cell.injectItems( input, Actionable.MODULATE, src ); final T ret = cell.injectItems( input, Actionable.MODULATE, src );
src.player().ifPresent( player -> src.player().ifPresent( player ->
{ {
final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize(); final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize();
Stats.ItemsInserted.addToPlayer( player, (int) diff ); Stats.ItemsInserted.addToPlayer( player, (int) diff );
} ); } );
return ret; return ret;
} }
@@ -1282,7 +1291,7 @@ public class Platform
return input; return input;
} }
@SuppressWarnings( { "rawtypes", "unchecked" } ) @SuppressWarnings( {"rawtypes", "unchecked"} )
public static void postChanges( final IStorageGrid gs, final ItemStack removed, final ItemStack added, final IActionSource src ) public static void postChanges( final IStorageGrid gs, final ItemStack removed, final ItemStack added, final IActionSource src )
{ {
for( final IStorageChannel<?> chan : AEApi.instance().storage().storageChannels() ) for( final IStorageChannel<?> chan : AEApi.instance().storage().storageChannels() )
@@ -1361,8 +1370,7 @@ public class Platform
final String locationA = a.getGridBlock().isWorldAccessible() ? a.getGridBlock().getLocation().toString() : "notInWorld"; final String locationA = a.getGridBlock().isWorldAccessible() ? a.getGridBlock().getLocation().toString() : "notInWorld";
final String locationB = b.getGridBlock().isWorldAccessible() ? b.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}]", 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 );
a_isSecure, a.getLastSecurityKey(), a.getPlayerID(), locationA, b_isSecure, b.getLastSecurityKey(), b.getPlayerID(), locationB );
} }
// can't do that son... // can't do that son...
@@ -1423,7 +1431,7 @@ public class Platform
float yaw = 0.0f; float yaw = 0.0f;
// player.yOffset = 1.8f; // player.yOffset = 1.8f;
switch( side ) switch ( side )
{ {
case DOWN: case DOWN:
pitch = 90.0f; pitch = 90.0f;
@@ -1513,16 +1521,14 @@ public class Platform
} }
} }
final boolean checkFuzzy = ae_req.getOre().isPresent() || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE || providedTemplate final boolean checkFuzzy = ae_req.getOre().isPresent() || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE || providedTemplate.hasTagCompound() || providedTemplate.isItemStackDamageable();
.hasTagCompound() || providedTemplate.isItemStackDamageable();
if( items != null && checkFuzzy ) if( items != null && checkFuzzy )
{ {
for( final IAEItemStack x : items ) for( final IAEItemStack x : items )
{ {
final ItemStack sh = x.getDefinition(); final ItemStack sh = x.getDefinition();
if( ( Platform.itemComparisons().isEqualItemType( providedTemplate, sh ) || ae_req.sameOre( x ) ) && !ItemStack.areItemsEqual( sh, if( ( Platform.itemComparisons().isEqualItemType( providedTemplate, sh ) || ae_req.sameOre( x ) ) && !ItemStack.areItemsEqual( sh, output ) )
output ) )
{ // Platform.isSameItemType( sh, providedTemplate ) { // Platform.isSameItemType( sh, providedTemplate )
final ItemStack cp = sh.copy(); final ItemStack cp = sh.copy();
cp.setCount( 1 ); cp.setCount( 1 );
@@ -1681,4 +1687,42 @@ public class Platform
return isPurified; return isPurified;
} }
//consider methods below moving to a compability class
public static boolean isGTDamageableItem( Item item )
{
return ( isModLoaded( "gregtech" ) && item instanceof IToolItem );
}
public static MetaTileEntity getMetaTileEntity( IBlockAccess world, BlockPos pos )
{
if( reflectGTgetMTE == null )
{
try
{
reflectGTgetMTE = ReflectionHelper.findMethod( BlockMachine.class, "getMetaTileEntity", null, IBlockAccess.class, BlockPos.class );
}
catch( ReflectionHelper.UnableToFindMethodException e )
{
reflectGTgetMTE = ReflectionHelper.findMethod( GTUtility.class, "getMetaTileEntity", null, IBlockAccess.class, BlockPos.class );
}
}
else
{
try
{
return (MetaTileEntity) reflectGTgetMTE.invoke( reflectGTgetMTE, world, pos );
}
catch( IllegalAccessException | InvocationTargetException e )
{
e.printStackTrace();
}
}
return null;
}
public static boolean isIC2DamageableItem( Item item )
{
return ( isModLoaded( "IC2" ) && item instanceof ICustomDamageItem );
}
} }
@@ -19,14 +19,13 @@
package appeng.util.inv; package appeng.util.inv;
import java.util.Iterator;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.util.InventoryAdaptor; import appeng.util.InventoryAdaptor;
import appeng.util.Platform; import appeng.util.Platform;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import java.util.Iterator;
public class AdaptorItemHandler extends InventoryAdaptor public class AdaptorItemHandler extends InventoryAdaptor
@@ -60,13 +59,13 @@ public class AdaptorItemHandler extends InventoryAdaptor
if( destination != null ) if( destination != null )
{ {
ItemStack extracted = this.itemHandler.extractItem( slot, amount, true ); if( !destination.canInsert( is ) )
if( extracted.isEmpty() )
{ {
continue; break;
} }
if( !destination.canInsert( extracted ) ) ItemStack extracted = this.itemHandler.extractItem( slot, amount, true );
if( extracted.isEmpty() )
{ {
continue; continue;
} }
@@ -109,21 +108,20 @@ public class AdaptorItemHandler extends InventoryAdaptor
final ItemStack is = this.itemHandler.getStackInSlot( slot ); final ItemStack is = this.itemHandler.getStackInSlot( slot );
if( !is.isEmpty() && ( filter.isEmpty() || Platform.itemComparisons().isSameItem( is, filter ) ) ) if( !is.isEmpty() && ( filter.isEmpty() || Platform.itemComparisons().isSameItem( is, filter ) ) )
{ {
ItemStack extracted = this.itemHandler.extractItem( slot, amount, true ); if( destination != null )
{
if( !destination.canInsert( is ) )
{
break;
}
}
ItemStack extracted = this.itemHandler.extractItem( slot, amount, true );
if( extracted.isEmpty() ) if( extracted.isEmpty() )
{ {
continue; continue;
} }
if( destination != null )
{
if( !destination.canInsert( extracted ) )
{
continue;
}
}
if( rv.isEmpty() ) if( rv.isEmpty() )
{ {
// Use the first stack as a template for the result // Use the first stack as a template for the result
@@ -163,13 +161,13 @@ public class AdaptorItemHandler extends InventoryAdaptor
if( destination != null ) if( destination != null )
{ {
ItemStack simulated = this.itemHandler.extractItem( slot, amount, true ); if( !destination.canInsert( is ) )
if( simulated.isEmpty() )
{ {
continue; continue;
} }
if( !destination.canInsert( simulated ) ) ItemStack simulated = this.itemHandler.extractItem( slot, amount, true );
if( simulated.isEmpty() )
{ {
continue; continue;
} }
@@ -177,6 +175,10 @@ public class AdaptorItemHandler extends InventoryAdaptor
// Attempt extracting it // Attempt extracting it
extracted = this.itemHandler.extractItem( slot, amount, false ); extracted = this.itemHandler.extractItem( slot, amount, false );
if( !extracted.isEmpty() )
{
return extracted;
}
} }
return extracted; return extracted;
@@ -196,15 +198,16 @@ public class AdaptorItemHandler extends InventoryAdaptor
continue; continue;
} }
if( destination != null && !destination.canInsert( is ) )
{
continue;
}
// Attempt extracting it // Attempt extracting it
extracted = this.itemHandler.extractItem( slot, amount, true ); extracted = this.itemHandler.extractItem( slot, amount, true );
if( !extracted.isEmpty() )
if( !extracted.isEmpty() && destination != null )
{ {
if( !destination.canInsert( extracted ) ) return extracted;
{
extracted = ItemStack.EMPTY; // Keep on looking...
}
} }
} }
@@ -223,26 +226,28 @@ public class AdaptorItemHandler extends InventoryAdaptor
return this.addItems( toBeSimulated, true ); return this.addItems( toBeSimulated, true );
} }
protected ItemStack addItems( final ItemStack itemsToAdd, final boolean simulate ) protected ItemStack addItems( ItemStack itemsToAdd, final boolean simulate )
{ {
if( itemsToAdd.isEmpty() ) if( itemsToAdd.isEmpty() )
{ {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
ItemStack left = itemsToAdd.copy();
for( int slot = 0; slot < this.itemHandler.getSlots(); slot++ ) for( int slot = 0; slot < this.itemHandler.getSlots(); slot++ )
{ {
left = this.itemHandler.insertItem( slot, left, simulate ); if( !simulate )
{
itemsToAdd = itemsToAdd.copy();
}
itemsToAdd = this.itemHandler.insertItem( slot, itemsToAdd, simulate );
if( left.isEmpty() ) if( itemsToAdd.isEmpty() )
{ {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
} }
return left; return itemsToAdd;
} }
@Override @Override
@@ -12,198 +12,201 @@ import java.util.Iterator;
public class AdaptorItemRepository extends InventoryAdaptor public class AdaptorItemRepository extends InventoryAdaptor
{ {
protected final IItemRepository itemRepository; protected final IItemRepository itemRepository;
public AdaptorItemRepository( IItemRepository itemRepository ) public AdaptorItemRepository( IItemRepository itemRepository )
{ {
this.itemRepository = itemRepository; this.itemRepository = itemRepository;
} }
@Override @Override
public ItemStack removeItems( int amount, ItemStack filter, IInventoryDestination destination ) public ItemStack removeItems( int amount, ItemStack filter, IInventoryDestination destination )
{ {
ItemStack rv = ItemStack.EMPTY; ItemStack rv = ItemStack.EMPTY;
ItemStack extracted = ItemStack.EMPTY; ItemStack extracted = ItemStack.EMPTY;
if( !filter.isEmpty() ) if( !filter.isEmpty() )
{ {
extracted = this.itemRepository.extractItem( filter, amount, true ); extracted = this.itemRepository.extractItem( filter, amount, true );
} }
else else
{ {
for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() ) for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() )
{ {
extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true ); extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true );
if( !extracted.isEmpty() ) if( !extracted.isEmpty() )
{ {
break; break;
} }
} }
} }
if( destination != null ) if( destination != null )
{ {
if( extracted.isEmpty() || !destination.canInsert( extracted ) ) if( extracted.isEmpty() || !destination.canInsert( extracted ) )
{ {
return rv; return rv;
} }
} }
extracted = this.itemRepository.extractItem( filter, amount, false ); extracted = this.itemRepository.extractItem( filter.isEmpty() ? extracted : filter, amount, false );
return extracted; return extracted;
} }
@Override @Override
public ItemStack simulateRemove( int amount, ItemStack filter, IInventoryDestination destination ) public ItemStack simulateRemove( int amount, ItemStack filter, IInventoryDestination destination )
{ {
ItemStack rv = ItemStack.EMPTY; ItemStack rv = ItemStack.EMPTY;
ItemStack extracted = ItemStack.EMPTY; ItemStack extracted = ItemStack.EMPTY;
if( !filter.isEmpty() ) if( !filter.isEmpty() )
{ {
extracted = this.itemRepository.extractItem( filter, amount, true ); extracted = this.itemRepository.extractItem( filter, amount, true );
} }
else else
{ {
for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() ) for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() )
{ {
extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true ); extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true );
if( !extracted.isEmpty() ) if( !extracted.isEmpty() )
{ {
break; break;
} }
} }
} }
if( destination != null ) if( destination != null )
{ {
if( extracted.isEmpty() || !destination.canInsert( extracted ) ) if( extracted.isEmpty() || !destination.canInsert( extracted ) )
{ {
return rv; return rv;
} }
} }
return extracted; return extracted;
} }
@Override @Override
public ItemStack removeSimilarItems( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination ) public ItemStack removeSimilarItems( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination )
{ {
ItemStack rv = ItemStack.EMPTY; ItemStack rv = ItemStack.EMPTY;
ItemStack extracted = ItemStack.EMPTY; ItemStack extracted = ItemStack.EMPTY;
for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() ) for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() )
{ {
if( Platform.itemComparisons().isFuzzyEqualItem( record.itemPrototype, filter, fuzzyMode ) ) if( Platform.itemComparisons().isFuzzyEqualItem( record.itemPrototype, filter, fuzzyMode ) )
{ {
extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true ); extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true );
} }
if( !extracted.isEmpty() ) if( !extracted.isEmpty() )
{ {
break; break;
} }
} }
if( destination != null ) if( destination != null )
{ {
if( extracted.isEmpty() || !destination.canInsert( extracted ) ) if( extracted.isEmpty() || !destination.canInsert( extracted ) )
{ {
return rv; return rv;
} }
} }
extracted = this.itemRepository.extractItem( extracted, amount, false ); extracted = this.itemRepository.extractItem( extracted, amount, false );
return extracted; return extracted;
} }
@Override @Override
public ItemStack simulateSimilarRemove( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination ) public ItemStack simulateSimilarRemove( int amount, ItemStack filter, FuzzyMode fuzzyMode, IInventoryDestination destination )
{ {
ItemStack rv = ItemStack.EMPTY; ItemStack rv = ItemStack.EMPTY;
ItemStack extracted = ItemStack.EMPTY; ItemStack extracted = ItemStack.EMPTY;
for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() ) for( IItemRepository.ItemRecord record : this.itemRepository.getAllItems() )
{ {
if( Platform.itemComparisons().isFuzzyEqualItem( record.itemPrototype, filter, fuzzyMode ) ) if( Platform.itemComparisons().isFuzzyEqualItem( record.itemPrototype, filter, fuzzyMode ) )
{ {
extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true ); extracted = this.itemRepository.extractItem( record.itemPrototype, amount, true );
} }
if( !extracted.isEmpty() ) if( !extracted.isEmpty() )
{ {
break; break;
} }
} }
if( destination != null ) if( destination != null )
{ {
if( extracted.isEmpty() || !destination.canInsert( extracted ) ) if( extracted.isEmpty() || !destination.canInsert( extracted ) )
{ {
return rv; return rv;
} }
} }
return extracted; return extracted;
} }
@Override @Override
public ItemStack addItems( ItemStack toBeAdded ) public ItemStack addItems( ItemStack toBeAdded )
{ {
return this.addItems( toBeAdded, false ); return this.addItems( toBeAdded, false );
} }
protected ItemStack addItems( final ItemStack itemsToAdd, final boolean simulate ) protected ItemStack addItems( ItemStack itemsToAdd, final boolean simulate )
{ {
if( itemsToAdd.isEmpty() ) if( itemsToAdd.isEmpty() )
{ {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
ItemStack left = itemsToAdd.copy(); if( !simulate )
{
itemsToAdd = itemsToAdd.copy();
}
left = this.itemRepository.insertItem( left, simulate ); itemsToAdd = this.itemRepository.insertItem( itemsToAdd, simulate );
if( left.isEmpty() ) if( itemsToAdd.isEmpty() )
{ {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
return left; return itemsToAdd;
} }
@Override @Override
public ItemStack simulateAdd( ItemStack toBeSimulated ) public ItemStack simulateAdd( ItemStack toBeSimulated )
{ {
return this.addItems( toBeSimulated, true ); return this.addItems( toBeSimulated, true );
} }
@Override @Override
public boolean containsItems() public boolean containsItems()
{ {
return !this.itemRepository.getAllItems().isEmpty(); return !this.itemRepository.getAllItems().isEmpty();
} }
@Override @Override
public boolean hasSlots() public boolean hasSlots()
{ {
return true; return true;
} }
@Override @Override
public Iterator<ItemSlot> iterator() public Iterator<ItemSlot> iterator()
{ {
return null; return null;
} }
} }
@@ -0,0 +1,26 @@
package appeng.util.inv;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public abstract class BlockingInventoryAdaptor implements Iterable<ItemSlot>
{
public static BlockingInventoryAdaptor getAdaptor( final TileEntity te, final EnumFacing d )
{
if( te != null && te.hasCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, d ) )
{
// Attempt getting an IItemHandler for the given side via caps
IItemHandler itemHandler = te.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, d );
if( itemHandler != null )
{
return new BlockingItemHandler( itemHandler, te.getBlockType().getRegistryName().getResourceDomain() );
}
}
return null;
}
public abstract boolean containsBlockingItems();
}
@@ -0,0 +1,54 @@
package appeng.util.inv;
import appeng.helpers.NonBlockingItems;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import java.util.Iterator;
public class BlockingItemHandler extends BlockingInventoryAdaptor
{
protected final IItemHandler itemHandler;
private final String domain;
public BlockingItemHandler( IItemHandler itemHandler, String domain )
{
this.itemHandler = itemHandler;
this.domain = domain;
}
boolean isBlockableItem( ItemStack stack )
{
Object2ObjectOpenHashMap<Item, IntSet> map = NonBlockingItems.INSTANCE.getMap().get( domain );
if( map.get( stack.getItem() ) != null )
{
return !map.get( stack.getItem() ).contains( stack.getMetadata() );
}
return true;
}
@Override
public boolean containsBlockingItems()
{
int slots = this.itemHandler.getSlots();
for( int slot = 0; slot < slots; slot++ )
{
ItemStack is = this.itemHandler.getStackInSlot( slot );
if( !is.isEmpty() && isBlockableItem( is ) )
{
return true;
}
}
return false;
}
@Override
public Iterator<ItemSlot> iterator()
{
return new ItemHandlerIterator( this.itemHandler );
}
}
+327 -225
View File
@@ -25,6 +25,9 @@ import java.util.Optional;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.google.common.primitives.Ints;
import gregtech.api.items.IToolItem;
import ic2.api.item.ICustomDamageItem;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -41,279 +44,378 @@ import appeng.api.storage.data.IAEItemStack;
import appeng.core.Api; import appeng.core.Api;
import appeng.util.Platform; import appeng.util.Platform;
public final class AEItemStack extends AEStack<IAEItemStack> implements IAEItemStack {
private static final String NBT_STACKSIZE = "Cnt";
private static final String NBT_REQUESTABLE = "Req";
private static final String NBT_CRAFTABLE = "Craft";
private final AESharedItemStack sharedStack; public class AEItemStack extends AEStack<IAEItemStack> implements IAEItemStack
private Optional<OreReference> oreReference; {
private static final String NBT_STACKSIZE = "Cnt";
private static final String NBT_REQUESTABLE = "Req";
private static final String NBT_CRAFTABLE = "Craft";
@SideOnly(Side.CLIENT) private final AESharedItemStack sharedStack;
private String displayName; private Optional<OreReference> oreReference;
@SideOnly(Side.CLIENT)
private List<String> tooltip;
private AEItemStack(final AEItemStack is) { @SideOnly( Side.CLIENT )
this.setStackSize(is.getStackSize()); private String displayName;
this.setCraftable(is.isCraftable()); @SideOnly( Side.CLIENT )
this.setCountRequestable(is.getCountRequestable()); private List<String> tooltip;
this.sharedStack = is.sharedStack; private ItemStack cachedItemStack;
this.oreReference = is.oreReference;
}
private AEItemStack(final AESharedItemStack is, long size) { private AEItemStack( final AEItemStack is )
this.sharedStack = is; {
this.setStackSize(size); this.setStackSize( is.getStackSize() );
this.setCraftable(false); this.setCraftable( is.isCraftable() );
this.setCountRequestable(0); this.setCountRequestable( is.getCountRequestable() );
this.oreReference = OreHelper.INSTANCE.getOre( is.getDefinition() ); this.sharedStack = is.sharedStack;
} this.oreReference = is.oreReference;
this.cachedItemStack = is.cachedItemStack;
}
@Nullable private AEItemStack( final AESharedItemStack is, long size )
public static AEItemStack fromItemStack(@Nonnull final ItemStack stack) { {
if (stack.isEmpty()) { this.sharedStack = is;
return null; this.setStackSize( size );
} this.setCraftable( false );
this.setCountRequestable( 0 );
this.oreReference = OreHelper.INSTANCE.getOre( is.getDefinition() );
}
return new AEItemStack(AEItemStackRegistry.getRegisteredStack(stack), stack.getCount()); @Nullable
} public static AEItemStack fromItemStack( @Nonnull final ItemStack stack )
{
if( stack.isEmpty() )
{
return null;
}
public static IAEItemStack fromNBT( final NBTTagCompound i ) return new AEItemStack( AEItemStackRegistry.getRegisteredStack( stack ), stack.getCount() );
{ }
if( i == null )
{
return null;
}
final ItemStack itemstack = new ItemStack( i ); public static IAEItemStack fromNBT( final NBTTagCompound i )
if( itemstack.isEmpty() ) {
{ if( i == null )
return null; {
} return null;
}
final AEItemStack item = AEItemStack.fromItemStack( itemstack ); final ItemStack itemstack = new ItemStack( i );
if( itemstack.isEmpty() )
{
return null;
}
item.setStackSize(i.getLong(NBT_STACKSIZE)); final AEItemStack item = AEItemStack.fromItemStack( itemstack );
item.setCountRequestable(i.getLong(NBT_REQUESTABLE));
item.setCraftable(i.getBoolean(NBT_CRAFTABLE));
return item;
}
@Override item.setStackSize( i.getLong( NBT_STACKSIZE ) );
public void writeToNBT(final NBTTagCompound i) { item.setCountRequestable( i.getLong( NBT_REQUESTABLE ) );
this.getDefinition().writeToNBT( i ); item.setCraftable( i.getBoolean( NBT_CRAFTABLE ) );
return item;
}
i.setLong(NBT_STACKSIZE, this.getStackSize()); @Override
i.setLong(NBT_REQUESTABLE, this.getCountRequestable()); public void writeToNBT( final NBTTagCompound i )
i.setBoolean(NBT_CRAFTABLE, this.isCraftable()); {
} this.getDefinition().writeToNBT( i );
public static AEItemStack fromPacket( final ByteBuf data ) i.setLong( NBT_STACKSIZE, this.getStackSize() );
{ i.setLong( NBT_REQUESTABLE, this.getCountRequestable() );
final byte mask = data.readByte(); i.setBoolean( NBT_CRAFTABLE, this.isCraftable() );
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 ); }
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0;
final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) ); public static AEItemStack fromPacket( final ByteBuf data )
final long stackSize = getPacketValue( stackType, data ); {
final long countRequestable = getPacketValue( countReqType, data ); final byte mask = data.readByte();
final byte stackType = (byte) ( ( mask & 0x0C ) >> 2 );
final byte countReqType = (byte) ( ( mask & 0x30 ) >> 4 );
final boolean isCraftable = ( mask & 0x40 ) > 0;
if( itemstack.isEmpty() ) final ItemStack itemstack = new ItemStack( ByteBufUtils.readTag( data ) );
{ final long stackSize = getPacketValue( stackType, data );
return null; final long countRequestable = getPacketValue( countReqType, data );
}
final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize ); if( itemstack.isEmpty() )
item.setCountRequestable( countRequestable ); {
item.setCraftable( isCraftable ); return null;
return item; }
}
@Override final AEItemStack item = new AEItemStack( AEItemStackRegistry.getRegisteredStack( itemstack ), stackSize );
public void writeToPacket( final ByteBuf i ) item.setCountRequestable( countRequestable );
{ item.setCraftable( isCraftable );
final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this return item;
.getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 ); }
i.writeByte( mask ); @Override
ByteBufUtils.writeTag( i, this.getDefinition().serializeNBT() ); public void writeToPacket( final ByteBuf i )
this.putPacketValue( i, this.getStackSize() ); {
this.putPacketValue( i, this.getCountRequestable() ); final byte mask = (byte) ( ( this.getType( this.getStackSize() ) << 2 ) | ( this.getType( this.getCountRequestable() ) << 4 ) | ( (byte) ( this.isCraftable() ? 1 : 0 ) << 6 ) | ( this.hasTagCompound() ? 1 : 0 ) << 7 );
}
@Override i.writeByte( mask );
public void add(final IAEItemStack option) { ByteBufUtils.writeTag( i, this.getDefinition().serializeNBT() );
if (option == null) { this.putPacketValue( i, this.getStackSize() );
return; this.putPacketValue( i, this.getCountRequestable() );
} }
this.incStackSize(option.getStackSize()); @Override
this.setCountRequestable(this.getCountRequestable() + option.getCountRequestable()); public void add( final IAEItemStack option )
this.setCraftable(this.isCraftable() || option.isCraftable()); {
} if( option == null )
{
return;
}
@Override this.incStackSize( option.getStackSize() );
public boolean fuzzyComparison(final IAEItemStack other, final FuzzyMode mode) { this.setCountRequestable( this.getCountRequestable() + option.getCountRequestable() );
final ItemStack itemStack = this.getDefinition(); this.setCraftable( this.isCraftable() || option.isCraftable() );
final ItemStack otherStack = other.getDefinition(); }
return this.fuzzyItemStackComparison(itemStack, otherStack, mode); @Override
} public boolean fuzzyComparison( final IAEItemStack other, final FuzzyMode mode )
{
final ItemStack itemStack = this.getDefinition();
final ItemStack otherStack = other.getDefinition();
@Override return this.fuzzyItemStackComparison( itemStack, otherStack, mode );
public IAEItemStack copy() { }
return new AEItemStack(this);
}
@Override @Override
public boolean isItem() public IAEItemStack copy()
{ {
return true; return new AEItemStack( this );
} }
@Override @Override
public boolean isFluid() public boolean isItem()
{ {
return false; return true;
} }
@Override @Override
public IStorageChannel<IAEItemStack> getChannel() { public boolean isFluid()
return Api.INSTANCE.storage().getStorageChannel(IItemStorageChannel.class); {
} return false;
}
@Override @Override
public ItemStack createItemStack() { public IStorageChannel<IAEItemStack> getChannel()
return ItemHandlerHelper.copyStackWithSize(this.getDefinition(), {
(int) Math.min(Integer.MAX_VALUE, this.getStackSize())); return Api.INSTANCE.storage().getStorageChannel( IItemStorageChannel.class );
} }
@Override @Override
public Item getItem() { public ItemStack createItemStack()
return this.getDefinition().getItem(); {
} return ItemHandlerHelper.copyStackWithSize( this.getDefinition(), (int) Math.min( Integer.MAX_VALUE, this.getStackSize() ) );
}
@Override @Override
public int getItemDamage() { public Item getItem()
return this.sharedStack.getItemDamage(); {
} return this.getDefinition().getItem();
}
@Override @Override
public boolean sameOre( final IAEItemStack is ) public int getItemDamage()
{ {
return OreHelper.INSTANCE.sameOre( this, is ); return this.sharedStack.getItemDamage();
} }
@Override @Override
public boolean isSameType(final IAEItemStack otherStack) { public boolean sameOre( final IAEItemStack is )
if (otherStack == null) { {
return false; return OreHelper.INSTANCE.sameOre( this, is );
} }
return Objects.equals(this.sharedStack, ((AEItemStack) otherStack).sharedStack); @Override
} public boolean isSameType( final IAEItemStack otherStack )
{
if( otherStack == null )
{
return false;
}
@Override return Objects.equals( this.sharedStack, ( (AEItemStack) otherStack ).sharedStack );
public boolean isSameType(final ItemStack otherStack) { }
if (otherStack.isEmpty()) {
return false;
}
int oldSize = otherStack.getCount();
otherStack.setCount(1); @Override
boolean ret = ItemStack.areItemStacksEqual(this.getDefinition(), otherStack); public boolean isSameType( final ItemStack otherStack )
otherStack.setCount(oldSize); {
if( otherStack.isEmpty() )
{
return false;
}
int oldSize = otherStack.getCount();
return ret; otherStack.setCount( 1 );
} boolean ret = ItemStack.areItemStacksEqual( this.getDefinition(), otherStack );
otherStack.setCount( oldSize );
@Override return ret;
public int hashCode() { }
return this.sharedStack.hashCode();
}
@Override @Override
public boolean equals(final Object ia) { public int hashCode()
if (ia instanceof AEItemStack) { {
return this.isSameType((AEItemStack) ia); return this.sharedStack.hashCode();
} else if (ia instanceof ItemStack) { }
// this actually breaks the equals contract (being equals to unrelated classes)
return equals((ItemStack) ia);
}
return false;
}
@Override @Override
public boolean equals(final ItemStack is) { public boolean equals( final Object ia )
return this.isSameType(is); {
} if( ia instanceof AEItemStack )
{
return this.isSameType( (AEItemStack) ia );
}
else if( ia instanceof ItemStack )
{
// this actually breaks the equals contract (being equals to unrelated classes)
return equals( (ItemStack) ia );
}
return false;
}
@Override @Override
public String toString() { public boolean equals( final ItemStack is )
return this.getStackSize() + "x" + this.getDefinition().getItem().getRegistryName(); {
} return this.isSameType( is );
}
@SideOnly(Side.CLIENT) @Override
public List<String> getToolTip() { public ItemStack getCachedItemStack( long stackSize )
if (this.tooltip == null) { {
this.tooltip = Platform.getTooltip(this.asItemStackRepresentation()); if( this.cachedItemStack != null )
} {
return this.tooltip; ItemStack currentCached = this.cachedItemStack;
} this.cachedItemStack = null;
currentCached.setCount( Ints.saturatedCast( stackSize ) );
return currentCached;
}
@SideOnly(Side.CLIENT) ItemStack itemStack = this.createItemStack();
public String getDisplayName() { itemStack.setCount( Ints.saturatedCast( stackSize ) );
if (this.displayName == null) {
this.displayName = Platform.getItemDisplayName(this.asItemStackRepresentation());
}
return this.displayName;
}
@SideOnly(Side.CLIENT) return itemStack;
public String getModID() { }
return this.getDefinition().getItem().getRegistryName().getResourceDomain();
}
public Optional<OreReference> getOre() @Override
{ public void setCachedItemStack( ItemStack itemStack )
return this.oreReference; {
} this.cachedItemStack = itemStack;
}
@Override @Override
public boolean hasTagCompound() { public String toString()
return this.getDefinition().hasTagCompound(); {
} return this.getStackSize() + "x" + this.getDefinition().getItem().getRegistryName();
}
@Override @SideOnly( Side.CLIENT )
public ItemStack asItemStackRepresentation() { public List<String> getToolTip()
return this.getDefinition().copy(); {
} if( this.tooltip == null )
{
this.tooltip = Platform.getTooltip( this.asItemStackRepresentation() );
}
return this.tooltip;
}
@Override @SideOnly( Side.CLIENT )
public ItemStack getDefinition() { public String getDisplayName()
return this.sharedStack.getDefinition(); {
} if( this.displayName == null )
{
this.displayName = Platform.getItemDisplayName( this.asItemStackRepresentation() );
}
return this.displayName;
}
AESharedItemStack getSharedStack() { @SideOnly( Side.CLIENT )
return this.sharedStack; public String getModID()
} {
return this.getDefinition().getItem().getRegistryName().getResourceDomain();
}
private boolean fuzzyItemStackComparison(ItemStack a, ItemStack b, FuzzyMode mode) { public Optional<OreReference> getOre()
if (a.getItem() == b.getItem() && a.getItem().isDamageable()) { {
if (mode == FuzzyMode.IGNORE_ALL) { return this.oreReference;
return true; }
} else if (mode == FuzzyMode.PERCENT_99) {
return a.getItemDamage() > 1 == b.getItemDamage() > 1;
} else {
final float percentDamageOfA = (float) a.getItemDamage() / a.getMaxDamage();
final float percentDamageOfB = (float) b.getItemDamage() / b.getMaxDamage();
return percentDamageOfA > mode.breakPoint == percentDamageOfB > mode.breakPoint; @Override
} public boolean hasTagCompound()
} {
return this.getDefinition().hasTagCompound();
}
@Override
public ItemStack asItemStackRepresentation()
{
return this.getDefinition().copy();
}
@Override
public ItemStack getDefinition()
{
return this.sharedStack.getDefinition();
}
AESharedItemStack getSharedStack()
{
return this.sharedStack;
}
private boolean fuzzyItemStackComparison( ItemStack a, ItemStack b, FuzzyMode mode )
{
if( a.getItem() == b.getItem() && ( a.getItem().isDamageable() || Platform.isGTDamageableItem( a.getItem() ) ) )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
if( a.getItem().isDamageable() )
{
return true;
}
else if( Platform.isGTDamageableItem( a.getItem() ) )
{
return a.getItemDamage() == b.getItemDamage();
}
}
else if( mode == FuzzyMode.PERCENT_99 )
{
if( Platform.isIC2DamageableItem( a.getItem() ) )
{
return ( (ICustomDamageItem) a.getItem() ).getCustomDamage( a ) > 1 == ( (ICustomDamageItem) b.getItem() ).getCustomDamage( b ) > 1;
}
else if( a.getItem().isDamageable() )
{
return a.getItemDamage() > 1 == b.getItemDamage() > 1;
}
else if( Platform.isGTDamageableItem( a.getItem() ) )
{
return ( (IToolItem) a.getItem() ).getItemDamage( a ) > 1 == ( (IToolItem) b.getItem() ).getItemDamage( b ) > 1;
}
}
else
{
float percentDamageOfA = 0;
float percentDamageOfB = 0;
if( Platform.isIC2DamageableItem( a.getItem() ) )
{
percentDamageOfA = (float) ( (ICustomDamageItem) a.getItem() ).getCustomDamage( a ) / ( (ICustomDamageItem) a.getItem() ).getMaxCustomDamage( a );
percentDamageOfB = (float) ( (ICustomDamageItem) b.getItem() ).getCustomDamage( b ) / ( (ICustomDamageItem) b.getItem() ).getMaxCustomDamage( b );
}
else if( a.getItem().isDamageable() )
{
percentDamageOfA = (float) a.getItemDamage() / a.getMaxDamage();
percentDamageOfB = (float) b.getItemDamage() / b.getMaxDamage();
}
else if( Platform.isGTDamageableItem( a.getItem() ) )
{
percentDamageOfA = (float) ( (IToolItem) a.getItem() ).getItemDamage( a ) / ( (IToolItem) a.getItem() ).getMaxItemDamage( a );
percentDamageOfB = (float) ( (IToolItem) b.getItem() ).getItemDamage( b ) / ( (IToolItem) b.getItem() ).getMaxItemDamage( b );
}
return percentDamageOfA > mode.breakPoint == percentDamageOfB > mode.breakPoint;
}
}
return false;
}
return false;
}
} }
@@ -22,72 +22,78 @@ import java.util.Objects;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
final class AESharedItemStack {
private final ItemStack itemStack; final class AESharedItemStack
private final int itemId; {
private final int itemDamage;
private final int hashCode;
public AESharedItemStack(final ItemStack itemStack) { private final ItemStack itemStack;
this(itemStack, itemStack.getItemDamage()); private final int itemDamage;
} private final int hashCode;
/** public AESharedItemStack( final ItemStack itemStack )
* A constructor to explicitly set the damage value and not fetch it from the {@link ItemStack} {
* this( itemStack, itemStack.getItemDamage() );
* @param itemStack The {@link ItemStack} to filter }
* @param damage The damage of the item
*/
private AESharedItemStack(ItemStack itemStack, int damage) {
this.itemStack = itemStack;
this.itemId = Item.getIdFromItem(itemStack.getItem());
this.itemDamage = damage;
// Ensure this is always called last. /**
this.hashCode = this.makeHashCode(); * A constructor to explicitly set the damage value and not fetch it from the {@link ItemStack}
} *
* @param itemStack The {@link ItemStack} to filter
* @param damage The damage of the item
*/
private AESharedItemStack( ItemStack itemStack, int damage )
{
this.itemStack = itemStack;
this.itemDamage = damage;
ItemStack getDefinition() { // Ensure this is always called last.
return this.itemStack; this.hashCode = this.makeHashCode();
} }
int getItemDamage() { ItemStack getDefinition()
return this.itemDamage; {
} return this.itemStack;
}
@Override int getItemDamage()
public int hashCode() { {
return this.hashCode; return this.itemDamage;
} }
@Override @Override
public boolean equals(final Object obj) { public int hashCode()
if (this == obj) { {
return true; return this.hashCode;
} }
if (!(obj instanceof AESharedItemStack)) {
return false;
}
final AESharedItemStack other = (AESharedItemStack) obj; @Override
Preconditions.checkState(this.itemStack.getCount() == 1, "ItemStack#getCount() has to be 1"); public boolean equals( final Object obj )
Preconditions.checkArgument(other.getDefinition().getCount() == 1, "ItemStack#getCount() has to be 1"); {
if( this == obj )
{
return true;
}
if( !( obj instanceof AESharedItemStack ) )
{
return false;
}
if (this.itemStack == other.itemStack) { final AESharedItemStack other = (AESharedItemStack) obj;
return true; Preconditions.checkState( this.itemStack.getCount() == 1, "ItemStack#getCount() has to be 1" );
} Preconditions.checkArgument( other.getDefinition().getCount() == 1, "ItemStack#getCount() has to be 1" );
return ItemStack.areItemStacksEqual(this.itemStack, other.itemStack);
}
private int makeHashCode() { if( this.itemStack == other.itemStack )
return Objects.hash( {
this.itemId, return true;
this.itemDamage, }
this.itemStack.hasTagCompound() ? this.itemStack.getTagCompound() : 0); return ItemStack.areItemStacksEqual( this.itemStack, other.itemStack );
} }
private int makeHashCode()
{
return Objects.hash( this.itemStack.getItem(), this.itemDamage, this.itemStack.hasTagCompound() ? this.itemStack.getTagCompound() : 0 );
}
} }
@@ -25,7 +25,8 @@ import java.util.Map;
import appeng.util.Platform; import appeng.util.Platform;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import gregtech.common.items.MetaTool; import gregtech.api.items.IToolItem;
import ic2.api.item.ICustomDamageItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap; import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap;
@@ -34,159 +35,210 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
import appeng.api.config.FuzzyMode; import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
/** /**
* This variant list is optimized for damageable items, and supports selecting durability ranges with * This variant list is optimized for damageable items, and supports selecting durability ranges with
* {@link #findFuzzy(IAEItemStack, FuzzyMode)}. * {@link #findFuzzy(IAEItemStack, FuzzyMode)}.
*/ */
class FuzzyItemVariantList extends ItemVariantList { class FuzzyItemVariantList extends ItemVariantList
{
static final SharedStackComparator COMPARATOR = new SharedStackComparator(); static final SharedStackComparator COMPARATOR = new SharedStackComparator();
// NOTE: We only use Object as they key here so we can pass our special DamageBounds to the subMap method. // NOTE: We only use Object as they key here so we can pass our special DamageBounds to the subMap method.
// We NEVER put any keys in this map that are not AESharedItemStacks. // We NEVER put any keys in this map that are not AESharedItemStacks.
private final Object2ObjectSortedMap<Object, IAEItemStack> records = new Object2ObjectAVLTreeMap<>(COMPARATOR); private final Object2ObjectSortedMap<Object, IAEItemStack> records = new Object2ObjectAVLTreeMap<>( COMPARATOR );
@Override @Override
public Collection<IAEItemStack> findFuzzy(final IAEItemStack filter, final FuzzyMode fuzzy) { public Collection<IAEItemStack> findFuzzy( final IAEItemStack filter, final FuzzyMode fuzzy )
ItemStack itemStack = filter.getDefinition(); {
ItemStack itemStack = filter.getDefinition();
ItemDamageBound lowerBound = makeLowerBound(itemStack, fuzzy); ItemDamageBound lowerBound = makeLowerBound( itemStack, fuzzy );
ItemDamageBound upperBound = makeUpperBound(itemStack, fuzzy); ItemDamageBound upperBound = makeUpperBound( itemStack, fuzzy );
Preconditions.checkState(lowerBound.itemDamage > upperBound.itemDamage); Preconditions.checkState( lowerBound.itemDamage > upperBound.itemDamage );
return this.records.subMap(lowerBound, upperBound).values(); return this.records.subMap( lowerBound, upperBound ).values();
} }
@SuppressWarnings("unchecked") @SuppressWarnings( "unchecked" )
@Override @Override
Map<AESharedItemStack, IAEItemStack> getRecords() { Map<AESharedItemStack, IAEItemStack> getRecords()
// We ensure on our end that we NEVER use anything but AESharedItemStack as the key in this map {
return (Map<AESharedItemStack, IAEItemStack>) (Object) this.records; // We ensure on our end that we NEVER use anything but AESharedItemStack as the key in this map
} return (Map<AESharedItemStack, IAEItemStack>) (Object) this.records;
}
static class ItemDamageBound { static class ItemDamageBound
final int itemDamage; {
final int itemDamage;
public ItemDamageBound(int itemDamage) { public ItemDamageBound( int itemDamage )
this.itemDamage = itemDamage; {
} this.itemDamage = itemDamage;
} }
}
/** /**
* This comparator creates a strict and total ordering over all {@link AESharedItemStack} of the same item. To * This comparator creates a strict and total ordering over all {@link AESharedItemStack} of the same item. To
* support selecting ranges of durability, it is defined for type {@link Object} and also accepts * support selecting ranges of durability, it is defined for type {@link Object} and also accepts
* {@link ItemDamageBound} as an argument to compare against. * {@link ItemDamageBound} as an argument to compare against.
*/ */
static class SharedStackComparator implements Comparator<Object> { static class SharedStackComparator implements Comparator<Object>
@Override {
public int compare(Object a, Object b) { @Override
// Either argument can either be a damage bound or a shared item stack public int compare( Object a, Object b )
// Since we never put damage bounds into the map as keys, only one {
// of the two arguments can possibly be a bound // Either argument can either be a damage bound or a shared item stack
ItemDamageBound boundA = null; // Since we never put damage bounds into the map as keys, only one
AESharedItemStack stackA = null; // of the two arguments can possibly be a bound
int itemDamageA; ItemDamageBound boundA = null;
if (a instanceof ItemDamageBound) { AESharedItemStack stackA = null;
boundA = (ItemDamageBound) a; int itemDamageA;
itemDamageA = boundA.itemDamage; if( a instanceof ItemDamageBound )
} else { {
stackA = (AESharedItemStack) a; boundA = (ItemDamageBound) a;
itemDamageA = stackA.getItemDamage(); itemDamageA = boundA.itemDamage;
} }
ItemDamageBound boundB = null; else
AESharedItemStack stackB = null; {
int itemDamageB; stackA = (AESharedItemStack) a;
if (b instanceof ItemDamageBound) { itemDamageA = stackA.getItemDamage();
boundB = (ItemDamageBound) b; }
itemDamageB = boundB.itemDamage; ItemDamageBound boundB = null;
} else { AESharedItemStack stackB = null;
stackB = (AESharedItemStack) b; int itemDamageB;
itemDamageB = stackB.getItemDamage(); if( b instanceof ItemDamageBound )
} {
boundB = (ItemDamageBound) b;
itemDamageB = boundB.itemDamage;
}
else
{
stackB = (AESharedItemStack) b;
itemDamageB = stackB.getItemDamage();
}
// When either argument is a damage bound, we just compare the damage values because it is used // When either argument is a damage bound, we just compare the damage values because it is used
// only to get a certain damage range out of the map. // only to get a certain damage range out of the map.
if (boundA != null || boundB != null) { if( boundA != null || boundB != null )
return Integer.compare(itemDamageB, itemDamageA); {
} return Integer.compare( itemDamageB, itemDamageA );
}
ItemStack itemStackA = stackA.getDefinition(); ItemStack itemStackA = stackA.getDefinition();
ItemStack itemStackB = stackB.getDefinition(); ItemStack itemStackB = stackB.getDefinition();
Preconditions.checkState(itemStackA.getCount() == 1, "ItemStack#getCount() has to be 1"); Preconditions.checkState( itemStackA.getCount() == 1, "ItemStack#getCount() has to be 1" );
Preconditions.checkArgument(itemStackB.getCount() == 1, "ItemStack#getCount() has to be 1"); Preconditions.checkArgument( itemStackB.getCount() == 1, "ItemStack#getCount() has to be 1" );
if (itemStackA == itemStackB) { if( itemStackA == itemStackB )
return 0; {
} return 0;
}
// Damaged items are sorted before undamaged items // Damaged items are sorted before undamaged items
final int damageValue = Integer.compare(itemDamageB, itemDamageA); final int damageValue = Integer.compare( itemDamageB, itemDamageA );
if (damageValue != 0) { if( damageValue != 0 )
return damageValue; {
} return damageValue;
}
// As a final tie breaker, order by the object identity of the item stack // As a final tie breaker, order by the object identity of the item stack
// While this will order seemingly at random, we only need the order of // While this will order seemingly at random, we only need the order of
// damage values to be predictable, while still having to satisfy the // damage values to be predictable, while still having to satisfy the
// complete order requirements of the sorted map // complete order requirements of the sorted map
return Long.compare(System.identityHashCode(itemStackA), System.identityHashCode(itemStackB)); return Long.compare( System.identityHashCode( itemStackA ), System.identityHashCode( itemStackB ) );
} }
} }
/** /**
* Minecraft reverses the damage values. So anything with a damage of 0 is undamaged and increases the more damaged * Minecraft reverses the damage values. So anything with a damage of 0 is undamaged and increases the more damaged
* the item is. * the item is.
* <p> * <p>
* Further the used subMap follows [MAX_DAMAGE, MIN_DAMAGE), so to include undamaged items, we have to start with a * Further the used subMap follows [MAX_DAMAGE, MIN_DAMAGE), so to include undamaged items, we have to start with a
* lower damage value than 0, while it is fine to use {@link ItemStack#getMaxDamage()} for the upper bound. * lower damage value than 0, while it is fine to use {@link ItemStack#getMaxDamage()} for the upper bound.
*/ */
private static final int MIN_DAMAGE_VALUE = -1; private static final int MIN_DAMAGE_VALUE = -1;
/* /*
* Keep in mind that the stack order is from most damaged to least damaged, so this lower bound will actually be a * Keep in mind that the stack order is from most damaged to least damaged, so this lower bound will actually be a
* higher number than the upper bound. * higher number than the upper bound.
*/ */
static ItemDamageBound makeLowerBound(final ItemStack stack, final FuzzyMode fuzzy) static ItemDamageBound makeLowerBound( final ItemStack stack, final FuzzyMode fuzzy )
{ {
Preconditions.checkState( stack.getItem().isDamageable() , "Item#isDamageable() has to be true" ); Preconditions.checkState( stack.getItem().isDamageable() || ( Platform.isGTDamageableItem( stack.getItem() ) ), "Item#isDamageable() has to be true" );
int damage; int damage;
if( fuzzy == FuzzyMode.IGNORE_ALL ) int maxDamage;
{ if( Platform.isIC2DamageableItem( stack.getItem() ) )
if( stack.getMaxDamage() == 0 ) {
{ maxDamage = ( (ICustomDamageItem) stack.getItem() ).getMaxCustomDamage( stack );
damage = stack.getItemDamage(); damage = ( (ICustomDamageItem) stack.getItem() ).getCustomDamage( stack );
} }
else else if( Platform.isGTDamageableItem( stack.getItem() ) )
{ {
damage = stack.getMaxDamage(); maxDamage = ( (IToolItem) stack.getItem() ).getMaxItemDamage( stack );
} damage = ( (IToolItem) stack.getItem() ).getItemDamage( stack );
} }
else else
{ {
final int breakpoint = fuzzy.calculateBreakPoint( stack.getMaxDamage() ); maxDamage = stack.getMaxDamage();
damage = stack.getItemDamage() <= breakpoint ? breakpoint : stack.getMaxDamage(); damage = stack.getItemDamage();
} }
return new ItemDamageBound( damage ); if( fuzzy == FuzzyMode.IGNORE_ALL )
} {
if( maxDamage != 0 )
{
damage = maxDamage;
}
}
else
{
final int breakpoint = fuzzy.calculateBreakPoint( maxDamage );
damage = damage <= breakpoint ? breakpoint : maxDamage;
}
/* return new ItemDamageBound( damage );
* Keep in mind that the stack order is from most damaged to least damaged, so this upper bound will actually be a }
* lower number than the lower bound. It also is exclusive.
*/
static ItemDamageBound makeUpperBound(final ItemStack stack, final FuzzyMode fuzzy) {
Preconditions.checkState(stack.getItem().isDamageable() , "Item#isDamageable() has to be true");
int damage; /*
if (fuzzy == FuzzyMode.IGNORE_ALL) { * Keep in mind that the stack order is from most damaged to least damaged, so this upper bound will actually be a
damage = MIN_DAMAGE_VALUE; * lower number than the lower bound. It also is exclusive.
} else { */
final int breakpoint = fuzzy.calculateBreakPoint(stack.getMaxDamage()); static ItemDamageBound makeUpperBound( final ItemStack stack, final FuzzyMode fuzzy )
damage = stack.getItemDamage() <= breakpoint ? MIN_DAMAGE_VALUE : breakpoint; {
} Preconditions.checkState( stack.getItem().isDamageable() || ( Platform.isGTDamageableItem( stack.getItem() ) ), "Item#isDamageable() has to be true" );
return new ItemDamageBound(damage); int damage;
} if( fuzzy == FuzzyMode.IGNORE_ALL )
{
damage = MIN_DAMAGE_VALUE;
}
else
{
int maxDamage;
if( Platform.isIC2DamageableItem( stack.getItem() ) )
{
maxDamage = ( (ICustomDamageItem) stack.getItem() ).getMaxCustomDamage( stack );
damage = ( (ICustomDamageItem) stack.getItem() ).getCustomDamage( stack );
}
else if( Platform.isGTDamageableItem( stack.getItem() ) )
{
maxDamage = ( (IToolItem) stack.getItem() ).getMaxItemDamage( stack );
damage = ( (IToolItem) stack.getItem() ).getItemDamage( stack );
}
else
{
maxDamage = stack.getMaxDamage();
damage = stack.getItemDamage();
}
final int breakpoint = fuzzy.calculateBreakPoint( maxDamage );
damage = damage <= breakpoint ? MIN_DAMAGE_VALUE : breakpoint;
}
return new ItemDamageBound( damage );
}
} }
+177 -141
View File
@@ -26,7 +26,6 @@ import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import appeng.util.Platform; import appeng.util.Platform;
import gregtech.common.items.MetaTool;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
@@ -36,180 +35,217 @@ import appeng.api.config.FuzzyMode;
import appeng.api.storage.data.IAEItemStack; import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList; import appeng.api.storage.data.IItemList;
public final class ItemList implements IItemList<IAEItemStack> {
private final Reference2ObjectMap<Item, ItemVariantList> records = new Reference2ObjectOpenHashMap<>(); public final class ItemList implements IItemList<IAEItemStack>
/** {
* We increment this version field everytime an attempt to mutate this item list (or potentially one of its
* sub-lists) is made. Iterators will copy the version when they are created and compare it against the current
* version whenever they advance to trigger a {@link ConcurrentModificationException}.
*/
private final AtomicInteger version = new AtomicInteger(0);
@Override private final Reference2ObjectMap<Item, ItemVariantList> records = new Reference2ObjectOpenHashMap<>();
public IAEItemStack findPrecise(final IAEItemStack itemStack) { /**
if (itemStack == null) { * We increment this version field everytime an attempt to mutate this item list (or potentially one of its
return null; * sub-lists) is made. Iterators will copy the version when they are created and compare it against the current
} * version whenever they advance to trigger a {@link ConcurrentModificationException}.
*/
private final AtomicInteger version = new AtomicInteger( 0 );
ItemVariantList record = this.records.get(itemStack.getItem()); @Override
return record != null ? record.findPrecise(itemStack) : null; public IAEItemStack findPrecise( final IAEItemStack itemStack )
} {
if( itemStack == null )
{
return null;
}
@Override ItemVariantList record = this.records.get( itemStack.getItem() );
public Collection<IAEItemStack> findFuzzy(final IAEItemStack filter, final FuzzyMode fuzzy) { return record != null ? record.findPrecise( itemStack ) : null;
if (filter == null) { }
return Collections.emptyList();
}
ItemVariantList record = this.records.get(filter.getItem()); @Override
return record != null ? record.findFuzzy(filter, fuzzy) : Collections.emptyList(); public Collection<IAEItemStack> findFuzzy( final IAEItemStack filter, final FuzzyMode fuzzy )
} {
if( filter == null )
{
return Collections.emptyList();
}
@Override ItemVariantList record = this.records.get( filter.getItem() );
public boolean isEmpty() { return record != null ? record.findFuzzy( filter, fuzzy ) : Collections.emptyList();
return !this.iterator().hasNext(); }
}
@Override @Override
public void add(final IAEItemStack itemStack) { public boolean isEmpty()
version.incrementAndGet(); {
return !this.iterator().hasNext();
}
if (itemStack == null) { @Override
return; public void add( final IAEItemStack itemStack )
} {
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).add(itemStack); if( itemStack == null )
} {
return;
}
@Override this.getOrCreateRecord( itemStack.getItem() ).add( itemStack );
public void addStorage(final IAEItemStack itemStack) { }
version.incrementAndGet();
if (itemStack == null) { @Override
return; public void addStorage( final IAEItemStack itemStack )
} {
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).addStorage(itemStack); if( itemStack == null )
} {
return;
}
@Override this.getOrCreateRecord( itemStack.getItem() ).addStorage( itemStack );
public void addCrafting(final IAEItemStack itemStack) { }
version.incrementAndGet();
if (itemStack == null) { @Override
return; public void addCrafting( final IAEItemStack itemStack )
} {
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).addCrafting(itemStack); if( itemStack == null )
} {
return;
}
@Override this.getOrCreateRecord( itemStack.getItem() ).addCrafting( itemStack );
public void addRequestable(final IAEItemStack itemStack) { }
version.incrementAndGet();
if (itemStack == null) { @Override
return; public void addRequestable( final IAEItemStack itemStack )
} {
version.incrementAndGet();
this.getOrCreateRecord(itemStack.getItem()).addRequestable(itemStack); if( itemStack == null )
} {
return;
}
@Override this.getOrCreateRecord( itemStack.getItem() ).addRequestable( itemStack );
public IAEItemStack getFirstItem() { }
for (final IAEItemStack stackType : this) {
return stackType;
}
return null; @Override
} public IAEItemStack getFirstItem()
{
for( final IAEItemStack stackType : this )
{
return stackType;
}
@Override return null;
public int size() { }
int size = 0;
for (ItemVariantList entry : records.values()) {
size += entry.size();
}
return size; @Override
} public int size()
{
int size = 0;
for( ItemVariantList entry : records.values() )
{
size += entry.size();
}
@Override return size;
public Iterator<IAEItemStack> iterator() { }
return new ChainedIterator(this.records.values().iterator(), version);
}
@Override @Override
public void resetStatus() { public Iterator<IAEItemStack> iterator()
for (final IAEItemStack i : this) { {
i.reset(); return new ChainedIterator( this.records.values().iterator(), version );
} }
}
private ItemVariantList getOrCreateRecord(Item item) { @Override
return this.records.computeIfAbsent(item, this::makeRecordMap); public void resetStatus()
} {
for( final IAEItemStack i : this )
{
i.reset();
}
}
private ItemVariantList makeRecordMap(Item item) { private ItemVariantList getOrCreateRecord( Item item )
if (item.isDamageable() ) { {
return new FuzzyItemVariantList(); return this.records.computeIfAbsent( item, this::makeRecordMap );
} else { }
return new NormalItemVariantList();
}
}
/** private ItemVariantList makeRecordMap( Item item )
* Iterates over multiple item lists as if they were one list. {
*/ if( item.isDamageable() || Platform.isGTDamageableItem( item ) )
private static class ChainedIterator implements Iterator<IAEItemStack> { {
return new FuzzyItemVariantList();
}
else
{
return new NormalItemVariantList();
}
}
private final AtomicInteger parentVersion; /**
private final int version; * Iterates over multiple item lists as if they were one list.
private final Iterator<ItemVariantList> parent; */
private Iterator<IAEItemStack> next; private static class ChainedIterator implements Iterator<IAEItemStack>
{
public ChainedIterator(Iterator<ItemVariantList> iterator, AtomicInteger parentVersion) { private final AtomicInteger parentVersion;
this.parent = iterator; private final int version;
this.parentVersion = parentVersion; private final Iterator<ItemVariantList> parent;
this.version = parentVersion.get(); private Iterator<IAEItemStack> next;
this.ensureItems();
}
@Override public ChainedIterator( Iterator<ItemVariantList> iterator, AtomicInteger parentVersion )
public boolean hasNext() { {
return next != null && next.hasNext(); this.parent = iterator;
} this.parentVersion = parentVersion;
this.version = parentVersion.get();
this.ensureItems();
}
@Override @Override
public IAEItemStack next() { public boolean hasNext()
if (this.next == null) { {
throw new NoSuchElementException(); return next != null && next.hasNext();
} }
if (this.version != this.parentVersion.get()) {
throw new ConcurrentModificationException();
}
IAEItemStack result = this.next.next(); @Override
this.ensureItems(); public IAEItemStack next()
return result; {
} if( this.next == null )
{
throw new NoSuchElementException();
}
if( this.version != this.parentVersion.get() )
{
throw new ConcurrentModificationException();
}
private void ensureItems() { IAEItemStack result = this.next.next();
if (hasNext()) { this.ensureItems();
return; // Still items left in the current one return result;
} }
// Find the next iterator willing to return some items... private void ensureItems()
while (this.parent.hasNext()) { {
this.next = this.parent.next().iterator(); if( hasNext() )
{
return; // Still items left in the current one
}
if (this.next.hasNext()) { // Find the next iterator willing to return some items...
return; // Found one! while ( this.parent.hasNext() )
} {
} this.next = this.parent.next().iterator();
// No more items if( this.next.hasNext() )
this.next = null; {
} return; // Found one!
} }
}
// No more items
this.next = null;
}
}
} }
@@ -0,0 +1,383 @@
package appeng.util.item;
import java.util.ArrayList;
import java.util.List;
/**
* @author brachy84
* @butcherer PrototypeTrousers
*/
public class OreDictFilterMatcher
{
/**
* Parses the given expression and creates a List.
*
* @param expression expr to parse
* @return match rule list
*/
public static List<MatchRule> parseExpression( String expression )
{
List<MatchRule> rules = new ArrayList<>();
parseExpression( rules, expression );
return rules;
}
/**
* Parses the given expression and puts them into the given list.
*
* @param rules list to fill
* @param expression expr to parse
* @return the position of the expr. Is only relevant for sub rules
*/
public static int parseExpression( List<MatchRule> rules, String expression )
{
rules.clear();
StringBuilder builder = new StringBuilder();
for( int i = 0; i < expression.length(); i++ )
{
char c = expression.charAt( i );
if( c == ' ' )
{
continue;
}
if( c == '(' )
{
List<MatchRule> subRules = new ArrayList<>();
i = parseExpression( subRules, expression.substring( i + 1 ) ) + i + 1;
rules.add( MatchRule.group( subRules, builder.toString() ) );
builder = new StringBuilder();
}
else
{
switch ( c )
{
case '&':
rules.add( new MatchRule( builder.toString() ) );
rules.add( new MatchRule( MatchLogic.AND ) );
builder = new StringBuilder();
break;
case '|':
rules.add( new MatchRule( builder.toString() ) );
rules.add( new MatchRule( MatchLogic.OR ) );
builder = new StringBuilder();
break;
case '^':
rules.add( new MatchRule( builder.toString() ) );
rules.add( new MatchRule( MatchLogic.XOR ) );
builder = new StringBuilder();
break;
case ')':
rules.add( new MatchRule( builder.toString() ) );
return i + 1;
default:
builder.append( c );
}
}
}
if( builder.length() > 0 )
{
rules.add( new MatchRule( builder.toString() ) );
}
return expression.length();
}
/**
* Matches the given string against a list of rules.
* The string does not have to be an oreDict.
*
* @param rules to check against
* @param oreDict string to check
* @return if the string matches the rules
*/
public static boolean matches( List<MatchRule> rules, String oreDict )
{
boolean first = true;
boolean lastResult = false;
MatchLogic lastLogic = null;
for( MatchRule rule : rules )
{
if( lastLogic == null )
{
if( rule.logic == MatchLogic.AND || rule.logic == MatchLogic.OR || rule.logic == MatchLogic.XOR )
{
lastLogic = rule.logic;
continue;
}
}
if( lastLogic != null || first )
{
if( lastLogic != null )
{
switch ( lastLogic )
{
case AND:
{
if( !lastResult )
{
return false;
}
break;
}
case OR:
{
if( lastResult )
{
return true;
}
break;
}
}
}
boolean newResult;
if( rule.isGroup() )
{
newResult = rule.logic == MatchLogic.NOT ^ matches( rule.subRules, oreDict );
}
else
{
newResult = matches( rule, oreDict );
}
if( lastLogic == MatchLogic.XOR )
{
if( lastResult == newResult )
{
return false;
}
}
lastLogic = null;
lastResult = newResult;
first = false;
}
}
return lastResult;
}
private static boolean matches( MatchRule rule, String oreDict )
{
String filter = rule.expression;
if( filter.equals( "*" ) )
{
return true;
}
boolean startWild = filter.startsWith( "*" ), endWild = filter.endsWith( "*" );
if( startWild )
{
filter = filter.substring( 1 );
}
String[] parts = filter.split( "\\*+" );
return ( rule.logic == MatchLogic.NOT ) ^ matches( parts, oreDict, startWild, endWild );
}
private static boolean matches( String[] filter, String oreDict, boolean startWild, boolean endWild )
{
String lastlastPart = filter[0];
String lastPart = filter[0];
int index = oreDict.indexOf( lastPart );
if( ( !startWild && index != 0 ) || index < 0 )
{
return false;
}
boolean didGoBack = false;
for( int i = 1; i < filter.length; i++ )
{
String part = filter[i];
int newIndex = oreDict.indexOf( part, index + lastPart.length() );
if( newIndex < 0 )
{
if( i > 1 && !didGoBack )
{
i -= 2;
lastPart = lastlastPart;
didGoBack = true;
continue;
}
return false;
}
lastlastPart = lastPart;
lastPart = part;
index = newIndex;
if( didGoBack )
{
didGoBack = false;
}
}
if( endWild || lastPart.length() + index == oreDict.length() )
{
return true;
}
for( int i = filter.length - 1; i < filter.length; i++ )
{
String part = filter[i];
int newIndex = oreDict.indexOf( part, index + lastPart.length() );
if( newIndex < 0 )
{
if( i > 1 && !didGoBack )
{
i -= 2;
lastPart = lastlastPart;
didGoBack = true;
continue;
}
return false;
}
lastlastPart = lastPart;
lastPart = part;
index = newIndex;
if( didGoBack )
{
didGoBack = false;
}
}
return lastPart.length() + index == oreDict.length();
}
public static String validateExp( String input )
{
// remove all operators that are double
input = input.replaceAll( "\\*{2,}", "*" );
input = input.replaceAll( "&{2,}", "&" );
input = input.replaceAll( "\\|{2,}", "|" );
input = input.replaceAll( "!{2,}", "!" );
input = input.replaceAll( "\\^{2,}", "^" );
input = input.replaceAll( " {2,}", " " );
// move ( and ) so it doesn't create invalid expressions f.e. xxx (& yyy) => xxx & (yyy)
// append or prepend ( and ) if the amount is not equal
StringBuilder builder = new StringBuilder();
int unclosed = 0;
char last = ' ';
for( int i = 0; i < input.length(); i++ )
{
char c = input.charAt( i );
if( c == ' ' )
{
if( last != '(' )
{
builder.append( " " );
}
continue;
}
if( c == '(' )
{
unclosed++;
}
else if( c == ')' )
{
unclosed--;
if( last == '&' || last == '|' || last == '^' )
{
int l = builder.lastIndexOf( " " + last );
int l2 = builder.lastIndexOf( "" + last );
builder.insert( l == l2 - 1 ? l : l2, ")" );
continue;
}
if( i > 0 && builder.charAt( builder.length() - 1 ) == ' ' )
{
builder.deleteCharAt( builder.length() - 1 );
}
}
else if( ( c == '&' || c == '|' || c == '^' ) && last == '(' )
{
builder.deleteCharAt( builder.lastIndexOf( "(" ) );
builder.append( c ).append( " (" );
continue;
}
builder.append( c );
last = c;
}
if( unclosed > 0 )
{
for( int i = 0; i < unclosed; i++ )
{
builder.append( ")" );
}
}
else if( unclosed < 0 )
{
unclosed = -unclosed;
for( int i = 0; i < unclosed; i++ )
{
builder.insert( 0, "(" );
}
}
input = builder.toString();
input = input.replaceAll( " {2,}", " " );
return input;
}
public static class MatchRule
{
public final MatchLogic logic;
public final String expression;
private final List<MatchRule> subRules;
private MatchRule( MatchLogic logic, String expression, List<MatchRule> subRules )
{
if( expression.startsWith( "!" ) )
{
logic = MatchLogic.NOT;
expression = expression.substring( 1 );
}
this.logic = logic;
this.expression = expression;
this.subRules = subRules;
}
public MatchRule( MatchLogic logic, String expression )
{
this( logic, expression, null );
}
public MatchRule( MatchLogic logic )
{
this( logic, "" );
}
public MatchRule( String expression )
{
this( MatchLogic.ANY, expression );
}
public static MatchRule not( String expression, boolean not )
{
return new MatchRule( not ? MatchLogic.NOT : MatchLogic.ANY, expression );
}
public static MatchRule group( List<MatchRule> subRules, String expression )
{
MatchLogic logic = expression.startsWith( "!" ) ? MatchLogic.NOT : MatchLogic.ANY;
return new MatchRule( logic, "", subRules );
}
public boolean isGroup()
{
return subRules != null;
}
}
public enum MatchLogic
{
OR,
AND,
XOR,
NOT,
ANY
}
}
+164 -200
View File
@@ -19,244 +19,208 @@
package appeng.util.item; package appeng.util.item;
import java.util.*; import appeng.api.storage.data.IAEItemStack;
import java.util.concurrent.ConcurrentMap;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.OreDictionary; import net.minecraftforge.oredict.OreDictionary;
import appeng.api.storage.data.IAEItemStack; import java.util.*;
public class OreHelper public class OreHelper
{ {
public static final OreHelper INSTANCE = new OreHelper(); public static final OreHelper INSTANCE = new OreHelper();
/** /**
* A local cache to speed up OreDictionary lookups. * A local cache to speed up OreDictionary lookups.
*/ */
private final LoadingCache<String, List<ItemStack>> oreDictCache = CacheBuilder.newBuilder().build( new CacheLoader<String, List<ItemStack>>() private final LoadingCache<String, List<ItemStack>> oreDictCache = CacheBuilder.newBuilder().build( new CacheLoader<String, List<ItemStack>>()
{ {
@Override @Override
public List<ItemStack> load( final String oreName ) public List<ItemStack> load( final String oreName )
{ {
return OreDictionary.getOres( oreName ); return OreDictionary.getOres( oreName );
} }
} ); } );
private final Map<ItemRef, OreReference> references = new HashMap<>(); private final Map<ItemRef, OreReference> references = new HashMap<>();
/** /**
* Test if the passed {@link ItemStack} is an ore. * Test if the passed {@link ItemStack} is an ore.
* *
* @param itemStack the itemstack to test * @param itemStack the itemstack to test
* * @return true if an ore entry exists, false otherwise
* @return true if an ore entry exists, false otherwise */
*/ public Optional<OreReference> getOre( final ItemStack itemStack )
public Optional<OreReference> getOre( final ItemStack itemStack ) {
{ final ItemRef ir = new ItemRef( itemStack );
final ItemRef ir = new ItemRef( itemStack );
if( !this.references.containsKey( ir ) ) if( !this.references.containsKey( ir ) )
{ {
final OreReference ref = new OreReference(); final OreReference ref = new OreReference();
final Collection<Integer> ores = ref.getOres(); final Collection<Integer> ores = ref.getOres();
final Collection<String> set = ref.getEquivalents(); final Collection<String> set = ref.getEquivalents();
final Set<String> toAdd = new HashSet<>(); final Set<String> toAdd = new HashSet<>();
for( final String ore : OreDictionary.getOreNames() ) for( final String ore : OreDictionary.getOreNames() )
{ {
// skip ore if it is a match already or null. // skip ore if it is a match already or null.
if( ore == null || toAdd.contains( ore ) ) if( ore == null || toAdd.contains( ore ) )
{ {
continue; continue;
} }
for( final ItemStack oreItem : this.oreDictCache.getUnchecked( ore ) ) for( final ItemStack oreItem : this.oreDictCache.getUnchecked( ore ) )
{ {
if( OreDictionary.itemMatches( oreItem, itemStack, false ) ) if( OreDictionary.itemMatches( oreItem, itemStack, false ) )
{ {
toAdd.add( ore ); toAdd.add( ore );
break; break;
} }
} }
} }
for( final String ore : toAdd ) for( final String ore : toAdd )
{ {
set.add( ore ); set.add( ore );
ores.add( OreDictionary.getOreID( ore ) ); ores.add( OreDictionary.getOreID( ore ) );
} }
if( !set.isEmpty() ) if( !set.isEmpty() )
{ {
this.references.put( ir, ref ); this.references.put( ir, ref );
} }
else else
{ {
this.references.put( ir, null ); this.references.put( ir, null );
} }
} }
return Optional.ofNullable( this.references.get( ir ) ); return Optional.ofNullable( this.references.get( ir ) );
} }
boolean sameOre( final AEItemStack aeItemStack, final IAEItemStack is ) boolean sameOre( final AEItemStack aeItemStack, final IAEItemStack is )
{ {
final OreReference a = aeItemStack.getOre().orElse( null ); final OreReference a = aeItemStack.getOre().orElse( null );
final OreReference b = ( (AEItemStack) is ).getOre().orElse( null ); final OreReference b = ( (AEItemStack) is ).getOre().orElse( null );
return this.sameOre( a, b ); return this.sameOre( a, b );
} }
public boolean sameOre( final OreReference a, final OreReference b ) public boolean sameOre( final OreReference a, final OreReference b )
{ {
if( a == null || b == null ) if( a == null || b == null )
{ {
return false; return false;
} }
if( a == b ) if( a == b )
{ {
return true; return true;
} }
final Collection<Integer> bOres = b.getOres(); final Collection<Integer> bOres = b.getOres();
for( final Integer ore : a.getOres() ) for( final Integer ore : a.getOres() )
{ {
if( bOres.contains( ore ) ) if( bOres.contains( ore ) )
{ {
return true; return true;
} }
} }
return false; return false;
} }
boolean sameOre( final AEItemStack aeItemStack, final ItemStack o ) boolean sameOre( final AEItemStack aeItemStack, final ItemStack o )
{ {
return aeItemStack.getOre().map( a -> return aeItemStack.getOre().map( a -> {
{ for( final String oreName : a.getEquivalents() )
for( final String oreName : a.getEquivalents() ) {
{ for( final ItemStack oreItem : this.oreDictCache.getUnchecked( oreName ) )
for( final ItemStack oreItem : this.oreDictCache.getUnchecked( oreName ) ) {
{ if( OreDictionary.itemMatches( oreItem, o, false ) )
if( OreDictionary.itemMatches( oreItem, o, false ) ) {
{ return true;
return true; }
} }
} }
} return false;
return false; } ).orElse( false );
} ).orElse( false ); }
}
public Set<Integer> getMatchingOre( String allow ) public Set<Integer> getMatchingOre( String oreExp )
{ {
List<String> matchingOres = new ArrayList<>(); Set<Integer> matchingIds = new HashSet<>();
ConcurrentMap<String, List<ItemStack>> oreKeys = oreDictCache.asMap();
oreKeys.forEach( ( s, l ) -> { List<OreDictFilterMatcher.MatchRule> rulesList = OreDictFilterMatcher.parseExpression( oreExp );
for( String ore : OreDictionary.getOreNames() )
{
if( OreDictFilterMatcher.matches( rulesList, ore ) )
{
matchingIds.add( OreDictionary.getOreID( ore ) );
}
}
return matchingIds;
}
if( allow.startsWith( "*" ) && allow.endsWith( "*" ) ) public List<ItemStack> getCachedOres( final String oreName )
{ {
if( s.contains( allow.substring( 1, allow.length() - 1 ) ) ) return this.oreDictCache.getUnchecked( oreName );
{ }
matchingOres.add( s );
}
}
else if( allow.startsWith( "*" ) )
{
if( s.endsWith( allow.substring( 1 ) ) )
{
matchingOres.add( s );
}
}
else if( allow.endsWith( "*" ) )
{
if( s.startsWith( allow.substring( 0, allow.length() - 1 ) ) )
{
matchingOres.add( s );
}
}
else
{
if( s.matches( allow ) )
{
matchingOres.add( s );
}
}
} );
Set<Integer> oreIDs = new HashSet<>(); private static class ItemRef
for( String matchingOre : matchingOres ) {
{
oreIDs.add( OreDictionary.getOreID( matchingOre ) );
}
return oreIDs; private final Item ref;
} private final int damage;
private final int hash;
List<ItemStack> getCachedOres( final String oreName ) ItemRef( final ItemStack stack )
{ {
return this.oreDictCache.getUnchecked( oreName ); this.ref = stack.getItem();
}
private static class ItemRef if( stack.getItem().isDamageable() )
{ {
this.damage = 0; // IGNORED
}
else
{
this.damage = stack.getItemDamage(); // might be important...
}
private final Item ref; this.hash = this.ref.hashCode() ^ this.damage;
private final int damage; }
private final int hash;
ItemRef( final ItemStack stack ) @Override
{ public int hashCode()
this.ref = stack.getItem(); {
return this.hash;
}
if( stack.getItem().isDamageable() ) @Override
{ public boolean equals( final Object obj )
this.damage = 0; // IGNORED {
} if( obj == null )
else {
{ return false;
this.damage = stack.getItemDamage(); // might be important... }
} if( this.getClass() != obj.getClass() )
{
return false;
}
final ItemRef other = (ItemRef) obj;
return this.damage == other.damage && this.ref == other.ref;
}
this.hash = this.ref.hashCode() ^ this.damage; @Override
} public String toString()
{
@Override return "ItemRef [ref=" + this.ref.getUnlocalizedName() + ", damage=" + this.damage + ", hash=" + this.hash + ']';
public int hashCode() }
{ }
return this.hash;
}
@Override
public boolean equals( final Object obj )
{
if( obj == null )
{
return false;
}
if( this.getClass() != obj.getClass() )
{
return false;
}
final ItemRef other = (ItemRef) obj;
return this.damage == other.damage && this.ref == other.ref;
}
@Override
public String toString()
{
return "ItemRef [ref=" + this.ref.getUnlocalizedName() + ", damage=" + this.damage + ", hash=" + this.hash + ']';
}
}
} }
@@ -102,6 +102,7 @@ gui.appliedenergistics2.FluidTunnel=Fluid
gui.appliedenergistics2.RedstoneTunnel=Redstone gui.appliedenergistics2.RedstoneTunnel=Redstone
gui.appliedenergistics2.EUTunnel=EU gui.appliedenergistics2.EUTunnel=EU
gui.appliedenergistics2.FETunnel=FE gui.appliedenergistics2.FETunnel=FE
gui.appliedenergistics2.GTEUTunnel=GTEU
gui.appliedenergistics2.LightTunnel=Light gui.appliedenergistics2.LightTunnel=Light
gui.appliedenergistics2.OCTunnel=OpenComputers gui.appliedenergistics2.OCTunnel=OpenComputers
gui.appliedenergistics2.PressureTunnel=Pressure gui.appliedenergistics2.PressureTunnel=Pressure
@@ -167,6 +168,7 @@ gui.appliedenergistics2.StoredFluids=Stored Fluids
gui.appliedenergistics2.Terminal=Terminal gui.appliedenergistics2.Terminal=Terminal
gui.appliedenergistics2.InterfaceTerminal=Interface Terminal gui.appliedenergistics2.InterfaceTerminal=Interface Terminal
gui.appliedenergistics2.InterfaceTerminalHint=Show Or Hide on Interface Terminal. gui.appliedenergistics2.InterfaceTerminalHint=Show Or Hide on Interface Terminal.
gui.appliedenergistics2.InterfaceConfigurationTerminal=Interface Configuration Terminal
gui.appliedenergistics2.FormationPlane=Formation Plane gui.appliedenergistics2.FormationPlane=Formation Plane
gui.appliedenergistics2.FluidFormationPlane=Fluid Formation Plane gui.appliedenergistics2.FluidFormationPlane=Fluid Formation Plane
gui.appliedenergistics2.VibrationChamber=Vibration Chamber gui.appliedenergistics2.VibrationChamber=Vibration Chamber
@@ -375,6 +377,7 @@ gui.tooltips.appliedenergistics2.HighlightInterface=Highlight interface
gui.appliedenergistics2.units.appliedenergstics=AE gui.appliedenergistics2.units.appliedenergstics=AE
gui.appliedenergistics2.units.ic2=Energy Units gui.appliedenergistics2.units.ic2=Energy Units
gui.appliedenergistics2.units.rf=Redstone Flux gui.appliedenergistics2.units.rf=Redstone Flux
gui.appliedenergistics2.units.gteu=GTEU
// Colors // Colors
gui.appliedenergistics2.White=White gui.appliedenergistics2.White=White
@@ -546,6 +549,7 @@ item.appliedenergistics2.multi_part.inverted_toggle_bus.name=ME Inverted Toggle
item.appliedenergistics2.multi_part.toggle_bus.name=ME Toggle Bus item.appliedenergistics2.multi_part.toggle_bus.name=ME Toggle Bus
item.appliedenergistics2.multi_part.crafting_monitor.name=ME Crafting Monitor item.appliedenergistics2.multi_part.crafting_monitor.name=ME Crafting Monitor
item.appliedenergistics2.multi_part.interface_terminal.name=ME Interface Terminal item.appliedenergistics2.multi_part.interface_terminal.name=ME Interface Terminal
item.appliedenergistics2.multi_part.interface_configuration_terminal.name=ME Configuration Interface Terminal
item.appliedenergistics2.multi_part.fluid_terminal.name=ME Fluid Terminal item.appliedenergistics2.multi_part.fluid_terminal.name=ME Fluid Terminal
item.appliedenergistics2.multi_part.invalid_type.name=Disabled Item item.appliedenergistics2.multi_part.invalid_type.name=Disabled Item
@@ -0,0 +1,662 @@
# Japanese translate by tier940 & Quarri6343
# 日本語ローカライズ担当: tier940 & Quarri6343
# Corresponding Version: v0.52.3
# 対応バージョン: v0.52.3
// Blocks
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.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.matrix_frame.name=マトリクスフレーム
tile.appliedenergistics2.io_port.name=ME入出力ポート
tile.appliedenergistics2.inscriber.name=刻印機
tile.appliedenergistics2.interface.name=MEインターフェース
tile.appliedenergistics2.fluid_interface.name=ME液体インターフェース
tile.appliedenergistics2.quantum_link.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.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.crafting_monitor.name=クラフティングモニター
tile.appliedenergistics2.crafting_storage_1k.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=分子組立室
// 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.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=スカイストーンの階段
// Slabs
tile.appliedenergistics2.chiseled_quartz_slab.name=柱状ケルタスクォーツのハーフブロック
tile.appliedenergistics2.fluix_slab.name=フルーシュのハーフブロック
tile.appliedenergistics2.quartz_slab.name=ケルタスクォーツのハーフブロック
tile.appliedenergistics2.smooth_sky_stone_slab.name=スカイストーンブロックのハーフブロック
tile.appliedenergistics2.quartz_pillar_slab.name=様入りケルタスクォーツのハーフブロック
tile.appliedenergistics2.sky_stone_brick_slab.name=スカイストーンレンガのハーフブロック
tile.appliedenergistics2.sky_stone_small_brick_slab.name=小さなスカイストーンレンガのハーフブロック
tile.appliedenergistics2.sky_stone_slab.name=スカイストーンのハーフブロック
// Chat Messages
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.ResetSettings=新しい端末を設定してメモリカードにコピーしました。
chat.appliedenergistics2.AmmoDepleted=マターボールを使い切りました。
chat.appliedenergistics2.isNowLocked=モニターはロックされています。
chat.appliedenergistics2.isNowUnlocked=モニターはロックされていません。
// Creative Tabs
itemGroup.appliedenergistics2=Applied Energistics 2
itemGroup.appliedenergistics2.facades=Applied Energistics 2 - 偽装板
// GUI
gui.appliedenergistics2.CraftingTerminal=クラフティングターミナル
gui.appliedenergistics2.METunnel=ME
gui.appliedenergistics2.ItemTunnel=アイテム
gui.appliedenergistics2.FluidTunnel=液体
gui.appliedenergistics2.RedstoneTunnel=レッドストーン
gui.appliedenergistics2.EUTunnel=EU
gui.appliedenergistics2.FETunnel=FE
gui.appliedenergistics2.GTEUTunnel=GTEU
gui.appliedenergistics2.LightTunnel=光源
gui.appliedenergistics2.OCTunnel=OC
gui.appliedenergistics2.PressureTunnel=圧力
gui.appliedenergistics2.security.extract.name=搬出
gui.appliedenergistics2.security.inject.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.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=最大電力
gui.appliedenergistics2.QuartzCuttingKnife=クォーツナイフ
gui.appliedenergistics2.Inscriber=刻印機
gui.appliedenergistics2.Wireless=無線アクセスポイント
gui.appliedenergistics2.WirelessTerminal=無線ターミナル
gui.appliedenergistics2.NoPermissions=アクセス権が選択されていません。
gui.appliedenergistics2.SecurityCardEditor=生体認証カードエディタ
gui.appliedenergistics2.Encoded=エンコード済
gui.appliedenergistics2.Priority=優先度
gui.appliedenergistics2.StorageBus=ストレージバス
gui.appliedenergistics2.OreDictStorageBus=鉱石辞書ストレージバス
gui.appliedenergistics2.StorageBusFluids=液体ストレージバス
gui.appliedenergistics2.EnergyDrain=受動排出
gui.appliedenergistics2.Installed=インストール済
gui.appliedenergistics2.NetworkTool=ネットワークツール
gui.appliedenergistics2.PowerUsageRate=エネルギー使用量
gui.appliedenergistics2.PowerInputRate=エネルギー入力量
gui.appliedenergistics2.PortableCell=ポータブルセル
gui.appliedenergistics2.Security=セキュリティターミナル
gui.appliedenergistics2.CellWorkbench=セル作業台
gui.appliedenergistics2.QuantumLinkChamber=量子リンクチャンバー
gui.appliedenergistics2.IOPort=ME IOポート
gui.appliedenergistics2.Chest=MEチェスト
gui.appliedenergistics2.Condenser=マターコンデンサ
gui.appliedenergistics2.Config=設定
gui.appliedenergistics2.Drive=MEドライブ
gui.appliedenergistics2.ExportBus=ME出力バス
gui.appliedenergistics2.ExportBusFluids=ME液体出力バス
gui.appliedenergistics2.GrindStone=手動粉砕機
gui.appliedenergistics2.ImportBus=ME入力バス
gui.appliedenergistics2.ImportBusFluids=ME液体入力バス
gui.appliedenergistics2.Interface=MEインターフェース
gui.appliedenergistics2.FluidInterface=ME液体インターフェース
gui.appliedenergistics2.LevelEmitter=MEレベルエミッター
gui.appliedenergistics2.FluidLevelEmitter=ME液体レベルエミッター
gui.appliedenergistics2.Of=/
gui.appliedenergistics2.Patterns=パターン
gui.appliedenergistics2.SpatialIOPort=空間IOポート
gui.appliedenergistics2.StoredEnergy=貯蔵エネルギー
gui.appliedenergistics2.StoredItems=貯蔵アイテム
gui.appliedenergistics2.StoredFluids=貯蔵液体
gui.appliedenergistics2.Terminal=ターミナル
gui.appliedenergistics2.InterfaceTerminal=インターフェースターミナル
gui.appliedenergistics2.InterfaceTerminalHint=インターフェースターミナルから表示または非表示
gui.appliedenergistics2.FormationPlane=形成プレーン
gui.appliedenergistics2.FluidFormationPlane=液体形成プレーン
gui.appliedenergistics2.VibrationChamber=振動チャンバー
gui.appliedenergistics2.NetworkDetails=ネットワークの詳細
gui.appliedenergistics2.StorageCells=MEストレージセル
gui.appliedenergistics2.IOBuses=ME入力/出力バス
gui.appliedenergistics2.IOBusesFluids=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.SkyChest=スカイストーンチェスト
gui.appliedenergistics2.PatternTerminal=パターンターミナル
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.Yes=Yes
gui.appliedenergistics2.No=No
gui.appliedenergistics2.InWorldCrafting=AE2 直接クラフト
gui.appliedenergistics2.inWorldFluix=水たまりにチャージドケルタスクォーツ + ネザークォーツ + レッドストーンを落とし、しばらく待ってください。
gui.appliedenergistics2.inWorldPurificationCertus=水源にケルタスクォーツの粉と砂からクラフトしたケルタスクォーツの種を入れてください。処理を速くするにはクリスタル成長加速機に隣接して水源を設置し、そこにクラフトした種を入れてください。
gui.appliedenergistics2.inWorldPurificationNether=水源にネザークォーツの粉と砂からクラフトしたネザークォーツの種を入れてください。処理を速くするにはクリスタル成長加速機に隣接して水源を設置し、そこにクラフトした種を入れてください。
gui.appliedenergistics2.inWorldPurificationFluix=水源にフルーシュの粉と砂からクラフトしたフルーシュの種を入れてください。処理を速くするにはクリスタル成長加速機に隣接して水源を設置し、そこにクラフトした種を入れてください。
gui.appliedenergistics2.inWorldSingularity=作る為には一個のシンギュラリティとエンダーパールの粉を投げ、爆発に巻き込んでください。
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.Next=次
gui.appliedenergistics2.Lumen=ルーメン
gui.appliedenergistics2.Empty=空
gui.appliedenergistics2.Stored=在庫
gui.appliedenergistics2.Cancel=中止
gui.appliedenergistics2.ETAFormat=HH:mm:ss
gui.appliedenergistics2.Crafting=クラフティング
gui.appliedenergistics2.Scheduled=予定
gui.appliedenergistics2.CraftingStatus=クラフティング状況
gui.appliedenergistics2.FromStorage=利用可
gui.appliedenergistics2.ToCraft=クラフト予定
gui.appliedenergistics2.CraftingPlan=クラフティング計画
gui.appliedenergistics2.Automatic=自動
gui.appliedenergistics2.Start=スタート
gui.appliedenergistics2.Missing=不足
gui.appliedenergistics2.Bytes=ストレージ
gui.appliedenergistics2.Simulation=シミュレーション
gui.appliedenergistics2.CoProcessors=Coプロセッサ
gui.appliedenergistics2.CraftingCPU=クラフティングCPU
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=CPU
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.Substitutions=鉱石辞書の置換
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.FuzzyMode=ファジー比較
gui.tooltips.appliedenergistics2.FZPercent_25=25%%の分離損失
gui.tooltips.appliedenergistics2.FZPercent_50=50%%の分離損失
gui.tooltips.appliedenergistics2.FZPercent_75=75%%の分離損失
gui.tooltips.appliedenergistics2.FZPercent_99=99%%の分離損失
gui.tooltips.appliedenergistics2.SortOrder=昇順/降順
gui.tooltips.appliedenergistics2.SortBy=並び替え方法
gui.tooltips.appliedenergistics2.FZIgnoreAll=すべてマッチする
gui.tooltips.appliedenergistics2.TransferDirection=転送方向
gui.tooltips.appliedenergistics2.TransferToNetwork=ネットワークへ
gui.tooltips.appliedenergistics2.TransferToStorageCell=ストレージセルへ
gui.tooltips.appliedenergistics2.ToggleSortDirection=昇順/降順の切り替え
gui.tooltips.appliedenergistics2.StoredItems=格納アイテム
gui.tooltips.appliedenergistics2.StoredCraftable=格納アイテム/クラフト可能アイテム
gui.tooltips.appliedenergistics2.View=表示アイテム
gui.tooltips.appliedenergistics2.RedstoneMode=レッドストーン制御
gui.tooltips.appliedenergistics2.OperationMode=動作モード
gui.tooltips.appliedenergistics2.NumberOfItems=アイテム数
gui.tooltips.appliedenergistics2.ItemName=アイテム名
gui.tooltips.appliedenergistics2.PowerUnits=パワーユニット
gui.tooltips.appliedenergistics2.IOMode=入出力モード
gui.tooltips.appliedenergistics2.CondenserOutput=MEコンデンサ - 出力
gui.tooltips.appliedenergistics2.PartitionStorage=パーティションストレージ
gui.tooltips.appliedenergistics2.Clear=リセット
gui.tooltips.appliedenergistics2.TrashController=Shift/Spaceで有効
gui.tooltips.appliedenergistics2.InterfaceBlockingMode=ブロッキングモード
gui.tooltips.appliedenergistics2.InterfaceCraftingMode=クラフティングモード
gui.tooltips.appliedenergistics2.Trash=アイテムを破棄する
gui.tooltips.appliedenergistics2.MatterBalls=\n%s個のアイテムごとにマターボールに変換する
gui.tooltips.appliedenergistics2.Singularity=\n%s個のアイテムごとにシンギュラリティに変換する
gui.tooltips.appliedenergistics2.Read=出力のみ
gui.tooltips.appliedenergistics2.Write=入力のみ
gui.tooltips.appliedenergistics2.ReadWrite=入出力可能
gui.tooltips.appliedenergistics2.AlwaysActive=常時処理
gui.tooltips.appliedenergistics2.ActiveWithoutSignal=RS信号なし
gui.tooltips.appliedenergistics2.ActiveWithSignal=RS信号あり
gui.tooltips.appliedenergistics2.ActiveOnPulse=RSパルス
gui.tooltips.appliedenergistics2.EmitLevelsBelow=設定値以下で出力
gui.tooltips.appliedenergistics2.EmitLevelAbove=設定値以上で出力
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=コンフィグ/設定をクリア
gui.tooltips.appliedenergistics2.Craftable=クラフト可能
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.LevelType=レベルタイプ
gui.tooltips.appliedenergistics2.LevelType_Energy=エネルギー
gui.tooltips.appliedenergistics2.LevelType_Item=アイテム
gui.tooltips.appliedenergistics2.InventoryTweaks=Inventory Tweaks
gui.tooltips.appliedenergistics2.Mod=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=Yes: 搬出できないアイテムがネットワークで可視化されます
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=No: 搬出できるアイテムのみがネットワークで可視化されます
gui.tooltips.appliedenergistics2.ReportInaccessibleFluids=アクセスできない液体を報告する
gui.tooltips.appliedenergistics2.ReportInaccessibleFluidsYes=Yes: 搬出できない液体がネットワークで可視化されます
gui.tooltips.appliedenergistics2.ReportInaccessibleFluidsNo=No: 搬出できる液体のみがネットワークで可視化されます
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を開くたびにリセットする
gui.tooltips.appliedenergistics2.ItemsStored=在庫アイテム: %s
gui.tooltips.appliedenergistics2.ItemsRequestable=要求可能なアイテム: %s
gui.tooltips.appliedenergistics2.P2PFrequency=周波数: %s
gui.tooltips.appliedenergistics2.MultiplyByTwo=アイテムを倍にする
gui.tooltips.appliedenergistics2.MultiplyByTwoDesc=スロットのアイテム数を倍にすることを試みる。
gui.tooltips.appliedenergistics2.MultiplyByThree=アイテムを3倍にする
gui.tooltips.appliedenergistics2.MultiplyByThreeDesc=スロットのアイテム数を3倍にすることを試みる。
gui.tooltips.appliedenergistics2.IncreaseByOne=1個追加
gui.tooltips.appliedenergistics2.IncreaseByOneDesc=スロットのアイテム数を1個増やすことを試みる。材料の比率は保持されない。
gui.tooltips.appliedenergistics2.DivideByTwo=2で割る
gui.tooltips.appliedenergistics2.DivideByTwoDesc=スロットのアイテム数を2で割ることを試みる。
gui.tooltips.appliedenergistics2.DivideByThree=3で割る
gui.tooltips.appliedenergistics2.DivideByThreeDesc=スロットのアイテム数を3で割ることを試みる。
gui.tooltips.appliedenergistics2.DecreaseByOne=1個減らす
gui.tooltips.appliedenergistics2.DecreaseByOneDesc=スロットのアイテム数を1個減らすことを試みる。材料の比率は保持されない。
gui.tooltips.appliedenergistics2.MaxCount=スロットのアイテム数を最大化
gui.tooltips.appliedenergistics2.MaxCountDesc=材料アイテムの比率を保ったままスロットのアイテム数を最大化する。
gui.tooltips.appliedenergistics2.FreeMolecularSlotShortcut=スロットが空いているインターフェースを表示する。
gui.tooltips.appliedenergistics2.FreeMolecularSlotShortcutDesc=スロットが空いているインターフェースを切り替えて分子組立室を検索するショートカット。
gui.tooltips.appliedenergistics2.ToggleShowFullInterfaces=スロットが一杯になっているインターフェースの表示切り替え
gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOnDesc=全てのインターフェースを表示。
gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOffDesc=空きがあるインターフェースのみを表示。
gui.tooltips.appliedenergistics2.HighlightInterface=インターフェースを強調表示
// Units
gui.appliedenergistics2.units.appliedenergstics=AE
gui.appliedenergistics2.units.ic2=EU
gui.appliedenergistics2.units.rf=RF
gui.appliedenergistics2.units.gteu=GTEU
// Colors
gui.appliedenergistics2.White=白色
gui.appliedenergistics2.Orange=橙色
gui.appliedenergistics2.Magenta=赤紫色
gui.appliedenergistics2.LightBlue=空色
gui.appliedenergistics2.Yellow=黄色
gui.appliedenergistics2.Lime=黄緑色
gui.appliedenergistics2.Pink=桃色
gui.appliedenergistics2.Gray=灰色
gui.appliedenergistics2.LightGray=薄灰色
gui.appliedenergistics2.Cyan=水色
gui.appliedenergistics2.Purple=紫色
gui.appliedenergistics2.Blue=青色
gui.appliedenergistics2.Brown=茶色
gui.appliedenergistics2.Green=緑色
gui.appliedenergistics2.Red=赤色
gui.appliedenergistics2.Black=黒色
gui.appliedenergistics2.Fluix=フルーシュ
// Waila
waila.appliedenergistics2.Crafting=クラフト中
waila.appliedenergistics2.DeviceOnline=装置はオンラインです
waila.appliedenergistics2.DeviceOffline=装置はオフラインです
waila.appliedenergistics2.DeviceMissingChannel=装置のチャンネルが見つかりません
waila.appliedenergistics2.Locked=ロックされています
waila.appliedenergistics2.Unlocked=ロックされてません
waila.appliedenergistics2.Showing=表示中
waila.appliedenergistics2.Contains=格納
waila.appliedenergistics2.Channels=%2$d中%1$dチャンネル使用中
waila.appliedenergistics2.P2PUnlinked=設定待機中
waila.appliedenergistics2.p2p_input_one_output=1個接続中 (接続元)
waila.appliedenergistics2.p2p_input_many_outputs=%d個接続中 (接続元)
waila.appliedenergistics2.p2p_output_one_input=1個接続中 (接続先)
waila.appliedenergistics2.p2p_output_many_inputs=%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=%2$d中%1$dチャンネル使用中
theoneprobe.appliedenergistics2.p2p_unlinked=設定待機中
theoneprobe.appliedenergistics2.p2p_input_one_output=1個接続中 (接続元)
theoneprobe.appliedenergistics2.p2p_input_many_outputs=%d個接続中 (接続元)
theoneprobe.appliedenergistics2.p2p_output_one_input=1個接続中 (接続先)
theoneprobe.appliedenergistics2.p2p_output_many_inputs=%d個接続中 (接続先)
theoneprobe.appliedenergistics2.p2p_output=接続中 (接続先)
theoneprobe.appliedenergistics2.p2p_frequency=周波数: %1$s
theoneprobe.appliedenergistics2.stored_energy=%1$d / %2$d
// Items
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.fluid_storage_cell_1k.name=1k ME液体セル
item.appliedenergistics2.fluid_storage_cell_4k.name=4k ME液体セル
item.appliedenergistics2.fluid_storage_cell_16k.name=16k ME液体セル
item.appliedenergistics2.fluid_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.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_pattern_expansion.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.fluid_cell1k_part.name=1k ME液体コンポーネント
item.appliedenergistics2.material.fluid_cell4k_part.name=4k ME液体コンポーネント
item.appliedenergistics2.material.fluid_cell16k_part.name=16k ME液体コンポーネント
item.appliedenergistics2.material.fluid_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.multi_part.annihilation_plane.name=ME消滅プレーン
item.appliedenergistics2.multi_part.fluid_annihilation_plane.name=ME液体消滅プレーン
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.fluid_export_bus.name=ME液体出力バス
item.appliedenergistics2.multi_part.formation_plane.name=ME形成プレーン
item.appliedenergistics2.multi_part.fluid_formation_plane.name=ME液体形成プレーン
item.appliedenergistics2.multi_part.import_bus.name=ME入力バス
item.appliedenergistics2.multi_part.fluid_import_bus.name=ME液体入力バス
item.appliedenergistics2.multi_part.interface.name=MEインターフェース
item.appliedenergistics2.multi_part.fluid_interface.name=ME液体インターフェース
item.appliedenergistics2.multi_part.level_emitter.name=MEレベルエミッタ
item.appliedenergistics2.multi_part.fluid_level_emitter.name=ME液体レベルエミッタ
item.appliedenergistics2.multi_part.p2p_tunnel.name=P2Pトンネル
item.appliedenergistics2.multi_part.pattern_terminal.name=MEパターンターミナル
item.appliedenergistics2.multi_part.expanded_processing_pattern_terminal.name=ME拡張パターンターミナル
item.appliedenergistics2.multi_part.quartz_fiber.name=クォーツファイバー
item.appliedenergistics2.multi_part.storage_bus.name=MEストレージバス
item.appliedenergistics2.multi_part.oredict_storage_bus.name=ME鉱石辞書ストレージバス
item.appliedenergistics2.multi_part.fluid_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.fluid_terminal.name=ME液体インターフェースターミナル
item.appliedenergistics2.multi_part.invalid_type.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.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.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.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=開発用.デバッグ用カード
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=チャンクロギングを開始しました。
commands.ae2.ChunkLoggerOff=チャンクロギングを終了しました。
commands.ae2.Supporters=AE2サポーターの一覧を表示します。
// Achievements
achievement.ae2.Root=Applied Energistics 2
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=空間IOポートを作る。
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=MEケーブルを作る。
achievement.ae2.Controller=ネットワークの配電盤
achievement.ae2.Controller.desc=コントローラを作る。
achievement.ae2.Networking1=ネットワークの実習生
achievement.ae2.Networking1.desc=ネットワーク上のチャンネルが8個に到達する。
achievement.ae2.Networking2=ネットワークの設計者
achievement.ae2.Networking2.desc=ネットワーク上のチャンネルが128個に到達する。
achievement.ae2.Networking3=ネットワークの管理者
achievement.ae2.Networking3.desc=ネットワーク上のチャンネルが2048個に到達する。
achievement.ae2.P2P=ポイント・トゥ・ポイント(ピア・トゥ・ピアではない)
achievement.ae2.P2P.desc=P2Pトンネルを作る。
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=MEストレージセルに搬入したアイテム数
stat.ae2.ItemsExtracted=MEストレージセルから搬出したアイテム数
stat.ae2.TurnedCranks=クランクを回した回数
// Keys
key.appliedenergistics2.category=Applied Energistics 2
key.toggle_focus.desc=検索ボックスの切り替え
@@ -16,6 +16,7 @@ tile.appliedenergistics2.matrix_frame.name=Каркас матрицы
tile.appliedenergistics2.io_port.name=МЭ порт ввода\вывода tile.appliedenergistics2.io_port.name=МЭ порт ввода\вывода
tile.appliedenergistics2.inscriber.name=Высекатель tile.appliedenergistics2.inscriber.name=Высекатель
tile.appliedenergistics2.interface.name=МЭ интерфейс tile.appliedenergistics2.interface.name=МЭ интерфейс
tile.appliedenergistics2.fluid_interface.name=МЭ жидкостный интерфейс
tile.appliedenergistics2.quantum_link.name=МЭ камера квантовой связи tile.appliedenergistics2.quantum_link.name=МЭ камера квантовой связи
tile.appliedenergistics2.quantum_ring.name=МЭ квантовое кольцо tile.appliedenergistics2.quantum_ring.name=МЭ квантовое кольцо
tile.appliedenergistics2.fluix_block.name=Изменчивый блок tile.appliedenergistics2.fluix_block.name=Изменчивый блок
@@ -84,6 +85,7 @@ chat.appliedenergistics2.StationCanNotBeLocated=Станция не найден
chat.appliedenergistics2.MachineNotPowered=Устройство без питания. chat.appliedenergistics2.MachineNotPowered=Устройство без питания.
chat.appliedenergistics2.CommunicationError=Ошибка связи с сетью. chat.appliedenergistics2.CommunicationError=Ошибка связи с сетью.
chat.appliedenergistics2.SavedSettings=Настройки успешно сохранены. chat.appliedenergistics2.SavedSettings=Настройки успешно сохранены.
chat.appliedenergistics2.ResetSettings=Новая конфигурация устройства создана и скопирована на карту памяти.
chat.appliedenergistics2.AmmoDepleted=Боеприпасы исчерпаны. chat.appliedenergistics2.AmmoDepleted=Боеприпасы исчерпаны.
chat.appliedenergistics2.isNowLocked=Монитор заблокирован. chat.appliedenergistics2.isNowLocked=Монитор заблокирован.
chat.appliedenergistics2.isNowUnlocked=Монитор разблокирован. chat.appliedenergistics2.isNowUnlocked=Монитор разблокирован.
@@ -100,6 +102,7 @@ gui.appliedenergistics2.FluidTunnel=Жидкость
gui.appliedenergistics2.RedstoneTunnel=Красный камень gui.appliedenergistics2.RedstoneTunnel=Красный камень
gui.appliedenergistics2.EUTunnel=EU gui.appliedenergistics2.EUTunnel=EU
gui.appliedenergistics2.FETunnel=FE gui.appliedenergistics2.FETunnel=FE
gui.appliedenergistics2.GTEUTunnel=GTEU
gui.appliedenergistics2.LightTunnel=Свет gui.appliedenergistics2.LightTunnel=Свет
gui.appliedenergistics2.OCTunnel=OpenComputers gui.appliedenergistics2.OCTunnel=OpenComputers
gui.appliedenergistics2.PressureTunnel=Давление gui.appliedenergistics2.PressureTunnel=Давление
@@ -131,6 +134,8 @@ gui.appliedenergistics2.SecurityCardEditor=Редактор биометриче
gui.appliedenergistics2.Encoded=Зашифрованный gui.appliedenergistics2.Encoded=Зашифрованный
gui.appliedenergistics2.Priority=Приоритет gui.appliedenergistics2.Priority=Приоритет
gui.appliedenergistics2.StorageBus=Шина хранения gui.appliedenergistics2.StorageBus=Шина хранения
gui.appliedenergistics2.OreDictStorageBus=Шина хранения по словарю руд
gui.appliedenergistics2.StorageBusFluids=Шина хранения жидкости
gui.appliedenergistics2.EnergyDrain=Пассивное потребление gui.appliedenergistics2.EnergyDrain=Пассивное потребление
gui.appliedenergistics2.Installed=Установлено gui.appliedenergistics2.Installed=Установлено
gui.appliedenergistics2.NetworkTool=Сетевой инструмент gui.appliedenergistics2.NetworkTool=Сетевой инструмент
@@ -146,23 +151,30 @@ gui.appliedenergistics2.Condenser=Конденсатор материи
gui.appliedenergistics2.Config=Настройки gui.appliedenergistics2.Config=Настройки
gui.appliedenergistics2.Drive=МЭ накопитель gui.appliedenergistics2.Drive=МЭ накопитель
gui.appliedenergistics2.ExportBus=МЭ шина экспорта gui.appliedenergistics2.ExportBus=МЭ шина экспорта
gui.appliedenergistics2.ExportBusFluids=МЭ жидкостная шина экспорта
gui.appliedenergistics2.GrindStone=Дробитель gui.appliedenergistics2.GrindStone=Дробитель
gui.appliedenergistics2.ImportBus=МЭ шина импорта gui.appliedenergistics2.ImportBus=МЭ шина импорта
gui.appliedenergistics2.ImportBusFluids=MЭ жидкостная шина импорта
gui.appliedenergistics2.Interface=МЭ интерфейс gui.appliedenergistics2.Interface=МЭ интерфейс
gui.appliedenergistics2.FluidInterface=МЭ жидкостный интерфейс
gui.appliedenergistics2.LevelEmitter=МЭ излучатель уровня gui.appliedenergistics2.LevelEmitter=МЭ излучатель уровня
gui.appliedenergistics2.FluidLevelEmitter=МЭ жидкостный излучатель уровня
gui.appliedenergistics2.Of=из gui.appliedenergistics2.Of=из
gui.appliedenergistics2.Patterns=Шаблоны gui.appliedenergistics2.Patterns=Шаблоны
gui.appliedenergistics2.SpatialIOPort=Пространственный порт ввода\вывода gui.appliedenergistics2.SpatialIOPort=Пространственный порт ввода\вывода
gui.appliedenergistics2.StoredEnergy=Накопленная энергия gui.appliedenergistics2.StoredEnergy=Накопленная энергия
gui.appliedenergistics2.StoredItems=Хранящиеся предметы gui.appliedenergistics2.StoredItems=Хранящиеся предметы
gui.appliedenergistics2.StoredFluids=Хранящиеся жидкости
gui.appliedenergistics2.Terminal=Терминал gui.appliedenergistics2.Terminal=Терминал
gui.appliedenergistics2.InterfaceTerminal=Терминал интерфейсов gui.appliedenergistics2.InterfaceTerminal=Терминал интерфейсов
gui.appliedenergistics2.InterfaceTerminalHint=Показать или спрятать в терминале интерфейсов. gui.appliedenergistics2.InterfaceTerminalHint=Показать или спрятать в терминале интерфейсов.
gui.appliedenergistics2.FormationPlane=Плоскость формирования gui.appliedenergistics2.FormationPlane=Плоскость формирования
gui.appliedenergistics2.FluidFormationPlane=Плоскость формирования жидкости
gui.appliedenergistics2.VibrationChamber=Вибрационная камера gui.appliedenergistics2.VibrationChamber=Вибрационная камера
gui.appliedenergistics2.NetworkDetails=Подробности сети gui.appliedenergistics2.NetworkDetails=Подробности сети
gui.appliedenergistics2.StorageCells=МЭ ячейки хранения gui.appliedenergistics2.StorageCells=МЭ ячейки хранения
gui.appliedenergistics2.IOBuses=МЭ шина импорта\экспорта gui.appliedenergistics2.IOBuses=МЭ шина импорта\экспорта
gui.appliedenergistics2.IOBusesFluids=МЭ жидкостная шина импорта\экспорта
gui.appliedenergistics2.Stores=Хранит gui.appliedenergistics2.Stores=Хранит
gui.appliedenergistics2.BytesUsed=байт использовано gui.appliedenergistics2.BytesUsed=байт использовано
gui.appliedenergistics2.Types=типов gui.appliedenergistics2.Types=типов
@@ -323,6 +335,9 @@ gui.tooltips.appliedenergistics2.EmitWhenCrafting=Излучать сигнал
gui.tooltips.appliedenergistics2.ReportInaccessibleItems=Сообщать о недоступных вещах gui.tooltips.appliedenergistics2.ReportInaccessibleItems=Сообщать о недоступных вещах
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=Да: Предметы, которые не могут быть извлечены, будут видны. gui.tooltips.appliedenergistics2.ReportInaccessibleItemsYes=Да: Предметы, которые не могут быть извлечены, будут видны.
gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=Нет: Только извлекаемые предметы будут видны. gui.tooltips.appliedenergistics2.ReportInaccessibleItemsNo=Нет: Только извлекаемые предметы будут видны.
gui.tooltips.appliedenergistics2.ReportInaccessibleFluids=Сообщать о недоступных жидкостях
gui.tooltips.appliedenergistics2.ReportInaccessibleFluidsYes=Да: Жидкости, которые невозможно извлечь, будут видны.
gui.tooltips.appliedenergistics2.ReportInaccessibleFluidsNo=Нет: будут видны только извлекаемые жидкости.
gui.tooltips.appliedenergistics2.BlockPlacement=Размещение блоков gui.tooltips.appliedenergistics2.BlockPlacement=Размещение блоков
gui.tooltips.appliedenergistics2.BlockPlacementYes=Блоки будут размещаться в виде блоков. gui.tooltips.appliedenergistics2.BlockPlacementYes=Блоки будут размещаться в виде блоков.
gui.tooltips.appliedenergistics2.BlockPlacementNo=Блоки будут выпадать в виде предметов. gui.tooltips.appliedenergistics2.BlockPlacementNo=Блоки будут выпадать в виде предметов.
@@ -335,11 +350,33 @@ gui.tooltips.appliedenergistics2.FilterModeKeep=Восстановить пре
gui.tooltips.appliedenergistics2.FilterModeClear=Очищать при каждом открытии. gui.tooltips.appliedenergistics2.FilterModeClear=Очищать при каждом открытии.
gui.tooltips.appliedenergistics2.ItemsStored=Хранящиеся предметы: %s gui.tooltips.appliedenergistics2.ItemsStored=Хранящиеся предметы: %s
gui.tooltips.appliedenergistics2.ItemsRequestable=Запрашиваемые предметы: %s gui.tooltips.appliedenergistics2.ItemsRequestable=Запрашиваемые предметы: %s
gui.tooltips.appliedenergistics2.P2PFrequency=Частота: %s
gui.tooltips.appliedenergistics2.MultiplyByTwo=Удвоить колличество предметов
gui.tooltips.appliedenergistics2.MultiplyByTwoDesc=Удвоить колличество предметов, установленных в слотах для крафта
gui.tooltips.appliedenergistics2.MultiplyByThree=Утроить колличество предметов
gui.tooltips.appliedenergistics2.MultiplyByThreeDesc=Утроить колличество предметов, установленных в слотах для крафта
gui.tooltips.appliedenergistics2.IncreaseByOne=Увеличить на единицу
gui.tooltips.appliedenergistics2.IncreaseByOneDesc=Добавить по одному предмету, установленных в слотах для крафта, на единицу. НЕ СОХРАНЯЕТ СООТНОШЕНИЕ ИНГРЕДИЕНТОВ
gui.tooltips.appliedenergistics2.DivideByTwo=Разделить набор предметов на два
gui.tooltips.appliedenergistics2.DivideByTwoDesc=Пытается разделить на 2 предметы, установленные в слотах для крафта
gui.tooltips.appliedenergistics2.DivideByThree=Разделить набор элементов на три
gui.tooltips.appliedenergistics2.DivideByThreeDesc=Пытается разделить на 3 предметы, установленные в слотах для крафта
gui.tooltips.appliedenergistics2.DecreaseByOne=Уменьшить на единицу
gui.tooltips.appliedenergistics2.DecreaseByOneDesc=Попытаюсь добавить уменьшение количества предметов, установленных в слотах для крафта, на единицу НЕ ПОДДЕРЖИВАЕТ СООТНОШЕНИЕ ИНГРЕДИЕНТОВ
gui.tooltips.appliedenergistics2.MaxCount=Увеличить количество слотов
gui.tooltips.appliedenergistics2.MaxCountDesc=Будет максимизировать выход, сохраняя коэффициент ввода предметов, установленных в слотах крафта
gui.tooltips.appliedenergistics2.FreeMolecularSlotShortcut=Показать интерфейсы крафта со свободными слотами
gui.tooltips.appliedenergistics2.FreeMolecularSlotShortcutDesc=Ярлык, который переключает интерфейсы со свободными слотами и ищет молекулярные ассемблеры
gui.tooltips.appliedenergistics2.ToggleShowFullInterfaces=Переключает отображение интерфейсов с заполненными слотами
gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOnDesc=Показ всех интерфейсов
gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOffDesc=Показаны только интерфейсы со свободными слотами
gui.tooltips.appliedenergistics2.HighlightInterface=Подсветка интерфейса
// Units // Units
gui.appliedenergistics2.units.appliedenergstics=AE gui.appliedenergistics2.units.appliedenergstics=AE
gui.appliedenergistics2.units.ic2=Energy Units gui.appliedenergistics2.units.ic2=Energy Units
gui.appliedenergistics2.units.rf=Redstone Flux gui.appliedenergistics2.units.rf=Redstone Flux
gui.appliedenergistics2.units.gteu=GTEU
// Colors // Colors
gui.appliedenergistics2.White=Белый gui.appliedenergistics2.White=Белый
@@ -373,6 +410,8 @@ waila.appliedenergistics2.Channels=Каналы: %1$d из %2$d
waila.appliedenergistics2.P2PUnlinked=Не связанный waila.appliedenergistics2.P2PUnlinked=Не связанный
waila.appliedenergistics2.P2PInputOneOutput=Связанный (Сторона ввода) waila.appliedenergistics2.P2PInputOneOutput=Связанный (Сторона ввода)
waila.appliedenergistics2.P2PInputManyOutputs=Связанный (Сторона ввода) - %d выводов waila.appliedenergistics2.P2PInputManyOutputs=Связанный (Сторона ввода) - %d выводов
waila.appliedenergistics2.p2p_output_one_input=Связанный (Сторона вывода)
waila.appliedenergistics2.p2p_output_many_inputs=Связанный (Сторона вывода) - %d выводов
waila.appliedenergistics2.P2POutput=Связанный (Сторона вывода) waila.appliedenergistics2.P2POutput=Связанный (Сторона вывода)
// TheOneProbe // TheOneProbe
@@ -388,7 +427,10 @@ theoneprobe.appliedenergistics2.channels=Каналы: %1$d из %2$d
theoneprobe.appliedenergistics2.p2p_unlinked=Не связанный theoneprobe.appliedenergistics2.p2p_unlinked=Не связанный
theoneprobe.appliedenergistics2.p2p_input_one_output=Связанный (сторона ввода) theoneprobe.appliedenergistics2.p2p_input_one_output=Связанный (сторона ввода)
theoneprobe.appliedenergistics2.p2p_input_many_outputs=Связанный (сторона ввода) - %d выводов theoneprobe.appliedenergistics2.p2p_input_many_outputs=Связанный (сторона ввода) - %d выводов
theoneprobe.appliedenergistics2.p2p_output_one_input=Связанный (Сторона вывода)
theoneprobe.appliedenergistics2.p2p_output_many_inputs=Связанный (Сторона вывода) - %d выводов
theoneprobe.appliedenergistics2.p2p_output=Связанный (Сторона вывода) theoneprobe.appliedenergistics2.p2p_output=Связанный (Сторона вывода)
theoneprobe.appliedenergistics2.p2p_frequency=Частота: %1$s
theoneprobe.appliedenergistics2.stored_energy=%1$d / %2$d theoneprobe.appliedenergistics2.stored_energy=%1$d / %2$d
// Items // Items
@@ -396,6 +438,10 @@ item.appliedenergistics2.storage_cell_1k.name=1К МЭ ячейка хранен
item.appliedenergistics2.storage_cell_4k.name=4К МЭ ячейка хранения item.appliedenergistics2.storage_cell_4k.name=4К МЭ ячейка хранения
item.appliedenergistics2.storage_cell_16k.name=16К МЭ ячейка хранения item.appliedenergistics2.storage_cell_16k.name=16К МЭ ячейка хранения
item.appliedenergistics2.storage_cell_64k.name=64К МЭ ячейка хранения item.appliedenergistics2.storage_cell_64k.name=64К МЭ ячейка хранения
item.appliedenergistics2.fluid_storage_cell_1k.name=1К МЭ жидкостная ячейка хранения
item.appliedenergistics2.fluid_storage_cell_4k.name=4К МЭ жидкостная ячейка хранения
item.appliedenergistics2.fluid_storage_cell_16k.name=16К МЭ жидкостная ячейка хранения
item.appliedenergistics2.fluid_storage_cell_64k.name=64К МЭ жидкостная ячейка хранения
item.appliedenergistics2.creative_storage_cell.name=Творческая МЭ ячейка хранения item.appliedenergistics2.creative_storage_cell.name=Творческая МЭ ячейка хранения
item.appliedenergistics2.encoded_pattern.name=Кодированный шаблон item.appliedenergistics2.encoded_pattern.name=Кодированный шаблон
item.appliedenergistics2.view_cell.name=Ячейка представления item.appliedenergistics2.view_cell.name=Ячейка представления
@@ -411,6 +457,7 @@ item.appliedenergistics2.material.basic_card.name=Базовая карта
item.appliedenergistics2.material.blank_pattern.name=Пустой шаблон item.appliedenergistics2.material.blank_pattern.name=Пустой шаблон
item.appliedenergistics2.material.calculation_processor.name=Вычислительный процессор item.appliedenergistics2.material.calculation_processor.name=Вычислительный процессор
item.appliedenergistics2.material.card_capacity.name=Карта ёмкости item.appliedenergistics2.material.card_capacity.name=Карта ёмкости
item.appliedenergistics2.material.card_pattern_expansion.name=Карта расширения шаблона
item.appliedenergistics2.material.card_fuzzy.name=Карта нечёткости item.appliedenergistics2.material.card_fuzzy.name=Карта нечёткости
item.appliedenergistics2.material.card_inverter.name=Карта инвертирования item.appliedenergistics2.material.card_inverter.name=Карта инвертирования
item.appliedenergistics2.material.card_redstone.name=Карта красного камня item.appliedenergistics2.material.card_redstone.name=Карта красного камня
@@ -422,6 +469,10 @@ item.appliedenergistics2.material.cell1k_part.name=1К МЭ компонент
item.appliedenergistics2.material.cell4k_part.name=4К МЭ компонент хранения item.appliedenergistics2.material.cell4k_part.name=4К МЭ компонент хранения
item.appliedenergistics2.material.cell16k_part.name=16К МЭ компонент хранения item.appliedenergistics2.material.cell16k_part.name=16К МЭ компонент хранения
item.appliedenergistics2.material.cell64k_part.name=64К МЭ компонент хранения item.appliedenergistics2.material.cell64k_part.name=64К МЭ компонент хранения
item.appliedenergistics2.material.fluid_cell1k_part.name=1К МЭ жидкостный компонент хранения
item.appliedenergistics2.material.fluid_cell4k_part.name=4К МЭ жидкостный компонент хранения
item.appliedenergistics2.material.fluid_cell16k_part.name=16К МЭ жидкостный компонент хранения
item.appliedenergistics2.material.fluid_cell64k_part.name=64К МЭ жидкостный компонент хранения
item.appliedenergistics2.material.certus_quartz_crystal.name=Кристалл истинного кварца item.appliedenergistics2.material.certus_quartz_crystal.name=Кристалл истинного кварца
item.appliedenergistics2.material.certus_quartz_crystal_charged.name=Заряженный кристалл истинного кварца item.appliedenergistics2.material.certus_quartz_crystal_charged.name=Заряженный кристалл истинного кварца
item.appliedenergistics2.material.certus_quartz_dust.name=Пыль истинного кварца item.appliedenergistics2.material.certus_quartz_dust.name=Пыль истинного кварца
@@ -461,6 +512,7 @@ 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.annihilation_plane.name=МЭ плоскость истребления
item.appliedenergistics2.multi_part.fluid_annihilation_plane.name=МЭ жидкостная плоскость истребления
item.appliedenergistics2.multi_part.identity_annihilation_plane.name=МЭ id плоскость истребления item.appliedenergistics2.multi_part.identity_annihilation_plane.name=МЭ id плоскость истребления
item.appliedenergistics2.multi_part.cable_anchor.name=Кабельный якорь item.appliedenergistics2.multi_part.cable_anchor.name=Кабельный якорь
item.appliedenergistics2.multi_part.cable_covered.name=МЭ закрытый кабель item.appliedenergistics2.multi_part.cable_covered.name=МЭ закрытый кабель
@@ -475,19 +527,28 @@ item.appliedenergistics2.multi_part.semi_dark_monitor.name=Осветитель
item.appliedenergistics2.multi_part.monitor.name=Яркая осветительная панель item.appliedenergistics2.multi_part.monitor.name=Яркая осветительная панель
item.appliedenergistics2.multi_part.dark_monitor.name=Тёмная осветительная панель item.appliedenergistics2.multi_part.dark_monitor.name=Тёмная осветительная панель
item.appliedenergistics2.multi_part.export_bus.name=МЭ шина экспорта item.appliedenergistics2.multi_part.export_bus.name=МЭ шина экспорта
item.appliedenergistics2.multi_part.fluid_export_bus.name=МЭ жидкостная шина экспорта
item.appliedenergistics2.multi_part.formation_plane.name=МЭ плоскость формирования item.appliedenergistics2.multi_part.formation_plane.name=МЭ плоскость формирования
item.appliedenergistics2.multi_part.fluid_formation_plane.name=МЭ жидкостная плоскость формирования
item.appliedenergistics2.multi_part.import_bus.name=МЭ шина импорта item.appliedenergistics2.multi_part.import_bus.name=МЭ шина импорта
item.appliedenergistics2.multi_part.fluid_import_bus.name=МЭ жидкостная шина импорта
item.appliedenergistics2.multi_part.interface.name=МЭ интерфейс item.appliedenergistics2.multi_part.interface.name=МЭ интерфейс
item.appliedenergistics2.multi_part.fluid_interface.name=МЭ интерфейс жидкостей
item.appliedenergistics2.multi_part.level_emitter.name=МЭ излучатель уровня item.appliedenergistics2.multi_part.level_emitter.name=МЭ излучатель уровня
item.appliedenergistics2.multi_part.fluid_level_emitter.name=МЭ излучатель уровня
item.appliedenergistics2.multi_part.p2p_tunnel.name=Туннель точка-точка item.appliedenergistics2.multi_part.p2p_tunnel.name=Туннель точка-точка
item.appliedenergistics2.multi_part.pattern_terminal.name=МЭ терминал шаблонов item.appliedenergistics2.multi_part.pattern_terminal.name=МЭ терминал шаблонов
item.appliedenergistics2.multi_part.expanded_processing_pattern_terminal.name=ME терминал расширенной схемы обработки
item.appliedenergistics2.multi_part.quartz_fiber.name=Кварцевое оптическое волокно item.appliedenergistics2.multi_part.quartz_fiber.name=Кварцевое оптическое волокно
item.appliedenergistics2.multi_part.storage_bus.name=МЭ шина хранения item.appliedenergistics2.multi_part.storage_bus.name=МЭ шина хранения
item.appliedenergistics2.multi_part.oredict_storage_bus.name=МЭ шина хранения по словарю руд
item.appliedenergistics2.multi_part.fluid_storage_bus.name=МЭ жидкостная шина хранения
item.appliedenergistics2.multi_part.terminal.name=МЭ терминал item.appliedenergistics2.multi_part.terminal.name=МЭ терминал
item.appliedenergistics2.multi_part.inverted_toggle_bus.name=МЭ инвертированная шина переключения item.appliedenergistics2.multi_part.inverted_toggle_bus.name=МЭ инвертированная шина переключения
item.appliedenergistics2.multi_part.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.interface_terminal.name=МЭ терминал интерфейсов
item.appliedenergistics2.multi_part.fluid_terminal.name=МЭ жидкостный терминал
item.appliedenergistics2.multi_part.invalid_type.name=Отключенный предмет item.appliedenergistics2.multi_part.invalid_type.name=Отключенный предмет
item.appliedenergistics2.spatial_storage_cell_128_cubed.name=128³ пространственная ячейка хранения item.appliedenergistics2.spatial_storage_cell_128_cubed.name=128³ пространственная ячейка хранения
@@ -590,3 +651,7 @@ achievement.ae2.QNB.desc=Сделайте квантовое соединени
stat.ae2.ItemsInserted=Предметов добавлено в МЭ хранилище stat.ae2.ItemsInserted=Предметов добавлено в МЭ хранилище
stat.ae2.ItemsExtracted=Предметов извлечено из МЭ хранилища stat.ae2.ItemsExtracted=Предметов извлечено из МЭ хранилища
stat.ae2.TurnedCranks=Сломано рукояток stat.ae2.TurnedCranks=Сломано рукояток
//Keys
key.appliedenergistics2.category=Applied Energistics 2
key.toggle_focus.desc=Переключить фокус окна поиска
@@ -102,6 +102,7 @@ gui.appliedenergistics2.FluidTunnel=流体
gui.appliedenergistics2.RedstoneTunnel=红石 gui.appliedenergistics2.RedstoneTunnel=红石
gui.appliedenergistics2.EUTunnel=EU gui.appliedenergistics2.EUTunnel=EU
gui.appliedenergistics2.FETunnel=FE gui.appliedenergistics2.FETunnel=FE
gui.appliedenergistics2.GTEUTunnel=GTEU
gui.appliedenergistics2.LightTunnel=光 gui.appliedenergistics2.LightTunnel=光
gui.appliedenergistics2.OCTunnel=开放式电脑 gui.appliedenergistics2.OCTunnel=开放式电脑
gui.appliedenergistics2.PressureTunnel=气压 gui.appliedenergistics2.PressureTunnel=气压
@@ -133,6 +134,7 @@ gui.appliedenergistics2.SecurityCardEditor=身份卡编辑
gui.appliedenergistics2.Encoded=已编码 gui.appliedenergistics2.Encoded=已编码
gui.appliedenergistics2.Priority=优先级 gui.appliedenergistics2.Priority=优先级
gui.appliedenergistics2.StorageBus=存储总线 gui.appliedenergistics2.StorageBus=存储总线
gui.appliedenergistics2.OreDictStorageBus=矿典存储总线
gui.appliedenergistics2.StorageBusFluids=流体储存总线 gui.appliedenergistics2.StorageBusFluids=流体储存总线
gui.appliedenergistics2.EnergyDrain=被动流失 gui.appliedenergistics2.EnergyDrain=被动流失
gui.appliedenergistics2.Installed=已安装 gui.appliedenergistics2.Installed=已安装
@@ -349,11 +351,32 @@ gui.tooltips.appliedenergistics2.FilterModeClear=在每次打开时清空.
gui.tooltips.appliedenergistics2.ItemsStored=存储物品: %s gui.tooltips.appliedenergistics2.ItemsStored=存储物品: %s
gui.tooltips.appliedenergistics2.ItemsRequestable=可请求: %s gui.tooltips.appliedenergistics2.ItemsRequestable=可请求: %s
gui.tooltips.appliedenergistics2.P2PFrequency=频率: %s gui.tooltips.appliedenergistics2.P2PFrequency=频率: %s
gui.tooltips.appliedenergistics2.MultiplyByTwo=物品数量×2
gui.tooltips.appliedenergistics2.MultiplyByTwoDesc=将尝试将格内物品数量×2
gui.tooltips.appliedenergistics2.MultiplyByThree=物品数量×3
gui.tooltips.appliedenergistics2.MultiplyByThreeDesc=将尝试将格内物品数量×3
gui.tooltips.appliedenergistics2.IncreaseByOne=物品数量+1
gui.tooltips.appliedenergistics2.IncreaseByOneDesc=将尝试将格内物品数量+1 注:将不会维持比例
gui.tooltips.appliedenergistics2.DivideByTwo=物品数量÷2
gui.tooltips.appliedenergistics2.DivideByTwoDesc=将尝试将格内物品数量÷2
gui.tooltips.appliedenergistics2.DivideByThree=物品数量÷3
gui.tooltips.appliedenergistics2.DivideByThreeDesc=将尝试将格内物品数量÷3
gui.tooltips.appliedenergistics2.DecreaseByOne=物品数量-1
gui.tooltips.appliedenergistics2.DecreaseByOneDesc=将尝试将格内物品数量-1 注:将不会维持比例
gui.tooltips.appliedenergistics2.MaxCount=物品数量最大
gui.tooltips.appliedenergistics2.MaxCountDesc=将把格内物品数量最大化并维持比例
gui.tooltips.appliedenergistics2.FreeMolecularSlotShortcut=显示有样板位的合成接口
gui.tooltips.appliedenergistics2.FreeMolecularSlotShortcutDesc=快捷切换有样板位的分子装配室接口
gui.tooltips.appliedenergistics2.ToggleShowFullInterfaces=显示满样板的接口
gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOnDesc=显示所有接口
gui.tooltips.appliedenergistics2.ToggleShowFullInterfacesOffDesc=仅显示有样板位的接口
gui.tooltips.appliedenergistics2.HighlightInterface=高亮接口
// Units (单位) // Units (单位)
gui.appliedenergistics2.units.appliedenergstics=AE gui.appliedenergistics2.units.appliedenergstics=AE
gui.appliedenergistics2.units.ic2=EU gui.appliedenergistics2.units.ic2=EU
gui.appliedenergistics2.units.rf=RF gui.appliedenergistics2.units.rf=RF
gui.appliedenergistics2.units.gteu=GTEU
// Colors (颜色) // Colors (颜色)
gui.appliedenergistics2.White=白色 gui.appliedenergistics2.White=白色
@@ -387,6 +410,8 @@ waila.appliedenergistics2.Channels=%1$d / %2$d 频道
waila.appliedenergistics2.P2PUnlinked=未连接 waila.appliedenergistics2.P2PUnlinked=未连接
waila.appliedenergistics2.P2PInputOneOutput=已连接(输入端) waila.appliedenergistics2.P2PInputOneOutput=已连接(输入端)
waila.appliedenergistics2.P2PInputManyOutputs=已连接(输入端)- %d 输出 waila.appliedenergistics2.P2PInputManyOutputs=已连接(输入端)- %d 输出
waila.appliedenergistics2.p2p_output_one_input=已连接(输出端)
waila.appliedenergistics2.p2p_output_many_inputs=已连接(输出端)- %d 输入
waila.appliedenergistics2.P2POutput=已连接(输出端) waila.appliedenergistics2.P2POutput=已连接(输出端)
// TheOneProbe // TheOneProbe
@@ -402,6 +427,8 @@ theoneprobe.appliedenergistics2.channels=%1$d / %2$d 频道
theoneprobe.appliedenergistics2.p2p_unlinked=未连接 theoneprobe.appliedenergistics2.p2p_unlinked=未连接
theoneprobe.appliedenergistics2.p2p_input_one_output=已连接(输入端) theoneprobe.appliedenergistics2.p2p_input_one_output=已连接(输入端)
theoneprobe.appliedenergistics2.p2p_input_many_outputs=已连接(输入端)- %d 输出 theoneprobe.appliedenergistics2.p2p_input_many_outputs=已连接(输入端)- %d 输出
theoneprobe.appliedenergistics2.p2p_output_one_input=已连接(输出端)
theoneprobe.appliedenergistics2.p2p_output_many_inputs=已连接(输出端)- %d 输入
theoneprobe.appliedenergistics2.p2p_output=已连接(输出端) theoneprobe.appliedenergistics2.p2p_output=已连接(输出端)
theoneprobe.appliedenergistics2.p2p_frequency=频率: %1$s theoneprobe.appliedenergistics2.p2p_frequency=频率: %1$s
theoneprobe.appliedenergistics2.stored_energy=%1$d / %2$d theoneprobe.appliedenergistics2.stored_energy=%1$d / %2$d
@@ -430,6 +457,7 @@ item.appliedenergistics2.material.basic_card.name=基础卡
item.appliedenergistics2.material.blank_pattern.name=空白样板 item.appliedenergistics2.material.blank_pattern.name=空白样板
item.appliedenergistics2.material.calculation_processor.name=运算处理器 item.appliedenergistics2.material.calculation_processor.name=运算处理器
item.appliedenergistics2.material.card_capacity.name=容量卡 item.appliedenergistics2.material.card_capacity.name=容量卡
item.appliedenergistics2.material.card_pattern_expansion.name=样板扩展卡
item.appliedenergistics2.material.card_fuzzy.name=模糊卡 item.appliedenergistics2.material.card_fuzzy.name=模糊卡
item.appliedenergistics2.material.card_inverter.name=反相卡 item.appliedenergistics2.material.card_inverter.name=反相卡
item.appliedenergistics2.material.card_redstone.name=红石卡 item.appliedenergistics2.material.card_redstone.name=红石卡
@@ -510,8 +538,10 @@ item.appliedenergistics2.multi_part.level_emitter.name=ME标准发信器
item.appliedenergistics2.multi_part.fluid_level_emitter.name=ME流体标准发信器 item.appliedenergistics2.multi_part.fluid_level_emitter.name=ME流体标准发信器
item.appliedenergistics2.multi_part.p2p_tunnel.name=P2P通道 item.appliedenergistics2.multi_part.p2p_tunnel.name=P2P通道
item.appliedenergistics2.multi_part.pattern_terminal.name=ME样板终端 item.appliedenergistics2.multi_part.pattern_terminal.name=ME样板终端
item.appliedenergistics2.multi_part.expanded_processing_pattern_terminal.name=ME增广处理样板终端
item.appliedenergistics2.multi_part.quartz_fiber.name=石英纤维 item.appliedenergistics2.multi_part.quartz_fiber.name=石英纤维
item.appliedenergistics2.multi_part.storage_bus.name=ME存储总线 item.appliedenergistics2.multi_part.storage_bus.name=ME存储总线
item.appliedenergistics2.multi_part.oredict_storage_bus.name=ME矿典存储总线
item.appliedenergistics2.multi_part.fluid_storage_bus.name=ME流体储存总线 item.appliedenergistics2.multi_part.fluid_storage_bus.name=ME流体储存总线
item.appliedenergistics2.multi_part.terminal.name=ME终端 item.appliedenergistics2.multi_part.terminal.name=ME终端
item.appliedenergistics2.multi_part.inverted_toggle_bus.name=ME反相触发总线 item.appliedenergistics2.multi_part.inverted_toggle_bus.name=ME反相触发总线
@@ -618,7 +648,7 @@ achievement.ae2.QNB=量子隧道
achievement.ae2.QNB.desc=制作一个链接室 achievement.ae2.QNB.desc=制作一个链接室
// Stats (统计) // Stats (统计)
stat.ae2.ItemsInserted=物品已入ME存储 stat.ae2.ItemsInserted=物品已入ME存储
stat.ae2.ItemsExtracted=物品已取出ME存储 stat.ae2.ItemsExtracted=物品已取出ME存储
stat.ae2.TurnedCranks=转动曲柄 stat.ae2.TurnedCranks=转动曲柄
@@ -0,0 +1,9 @@
{
"parent": "appliedenergistics2:item/part/display",
"textures": {
"front": "appliedenergistics2:items/part/interface_terminal",
"front_bright": "appliedenergistics2:parts/interface_configuration_terminal_bright",
"front_medium": "appliedenergistics2:parts/interface_configuration_terminal_medium",
"front_dark": "appliedenergistics2:parts/interface_configuration_terminal_dark"
}
}
@@ -0,0 +1,6 @@
{
"parent": "appliedenergistics2:item/part/p2p_tunnel",
"textures": {
"type": "appliedenergistics2:parts/p2p/power_gteu"
}
}
@@ -0,0 +1,8 @@
{
"parent": "appliedenergistics2:part/display_off",
"textures": {
"lightsBright": "appliedenergistics2:parts/interface_configuration_terminal_bright",
"lightsMedium": "appliedenergistics2:parts/interface_configuration_terminal_medium",
"lightsDark": "appliedenergistics2:parts/interface_configuration_terminal_dark"
}
}
@@ -0,0 +1,76 @@
{
"ae2_uvl_marker": true,
"textures": {
"lightsBright": "appliedenergistics2:parts/interface_configuration_terminal_bright",
"lightsMedium": "appliedenergistics2:parts/interface_configuration_terminal_medium",
"lightsDark": "appliedenergistics2:parts/interface_configuration_terminal_dark"
},
"elements": [
{
"from": [
2,
2,
0
],
"to": [
14,
14,
2
],
"faces": {
"north": {
"texture": "#lightsBright",
"tintindex": 3,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
}
}
},
{
"from": [
2,
2,
0
],
"to": [
14,
14,
2
],
"faces": {
"north": {
"texture": "#lightsMedium",
"tintindex": 2,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
}
}
},
{
"from": [
2,
2,
0
],
"to": [
14,
14,
2
],
"faces": {
"north": {
"texture": "#lightsDark",
"tintindex": 1,
"uvlightmap": {
"sky": 0.007,
"block": 0.007
}
}
}
}
]
}
@@ -0,0 +1,6 @@
{
"parent": "appliedenergistics2:part/p2p/p2p_tunnel_base",
"textures": {
"type": "appliedenergistics2:parts/p2p/power_gteu"
}
}
@@ -0,0 +1,36 @@
{
"conditions": [
{
"type": "forge:and",
"values": [
{
"type": "appliedenergistics2:part_exists",
"part": "part.storage_bus"
},
{
"type": "minecraft:item_exists",
"item": "appliedenergistics2:interface"
}
]
}
],
"result": {
"type": "appliedenergistics2:part",
"part": "part.oredict_storage_bus"
},
"type": "appliedenergistics2:part_shapeless",
"ingredients": [
{
"item": "minecraft:sticky_piston"
},
{
"item": "#appliedenergistics2:interface"
},
{
"item": "minecraft:piston"
},
{
"item": "minecraft:book"
}
]
}

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