Applied-Energistics-2-tiler.../src/main/java/appeng/util/Platform.java

2206 lines
55 KiB
Java
Raw Normal View History

2014-11-14 12:02:52 +01:00
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
2014-11-14 12:02:52 +01:00
*
* 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.util;
import java.lang.reflect.Field;
2014-08-07 08:47:42 +02:00
import java.lang.reflect.Method;
import java.security.InvalidParameterException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
2014-02-09 02:34:52 +01:00
import java.util.Set;
import java.util.WeakHashMap;
2015-06-16 02:44:59 +02:00
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
2015-06-16 02:44:59 +02:00
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
2014-01-20 17:41:37 +01:00
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
2014-02-09 02:34:52 +01:00
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.IInventory;
2013-12-28 22:05:58 +01:00
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.inventory.InventoryLargeChest;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
2014-08-07 08:47:42 +02:00
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S21PacketChunkData;
import net.minecraft.server.management.PlayerManager;
2014-09-14 07:02:02 +02:00
import net.minecraft.stats.Achievement;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
2014-01-20 17:41:37 +01:00
import net.minecraft.util.AxisAlignedBB;
2015-06-16 02:44:59 +02:00
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.MathHelper;
2014-01-20 17:41:37 +01:00
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.StatCollector;
import net.minecraft.util.Vec3;
2015-06-16 02:44:59 +02:00
import net.minecraft.world.ILockableContainer;
import net.minecraft.world.World;
2014-02-09 02:34:52 +01:00
import net.minecraft.world.WorldServer;
2014-08-07 08:47:42 +02:00
import net.minecraft.world.chunk.Chunk;
2014-02-09 02:34:52 +01:00
import net.minecraftforge.common.util.FakePlayerFactory;
2015-06-16 02:44:59 +02:00
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
import appeng.api.AEApi;
import appeng.api.config.AccessRestriction;
import appeng.api.config.Actionable;
import appeng.api.config.FuzzyMode;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.PowerUnits;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.SecurityPermissions;
import appeng.api.config.SortOrder;
import appeng.api.definitions.IItemDefinition;
import appeng.api.definitions.IMaterials;
import appeng.api.definitions.IParts;
2014-01-23 20:02:48 +01:00
import appeng.api.implementations.items.IAEItemPowerStorage;
import appeng.api.implementations.items.IAEWrench;
import appeng.api.implementations.tiles.ITileStorageMonitorable;
import appeng.api.networking.IGrid;
import appeng.api.networking.IGridNode;
import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.energy.IEnergySource;
2014-01-05 09:43:49 +01:00
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.security.IActionHost;
import appeng.api.networking.security.ISecurityGrid;
import appeng.api.networking.security.MachineSource;
import appeng.api.networking.security.PlayerSource;
import appeng.api.networking.storage.IStorageGrid;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.IMEMonitorHandlerReceiver;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IAEStack;
import appeng.api.storage.data.IAETagCompound;
import appeng.api.storage.data.IItemList;
import appeng.api.util.AEColor;
2015-06-16 02:44:59 +02:00
import appeng.api.util.AEPartLocation;
import appeng.api.util.DimensionalCoord;
import appeng.core.AEConfig;
2014-02-09 02:34:52 +01:00
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.features.AEFeature;
import appeng.core.stats.Stats;
import appeng.core.sync.GuiBridge;
2014-08-09 21:09:49 +02:00
import appeng.core.sync.GuiHostType;
import appeng.hooks.TickHandler;
import appeng.integration.IntegrationRegistry;
2014-07-24 00:26:23 +02:00
import appeng.integration.IntegrationType;
import appeng.me.GridAccessException;
import appeng.me.GridNode;
import appeng.me.helpers.AENetworkProxy;
import appeng.util.item.AEItemStack;
import appeng.util.item.AESharedNBT;
import appeng.util.item.OreHelper;
import appeng.util.item.OreReference;
import appeng.util.prioitylist.IPartitionList;
/**
* @author AlgorithmX2
* @author thatsIch
* @version rv2
* @since rv0
*/
public class Platform
{
public static final Block AIR_BLOCK = Blocks.air;
2014-02-09 02:34:52 +01:00
public static final int DEF_OFFSET = 16;
/*
* random source, use it for item drop locations...
*/
private static final Random RANDOM_GENERATOR = new Random();
private static final WeakHashMap<World, EntityPlayer> FAKE_PLAYERS = new WeakHashMap<World, EntityPlayer>();
private static Field tagList;
private static Class playerInstance;
private static Method getOrCreateChunkWatcher;
private static Method sendToAllPlayersWatchingChunk;
2014-02-14 06:32:35 +01:00
public static Random getRandom()
{
2015-01-01 22:13:10 +01:00
return RANDOM_GENERATOR;
2014-02-14 06:32:35 +01:00
}
public static float getRandomFloat()
{
2015-01-01 22:13:10 +01:00
return RANDOM_GENERATOR.nextFloat();
}
/**
* This displays the value for encoded longs ( double *100 )
2015-02-03 12:04:13 +01:00
*
* @param n to be formatted long value
2014-09-27 23:17:47 +02:00
* @param isRate if true it adds a /t to the formatted string
*
2014-09-27 23:17:47 +02:00
* @return formatted long value
*/
2015-09-30 14:24:40 +02:00
public static String formatPowerLong( final long n, final boolean isRate )
{
double p = ( (double) n ) / 100;
2015-09-30 14:24:40 +02:00
final PowerUnits displayUnits = AEConfig.instance.selectedPowerUnit();
p = PowerUnits.AE.convertTo( displayUnits, p );
2015-09-30 14:24:40 +02:00
final String[] preFixes = { "k", "M", "G", "T", "P", "T", "P", "E", "Z", "Y" };
String unitName = displayUnits.name();
if( displayUnits == PowerUnits.WA )
2015-04-29 02:30:53 +02:00
{
unitName = "J";
2015-04-29 02:30:53 +02:00
}
if( displayUnits == PowerUnits.MK )
2015-04-29 02:30:53 +02:00
{
unitName = "J";
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:22:21 +02:00
String level = "";
int offset = 0;
while( p > 1000 && offset < preFixes.length )
{
p /= 1000;
level = preFixes[offset];
offset++;
}
2015-09-30 14:24:40 +02:00
final DecimalFormat df = new DecimalFormat( "#.##" );
return df.format( p ) + ' ' + level + unitName + ( isRate ? "/t" : "" );
}
2015-09-30 14:24:40 +02:00
public static AEPartLocation crossProduct( final AEPartLocation forward, final AEPartLocation up )
2015-06-16 02:44:59 +02:00
{
2015-09-30 14:24:40 +02:00
final int west_x = forward.yOffset * up.zOffset - forward.zOffset * up.yOffset;
final int west_y = forward.zOffset * up.xOffset - forward.xOffset * up.zOffset;
final int west_z = forward.xOffset * up.yOffset - forward.yOffset * up.xOffset;
2015-06-16 02:44:59 +02:00
switch( west_x + west_y * 2 + west_z * 3 )
{
case 1:
return AEPartLocation.EAST;
case -1:
return AEPartLocation.WEST;
case 2:
return AEPartLocation.UP;
case -2:
return AEPartLocation.DOWN;
case 3:
return AEPartLocation.SOUTH;
case -3:
return AEPartLocation.NORTH;
}
return AEPartLocation.INTERNAL;
}
2015-09-30 14:24:40 +02:00
public static EnumFacing crossProduct( final EnumFacing forward, final EnumFacing up )
{
2015-09-30 14:24:40 +02:00
final int west_x = forward.getFrontOffsetY() * up.getFrontOffsetZ() - forward.getFrontOffsetZ() * up.getFrontOffsetY();
final int west_y = forward.getFrontOffsetZ() * up.getFrontOffsetX() - forward.getFrontOffsetX() * up.getFrontOffsetZ();
final int west_z = forward.getFrontOffsetX() * up.getFrontOffsetY() - forward.getFrontOffsetY() * up.getFrontOffsetX();
switch( west_x + west_y * 2 + west_z * 3 )
{
case 1:
2015-06-16 02:44:59 +02:00
return EnumFacing.EAST;
case -1:
2015-06-16 02:44:59 +02:00
return EnumFacing.WEST;
case 2:
2015-06-16 02:44:59 +02:00
return EnumFacing.UP;
case -2:
2015-06-16 02:44:59 +02:00
return EnumFacing.DOWN;
case 3:
2015-06-16 02:44:59 +02:00
return EnumFacing.SOUTH;
case -3:
2015-06-16 02:44:59 +02:00
return EnumFacing.NORTH;
}
2015-06-16 02:44:59 +02:00
//something is better then nothing?
return EnumFacing.NORTH;
}
2015-09-30 14:24:40 +02:00
public static <T extends Enum> T rotateEnum( T ce, final boolean backwards, final EnumSet validOptions )
{
do
{
if( backwards )
2015-04-29 02:30:53 +02:00
{
ce = prevEnum( ce );
2015-04-29 02:30:53 +02:00
}
else
2015-04-29 02:30:53 +02:00
{
ce = nextEnum( ce );
2015-04-29 02:30:53 +02:00
}
}
while( !validOptions.contains( ce ) || isNotValidSetting( ce ) );
return ce;
}
/*
* Simple way to cycle an enum...
*/
private static <T extends Enum> T prevEnum( final T ce )
{
2015-09-30 14:24:40 +02:00
final EnumSet valList = EnumSet.allOf( ce.getClass() );
int pLoc = ce.ordinal() - 1;
if( pLoc < 0 )
2015-04-29 02:30:53 +02:00
{
pLoc = valList.size() - 1;
2015-04-29 02:30:53 +02:00
}
if( pLoc < 0 || pLoc >= valList.size() )
2015-04-29 02:30:53 +02:00
{
pLoc = 0;
2015-04-29 02:30:53 +02:00
}
int pos = 0;
2015-09-30 14:24:40 +02:00
for( final Object g : valList )
{
if( pos == pLoc )
2015-04-29 02:30:53 +02:00
{
return (T) g;
2015-04-29 02:30:53 +02:00
}
2015-03-26 11:07:26 +01:00
pos++;
}
return null;
}
/*
* Simple way to cycle an enum...
*/
2015-09-30 14:24:40 +02:00
public static <T extends Enum> T nextEnum( final T ce )
{
2015-09-30 14:24:40 +02:00
final EnumSet valList = EnumSet.allOf( ce.getClass() );
int pLoc = ce.ordinal() + 1;
if( pLoc >= valList.size() )
2015-04-29 02:30:53 +02:00
{
pLoc = 0;
2015-04-29 02:30:53 +02:00
}
if( pLoc < 0 || pLoc >= valList.size() )
2015-04-29 02:30:53 +02:00
{
pLoc = 0;
2015-04-29 02:30:53 +02:00
}
int pos = 0;
2015-09-30 14:24:40 +02:00
for( final Object g : valList )
{
if( pos == pLoc )
2015-04-29 02:30:53 +02:00
{
return (T) g;
2015-04-29 02:30:53 +02:00
}
2015-03-26 11:07:26 +01:00
pos++;
}
return null;
}
2015-09-30 14:24:40 +02:00
private static boolean isNotValidSetting( final Enum e )
{
if( e == SortOrder.INVTWEAKS && !IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.InvTweaks ) )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
if( e == SearchBoxMode.NEI_AUTOSEARCH && !IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.NEI ) )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
if( e == SearchBoxMode.NEI_MANUAL_SEARCH && !IntegrationRegistry.INSTANCE.isEnabled( IntegrationType.NEI ) )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
return false;
}
2015-09-30 14:24:40 +02:00
public static void openGUI( @Nonnull final EntityPlayer p, @Nullable final TileEntity tile, @Nullable final AEPartLocation side, @Nonnull final GuiBridge type )
{
if( isClient() )
2015-04-29 02:30:53 +02:00
{
return;
2015-04-29 02:30:53 +02:00
}
2015-03-26 12:13:34 +01:00
int x = (int) p.posX;
int y = (int) p.posY;
int z = (int) p.posZ;
if( tile != null )
2014-02-01 06:37:27 +01:00
{
2015-06-16 02:44:59 +02:00
x = tile.getPos().getX();
y = tile.getPos().getY();
z = tile.getPos().getZ();
2014-02-01 06:37:27 +01:00
}
2015-06-16 02:44:59 +02:00
if( ( type.getType().isItem() && tile == null ) || type.hasPermissions( tile, x,y,z, side, p ) )
2014-01-20 17:41:37 +01:00
{
if( tile == null && type.getType() == GuiHostType.ITEM )
2015-04-29 02:30:53 +02:00
{
p.openGui( AppEng.instance(), type.ordinal() << 4, p.getEntityWorld(), p.inventory.currentItem, 0, 0 );
2015-04-29 02:30:53 +02:00
}
else if( tile == null || type.getType() == GuiHostType.ITEM )
2015-04-29 02:30:53 +02:00
{
p.openGui( AppEng.instance(), type.ordinal() << 4 | ( 1 << 3 ), p.getEntityWorld(), x, y, z );
2015-04-29 02:30:53 +02:00
}
else
2015-04-29 02:30:53 +02:00
{
2015-06-16 02:44:59 +02:00
p.openGui( AppEng.instance(), type.ordinal() << 4 | ( side.ordinal() ), tile.getWorld(), x, y, z );
2015-04-29 02:30:53 +02:00
}
2014-01-20 17:41:37 +01:00
}
}
/*
* returns true if the code is on the client.
*/
public static boolean isClient()
{
return FMLCommonHandler.instance().getEffectiveSide().isClient();
}
2015-09-30 14:24:40 +02:00
public static boolean hasPermissions( final DimensionalCoord dc, final EntityPlayer player )
2014-02-01 06:37:27 +01:00
{
2015-06-16 02:44:59 +02:00
return dc.getWorld().canMineBlockBody( player, dc.getPos() );
2014-02-01 06:37:27 +01:00
}
/*
* Checks to see if a block is air?
*/
2015-09-30 14:24:40 +02:00
public static boolean isBlockAir( final World w, final BlockPos pos )
{
try
{
2015-06-16 02:44:59 +02:00
return w.getBlockState( pos ).getBlock().isAir( w, pos );
}
2015-09-30 14:24:40 +02:00
catch( final Throwable e )
{
return false;
}
}
/*
2014-09-21 02:31:13 +02:00
* Lots of silliness to try and account for weird tag related junk, basically requires that two tags have at least
2014-02-09 02:34:52 +01:00
* something in their tags before it wasts its time comparing them.
*/
private static boolean sameStackStags( final ItemStack a, final ItemStack b )
{
if( a == null && b == null )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
if( a == null || b == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
if( a == b )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final NBTTagCompound ta = a.getTagCompound();
final NBTTagCompound tb = b.getTagCompound();
if( ta == tb )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
if( ( ta == null && tb == null ) || ( ta != null && ta.hasNoTags() && tb == null ) || ( tb != null && tb.hasNoTags() && ta == null ) || ( ta != null && ta.hasNoTags() && tb != null && tb.hasNoTags() ) )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
if( ( ta == null && tb != null ) || ( ta != null && tb == null ) )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
// if both tags are shared this is easy...
if( AESharedNBT.isShared( ta ) && AESharedNBT.isShared( tb ) )
{
return ta == tb;
}
return NBTEqualityTest( ta, tb );
}
/*
2014-02-09 02:34:52 +01:00
* recursive test for NBT Equality, this was faster then trying to compare / generate hashes, its also more reliable
* then the vanilla version which likes to fail when NBT Compound data changes order, it is pretty expensive
* performance wise, so try an use shared tag compounds as long as the system remains in AE.
*/
2015-09-30 14:24:40 +02:00
public static boolean NBTEqualityTest( final NBTBase left, final NBTBase right )
{
// same type?
2015-09-30 14:24:40 +02:00
final byte id = left.getId();
if( id == right.getId() )
{
switch( id )
2014-09-14 07:02:02 +02:00
{
case 10:
{
2015-09-30 14:24:40 +02:00
final NBTTagCompound ctA = (NBTTagCompound) left;
final NBTTagCompound ctB = (NBTTagCompound) right;
2015-09-30 14:24:40 +02:00
final Set<String> cA = ctA.getKeySet();
final Set<String> cB = ctB.getKeySet();
if( cA.size() != cB.size() )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
for( final String name : cA )
{
2015-09-30 14:24:40 +02:00
final NBTBase tag = ctA.getTag( name );
final NBTBase aTag = ctB.getTag( name );
if( aTag == null )
{
return false;
}
if( !NBTEqualityTest( tag, aTag ) )
{
return false;
}
}
return true;
}
2014-02-15 08:05:28 +01:00
case 9: // ) // A instanceof NBTTagList )
{
2015-09-30 14:24:40 +02:00
final NBTTagList lA = (NBTTagList) left;
final NBTTagList lB = (NBTTagList) right;
if( lA.tagCount() != lB.tagCount() )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final List<NBTBase> tag = tagList( lA );
final List<NBTBase> aTag = tagList( lB );
if( tag.size() != aTag.size() )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
for( int x = 0; x < tag.size(); x++ )
{
if( aTag.get( x ) == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
if( !NBTEqualityTest( tag.get( x ), aTag.get( x ) ) )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
}
return true;
}
case 1: // ( A instanceof NBTTagByte )
2015-06-16 02:44:59 +02:00
return ( (NBTBase.NBTPrimitive) left ).getByte() == ( (NBTBase.NBTPrimitive) right ).getByte();
case 4: // else if ( A instanceof NBTTagLong )
2015-06-16 02:44:59 +02:00
return ( (NBTBase.NBTPrimitive) left ).getLong() == ( (NBTBase.NBTPrimitive) right ).getLong();
case 8: // else if ( A instanceof NBTTagString )
2015-06-16 02:44:59 +02:00
return ( (NBTTagString) left ).getString().equals( ( (NBTTagString) right ).getString() ) || ( (NBTTagString) left ).getString().equals( ( (NBTTagString) right ).getString() );
case 6: // else if ( A instanceof NBTTagDouble )
2015-06-16 02:44:59 +02:00
return ( (NBTBase.NBTPrimitive) left ).getDouble() == ( (NBTBase.NBTPrimitive) right ).getDouble();
case 5: // else if ( A instanceof NBTTagFloat )
2015-06-16 02:44:59 +02:00
return ( (NBTBase.NBTPrimitive) left ).getFloat() == ( (NBTBase.NBTPrimitive) right ).getFloat();
case 3: // else if ( A instanceof NBTTagInt )
2015-06-16 02:44:59 +02:00
return ( (NBTBase.NBTPrimitive) left ).getInt() == ( (NBTBase.NBTPrimitive) right ).getInt();
default:
return left.equals( right );
}
}
return false;
}
2015-09-30 14:24:40 +02:00
private static List<NBTBase> tagList( final NBTTagList lB )
2014-02-09 02:34:52 +01:00
{
if( tagList == null )
2014-02-09 02:34:52 +01:00
{
try
{
tagList = lB.getClass().getDeclaredField( "tagList" );
}
2015-09-30 14:24:40 +02:00
catch( final Throwable t )
2014-02-09 02:34:52 +01:00
{
2014-02-15 08:05:28 +01:00
try
{
tagList = lB.getClass().getDeclaredField( "field_74747_a" );
}
2015-09-30 14:24:40 +02:00
catch( final Throwable z )
2014-02-15 08:05:28 +01:00
{
AELog.error( t );
AELog.error( z );
}
2014-02-09 02:34:52 +01:00
}
}
try
{
tagList.setAccessible( true );
return (List<NBTBase>) tagList.get( lB );
}
2015-09-30 14:24:40 +02:00
catch( final Throwable t )
2014-02-09 02:34:52 +01:00
{
AELog.error( t );
}
2014-09-28 22:20:14 +02:00
return new ArrayList<NBTBase>();
2014-02-09 02:34:52 +01:00
}
/*
2014-09-21 03:02:40 +02:00
* Orderless hash on NBT Data, used to work thought huge piles fast, but ignores the order just in case MC decided
2014-02-09 02:34:52 +01:00
* to change it... WHICH IS BAD...
*/
2015-09-30 14:24:40 +02:00
public static int NBTOrderlessHash( final NBTBase nbt )
{
// same type?
int hash = 0;
2015-09-30 14:24:40 +02:00
final byte id = nbt.getId();
hash += id;
switch( id )
2014-09-14 07:02:02 +02:00
{
case 10:
{
2015-09-30 14:24:40 +02:00
final NBTTagCompound ctA = (NBTTagCompound) nbt;
2015-09-30 14:24:40 +02:00
final Set<String> cA = ctA.getKeySet();
2015-09-30 14:24:40 +02:00
for( final String name : cA )
{
hash += name.hashCode() ^ NBTOrderlessHash( ctA.getTag( name ) );
}
return hash;
}
case 9: // ) // A instanceof NBTTagList )
{
2015-09-30 14:24:40 +02:00
final NBTTagList lA = (NBTTagList) nbt;
hash += 9 * lA.tagCount();
2015-09-30 14:24:40 +02:00
final List<NBTBase> l = tagList( lA );
for( int x = 0; x < l.size(); x++ )
{
hash += ( (Integer) x ).hashCode() ^ NBTOrderlessHash( l.get( x ) );
}
return hash;
}
case 1: // ( A instanceof NBTTagByte )
2015-06-16 02:44:59 +02:00
return hash + ( (NBTBase.NBTPrimitive) nbt ).getByte();
case 4: // else if ( A instanceof NBTTagLong )
2015-06-16 02:44:59 +02:00
return hash + (int) ( (NBTBase.NBTPrimitive) nbt ).getLong();
case 8: // else if ( A instanceof NBTTagString )
2015-06-16 02:44:59 +02:00
return hash + ( (NBTTagString) nbt ).getString().hashCode();
case 6: // else if ( A instanceof NBTTagDouble )
2015-06-16 02:44:59 +02:00
return hash + (int) ( (NBTBase.NBTPrimitive) nbt ).getDouble();
case 5: // else if ( A instanceof NBTTagFloat )
2015-06-16 02:44:59 +02:00
return hash + (int) ( (NBTBase.NBTPrimitive) nbt ).getFloat();
case 3: // else if ( A instanceof NBTTagInt )
2015-06-16 02:44:59 +02:00
return hash + ( (NBTBase.NBTPrimitive) nbt ).getInt();
default:
return hash;
}
}
/*
2014-02-09 02:34:52 +01:00
* The usual version of this returns an ItemStack, this version returns the recipe.
*/
2015-09-30 14:24:40 +02:00
public static IRecipe findMatchingRecipe( final InventoryCrafting inventoryCrafting, final World par2World )
{
2015-09-30 14:24:40 +02:00
final CraftingManager cm = CraftingManager.getInstance();
final List<IRecipe> rl = cm.getRecipeList();
2015-09-30 14:24:40 +02:00
for( final IRecipe r : rl )
{
if( r.matches( inventoryCrafting, par2World ) )
{
return r;
}
}
return null;
}
2015-09-30 14:24:40 +02:00
public static ItemStack[] getBlockDrops( final World w, final BlockPos pos )
{
List<ItemStack> out = new ArrayList<ItemStack>();
2015-09-30 14:24:40 +02:00
final IBlockState state = w.getBlockState( pos );
2015-06-16 02:44:59 +02:00
if( state != null )
{
2015-06-16 02:44:59 +02:00
out = state.getBlock().getDrops( w, pos, state, 0 );
}
if( out == null )
2015-04-29 02:30:53 +02:00
{
return new ItemStack[0];
2015-04-29 02:30:53 +02:00
}
return out.toArray( new ItemStack[out.size()] );
}
2015-09-30 14:24:40 +02:00
public static AEPartLocation cycleOrientations( final AEPartLocation dir, final boolean upAndDown )
{
if( upAndDown )
{
switch( dir )
{
case NORTH:
2015-06-16 02:44:59 +02:00
return AEPartLocation.SOUTH;
case SOUTH:
2015-06-16 02:44:59 +02:00
return AEPartLocation.EAST;
case EAST:
2015-06-16 02:44:59 +02:00
return AEPartLocation.WEST;
case WEST:
2015-06-16 02:44:59 +02:00
return AEPartLocation.NORTH;
case UP:
2015-06-16 02:44:59 +02:00
return AEPartLocation.UP;
case DOWN:
2015-06-16 02:44:59 +02:00
return AEPartLocation.DOWN;
case INTERNAL:
return AEPartLocation.INTERNAL;
}
}
else
{
switch( dir )
{
case UP:
2015-06-16 02:44:59 +02:00
return AEPartLocation.DOWN;
case DOWN:
2015-06-16 02:44:59 +02:00
return AEPartLocation.NORTH;
case NORTH:
2015-06-16 02:44:59 +02:00
return AEPartLocation.SOUTH;
case SOUTH:
2015-06-16 02:44:59 +02:00
return AEPartLocation.EAST;
case EAST:
2015-06-16 02:44:59 +02:00
return AEPartLocation.WEST;
case WEST:
2015-06-16 02:44:59 +02:00
return AEPartLocation.UP;
case INTERNAL:
return AEPartLocation.INTERNAL;
}
}
2015-06-16 02:44:59 +02:00
return AEPartLocation.INTERNAL;
}
/*
2014-02-09 02:34:52 +01:00
* Creates / or loads previous NBT Data on items, used for editing items owned by AE.
*/
2015-09-30 14:24:40 +02:00
public static NBTTagCompound openNbtData( final ItemStack i )
{
NBTTagCompound compound = i.getTagCompound();
if( compound == null )
{
i.setTagCompound( compound = new NBTTagCompound() );
}
return compound;
}
/*
2014-09-21 01:46:46 +02:00
* Generates Item entities in the world similar to how items are generally dropped.
*/
2015-09-30 14:24:40 +02:00
public static void spawnDrops( final World w, final BlockPos pos, final List<ItemStack> drops )
{
if( isServer() )
{
2015-09-30 14:24:40 +02:00
for( final ItemStack i : drops )
{
if( i != null )
{
if( i.stackSize > 0 )
{
2015-09-30 14:24:40 +02:00
final double offset_x = ( getRandomInt() % 32 - 16 ) / 82;
final double offset_y = ( 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.copy() );
w.spawnEntityInWorld( ei );
}
}
}
}
}
/*
* returns true if the code is on the server.
*/
public static boolean isServer()
{
return FMLCommonHandler.instance().getEffectiveSide().isServer();
}
public static int getRandomInt()
{
return Math.abs( RANDOM_GENERATOR.nextInt() );
}
/*
2014-02-09 02:34:52 +01:00
* Utility function to get the full inventory for a Double Chest in the World.
*/
2015-09-30 14:24:40 +02:00
public static IInventory GetChestInv( final Object te )
{
TileEntityChest teA = (TileEntityChest) te;
TileEntity teB = null;
2015-09-30 14:24:40 +02:00
final IBlockState myBlockID = teA.getWorld().getBlockState( teA.getPos() );
2015-09-30 14:24:40 +02:00
final BlockPos posX = teA.getPos().offset( EnumFacing.EAST );
final BlockPos negX = teA.getPos().offset( EnumFacing.WEST );
2015-06-16 02:44:59 +02:00
if( teA.getWorld().getBlockState( posX ) == myBlockID )
{
2015-06-16 02:44:59 +02:00
teB = teA.getWorld().getTileEntity( posX );
if( !( teB instanceof TileEntityChest ) )
2015-04-29 02:30:53 +02:00
{
teB = null;
2015-04-29 02:30:53 +02:00
}
}
if( teB == null )
{
2015-06-16 02:44:59 +02:00
if( teA.getWorld().getBlockState( negX ) == myBlockID )
{
2015-06-16 02:44:59 +02:00
teB = teA.getWorld().getTileEntity( negX );
if( !( teB instanceof TileEntityChest ) )
2015-04-29 02:30:53 +02:00
{
teB = null;
2015-04-29 02:30:53 +02:00
}
else
{
2015-09-30 14:24:40 +02:00
final TileEntityChest x = teA;
teA = (TileEntityChest) teB;
teB = x;
}
}
}
2015-09-30 14:24:40 +02:00
final BlockPos posY = teA.getPos().offset( EnumFacing.SOUTH );
final BlockPos negY = teA.getPos().offset( EnumFacing.NORTH );
2015-06-16 02:44:59 +02:00
if( teB == null )
{
2015-06-16 02:44:59 +02:00
if( teA.getWorld().getBlockState( posY ) == myBlockID )
{
2015-06-16 02:44:59 +02:00
teB = teA.getWorld().getTileEntity(posY);
if( !( teB instanceof TileEntityChest ) )
2015-04-29 02:30:53 +02:00
{
teB = null;
2015-04-29 02:30:53 +02:00
}
}
}
if( teB == null )
{
2015-06-16 02:44:59 +02:00
if( teA.getWorld().getBlockState( negY ) == myBlockID )
{
2015-06-16 02:44:59 +02:00
teB = teA.getWorld().getTileEntity( negY );
if( !( teB instanceof TileEntityChest ) )
2015-04-29 02:30:53 +02:00
{
teB = null;
2015-04-29 02:30:53 +02:00
}
else
{
2015-09-30 14:24:40 +02:00
final TileEntityChest x = teA;
teA = (TileEntityChest) teB;
teB = x;
}
}
}
if( teB == null )
2015-04-29 02:30:53 +02:00
{
return teA;
2015-04-29 02:30:53 +02:00
}
2015-06-16 02:44:59 +02:00
return new InventoryLargeChest( "", teA, (ILockableContainer) teB );
}
2015-09-30 14:24:40 +02:00
public static boolean isModLoaded( final String modid )
{
try
{
// if this fails for some reason, try the other method.
return Loader.isModLoaded( modid );
}
2015-09-30 14:24:40 +02:00
catch( final Throwable ignored )
{
}
2015-09-30 14:24:40 +02:00
for( final ModContainer f : Loader.instance().getActiveModList() )
{
if( f.getModId().equals( modid ) )
{
return true;
}
}
return false;
}
2015-09-30 14:24:40 +02:00
public static ItemStack findMatchingRecipeOutput( final InventoryCrafting ic, final World worldObj )
{
return CraftingManager.getInstance().findMatchingRecipe( ic, worldObj );
}
@SideOnly( Side.CLIENT )
2015-09-30 14:24:40 +02:00
public static List getTooltip( final Object o )
{
if( o == null )
2015-04-29 02:30:53 +02:00
{
return new ArrayList();
2015-04-29 02:30:53 +02:00
}
ItemStack itemStack = null;
if( o instanceof AEItemStack )
{
2015-09-30 14:24:40 +02:00
final AEItemStack ais = (AEItemStack) o;
return ais.getToolTip();
}
else if( o instanceof ItemStack )
2015-04-29 02:30:53 +02:00
{
itemStack = (ItemStack) o;
2015-04-29 02:30:53 +02:00
}
else
2015-04-29 02:30:53 +02:00
{
return new ArrayList();
2015-04-29 02:30:53 +02:00
}
try
{
return itemStack.getTooltip( Minecraft.getMinecraft().thePlayer, false );
}
2015-09-30 14:24:40 +02:00
catch( final Exception errB )
{
return new ArrayList();
}
}
2015-09-30 14:24:40 +02:00
public static String getModId( final IAEItemStack is )
2014-07-03 04:09:17 +02:00
{
if( is == null )
2015-04-29 02:30:53 +02:00
{
2014-07-03 04:09:17 +02:00
return "** Null";
2015-04-29 02:30:53 +02:00
}
2014-07-03 04:09:17 +02:00
2015-09-30 14:24:40 +02:00
final String n = ( (AEItemStack) is ).getModID();
2014-07-03 04:09:17 +02:00
return n == null ? "** Null" : n;
}
2015-09-30 14:24:40 +02:00
public static String getItemDisplayName( final Object o )
{
if( o == null )
2015-04-29 02:30:53 +02:00
{
return "** Null";
2015-04-29 02:30:53 +02:00
}
ItemStack itemStack = null;
if( o instanceof AEItemStack )
{
2015-09-30 14:24:40 +02:00
final String n = ( (AEItemStack) o ).getDisplayName();
return n == null ? "** Null" : n;
}
else if( o instanceof ItemStack )
2015-04-29 02:30:53 +02:00
{
itemStack = (ItemStack) o;
2015-04-29 02:30:53 +02:00
}
else
2015-04-29 02:30:53 +02:00
{
return "**Invalid Object";
2015-04-29 02:30:53 +02:00
}
try
{
String name = itemStack.getDisplayName();
if( name == null || name.isEmpty() )
2015-04-29 02:30:53 +02:00
{
name = itemStack.getItem().getUnlocalizedName( itemStack );
2015-04-29 02:30:53 +02:00
}
return name == null ? "** Null" : name;
}
2015-09-30 14:24:40 +02:00
catch( final Exception errA )
{
try
{
2015-09-30 14:24:40 +02:00
final String n = itemStack.getUnlocalizedName();
return n == null ? "** Null" : n;
}
2015-09-30 14:24:40 +02:00
catch( final Exception errB )
{
return "** Exception";
}
}
}
2015-09-30 14:24:40 +02:00
public static boolean hasSpecialComparison( final IAEItemStack willAdd )
{
if( willAdd == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final IAETagCompound tag = willAdd.getTagCompound();
if( tag != null && tag.getSpecialComparison() != null )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
return false;
}
2015-09-30 14:24:40 +02:00
public static boolean hasSpecialComparison( final ItemStack willAdd )
{
if( AESharedNBT.isShared( willAdd.getTagCompound() ) )
{
2015-05-09 00:00:52 +02:00
if( ( (IAETagCompound) willAdd.getTagCompound() ).getSpecialComparison() != null )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
}
return false;
}
2015-09-30 14:24:40 +02:00
public static boolean isWrench( final EntityPlayer player, final ItemStack eq, final BlockPos pos )
{
if( eq != null )
{
try
{
2015-06-16 02:44:59 +02:00
// TODO: Build Craft Wrench?
/*
if( eq.getItem() instanceof IToolWrench )
{
IToolWrench wrench = (IToolWrench) eq.getItem();
return wrench.canWrench( player, x, y, z );
}
2015-06-16 02:44:59 +02:00
*/
}
2015-09-30 14:24:40 +02:00
catch( final Throwable ignore )
{ // explodes without BC
2014-01-30 19:53:06 +01:00
}
if( eq.getItem() instanceof IAEWrench )
2014-01-30 19:53:06 +01:00
{
2015-09-30 14:24:40 +02:00
final IAEWrench wrench = (IAEWrench) eq.getItem();
2015-06-16 02:44:59 +02:00
return wrench.canWrench( eq, player, pos );
}
}
return false;
}
2015-09-30 14:24:40 +02:00
public static boolean isChargeable( final ItemStack i )
{
if( i == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final Item it = i.getItem();
if( it instanceof IAEItemPowerStorage )
{
return ( (IAEItemPowerStorage) it ).getPowerFlow( i ) != AccessRestriction.READ;
}
return false;
}
2015-09-30 14:24:40 +02:00
public static EntityPlayer getPlayer( final WorldServer w )
{
if( w == null )
2015-04-29 02:30:53 +02:00
{
throw new InvalidParameterException( "World is null." );
2015-04-29 02:30:53 +02:00
}
2014-07-04 08:19:45 +02:00
2015-09-30 14:24:40 +02:00
final EntityPlayer wrp = FAKE_PLAYERS.get( w );
if( wrp != null )
2015-04-29 02:30:53 +02:00
{
return wrp;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final EntityPlayer p = FakePlayerFactory.getMinecraft( w );
2015-01-01 22:13:10 +01:00
FAKE_PLAYERS.put( w, p );
return p;
}
2015-09-30 14:24:40 +02:00
public static int MC2MEColor( final int color )
{
switch( color )
{
case 4: // "blue"
return 0;
case 0: // "black"
return 1;
case 15: // "white"
return 2;
case 3: // "brown"
return 3;
case 1: // "red"
return 4;
case 11: // "yellow"
return 5;
case 2: // "green"
return 6;
case 5: // "purple"
case 6: // "cyan"
case 7: // "silver"
case 8: // "gray"
case 9: // "pink"
case 10: // "lime"
case 12: // "lightBlue"
case 13: // "magenta"
case 14: // "orange"
}
return -1;
}
2015-09-30 14:24:40 +02:00
public static int findEmpty( final Object[] l )
{
for( int x = 0; x < l.length; x++ )
{
if( l[x] == null )
2015-04-29 02:30:53 +02:00
{
return x;
2015-04-29 02:30:53 +02:00
}
}
return -1;
}
2015-09-30 14:24:40 +02:00
public static <T> T pickRandom( final Collection<T> outs )
{
2015-01-01 22:13:10 +01:00
int index = RANDOM_GENERATOR.nextInt( outs.size() );
2015-09-30 14:24:40 +02:00
final Iterator<T> i = outs.iterator();
while( i.hasNext() && index > 0 )
2015-03-26 11:07:26 +01:00
{
index--;
i.next();
2015-03-26 11:07:26 +01:00
}
index--;
if( i.hasNext() )
2015-04-29 02:30:53 +02:00
{
return i.next();
2015-04-29 02:30:53 +02:00
}
return null; // wtf?
}
2015-09-30 14:24:40 +02:00
public static AEPartLocation rotateAround( final AEPartLocation forward, final AEPartLocation axis )
{
2015-06-16 02:44:59 +02:00
if( axis == AEPartLocation.INTERNAL || forward == AEPartLocation.INTERNAL )
2015-04-29 02:30:53 +02:00
{
return forward;
2015-04-29 02:30:53 +02:00
}
switch( forward )
{
case DOWN:
switch( axis )
{
case DOWN:
return forward;
case UP:
return forward;
case NORTH:
2015-06-16 02:44:59 +02:00
return AEPartLocation.EAST;
case SOUTH:
return AEPartLocation.WEST;
case EAST:
return AEPartLocation.NORTH;
case WEST:
return AEPartLocation.SOUTH;
default:
break;
}
break;
case UP:
switch( axis )
{
case NORTH:
return AEPartLocation.WEST;
case SOUTH:
return AEPartLocation.EAST;
case EAST:
return AEPartLocation.SOUTH;
case WEST:
return AEPartLocation.NORTH;
default:
break;
}
break;
case NORTH:
switch( axis )
{
case UP:
return AEPartLocation.WEST;
case DOWN:
return AEPartLocation.EAST;
case EAST:
return AEPartLocation.UP;
case WEST:
return AEPartLocation.DOWN;
default:
break;
}
break;
case SOUTH:
switch( axis )
{
case UP:
return AEPartLocation.EAST;
case DOWN:
return AEPartLocation.WEST;
case EAST:
return AEPartLocation.DOWN;
case WEST:
return AEPartLocation.UP;
default:
break;
}
break;
case EAST:
switch( axis )
{
case UP:
return AEPartLocation.NORTH;
case DOWN:
return AEPartLocation.SOUTH;
case NORTH:
return AEPartLocation.UP;
case SOUTH:
return AEPartLocation.DOWN;
default:
break;
}
case WEST:
switch( axis )
{
case UP:
return AEPartLocation.SOUTH;
case DOWN:
return AEPartLocation.NORTH;
case NORTH:
return AEPartLocation.DOWN;
case SOUTH:
return AEPartLocation.UP;
default:
break;
}
default:
break;
}
return forward;
}
2015-09-30 14:24:40 +02:00
public static EnumFacing rotateAround( final EnumFacing forward, final EnumFacing axis )
2015-06-16 02:44:59 +02:00
{
switch( forward )
{
case DOWN:
switch( axis )
{
case DOWN:
return forward;
case UP:
return forward;
case NORTH:
return EnumFacing.EAST;
case SOUTH:
2015-06-16 02:44:59 +02:00
return EnumFacing.WEST;
case EAST:
2015-06-16 02:44:59 +02:00
return EnumFacing.NORTH;
case WEST:
2015-06-16 02:44:59 +02:00
return EnumFacing.SOUTH;
default:
break;
}
break;
case UP:
switch( axis )
{
case NORTH:
2015-06-16 02:44:59 +02:00
return EnumFacing.WEST;
case SOUTH:
2015-06-16 02:44:59 +02:00
return EnumFacing.EAST;
case EAST:
2015-06-16 02:44:59 +02:00
return EnumFacing.SOUTH;
case WEST:
2015-06-16 02:44:59 +02:00
return EnumFacing.NORTH;
default:
break;
}
break;
case NORTH:
switch( axis )
{
case UP:
2015-06-16 02:44:59 +02:00
return EnumFacing.WEST;
case DOWN:
2015-06-16 02:44:59 +02:00
return EnumFacing.EAST;
case EAST:
2015-06-16 02:44:59 +02:00
return EnumFacing.UP;
case WEST:
2015-06-16 02:44:59 +02:00
return EnumFacing.DOWN;
default:
break;
}
break;
case SOUTH:
switch( axis )
{
case UP:
2015-06-16 02:44:59 +02:00
return EnumFacing.EAST;
case DOWN:
2015-06-16 02:44:59 +02:00
return EnumFacing.WEST;
case EAST:
2015-06-16 02:44:59 +02:00
return EnumFacing.DOWN;
case WEST:
2015-06-16 02:44:59 +02:00
return EnumFacing.UP;
default:
break;
}
break;
case EAST:
switch( axis )
{
case UP:
2015-06-16 02:44:59 +02:00
return EnumFacing.NORTH;
case DOWN:
2015-06-16 02:44:59 +02:00
return EnumFacing.SOUTH;
case NORTH:
2015-06-16 02:44:59 +02:00
return EnumFacing.UP;
case SOUTH:
2015-06-16 02:44:59 +02:00
return EnumFacing.DOWN;
default:
break;
}
case WEST:
switch( axis )
{
case UP:
2015-06-16 02:44:59 +02:00
return EnumFacing.SOUTH;
case DOWN:
2015-06-16 02:44:59 +02:00
return EnumFacing.NORTH;
case NORTH:
2015-06-16 02:44:59 +02:00
return EnumFacing.DOWN;
case SOUTH:
2015-06-16 02:44:59 +02:00
return EnumFacing.UP;
default:
break;
}
default:
break;
}
return forward;
}
@SideOnly( Side.CLIENT )
2015-09-30 14:24:40 +02:00
public static String gui_localize( final String string )
{
return StatCollector.translateToLocal( string );
}
2015-09-30 14:24:40 +02:00
public static boolean isSameItemPrecise( @Nullable final ItemStack is, @Nullable final ItemStack filter )
{
return isSameItem( is, filter ) && sameStackStags( is, filter );
}
2015-09-30 14:24:40 +02:00
public static boolean isSameItemFuzzy( final ItemStack a, final ItemStack b, final FuzzyMode mode )
{
if( a == null && b == null )
{
return true;
}
if( a == null )
{
return false;
}
if( b == null )
{
return false;
}
/*
2014-02-09 02:34:52 +01:00
* if ( a.itemID != 0 && b.itemID != 0 && a.isItemStackDamageable() && ! a.getHasSubtypes() && a.itemID ==
* b.itemID ) { return (a.getItemDamage() > 0) == (b.getItemDamage() > 0); }
*/
// test damageable items..
if( a.getItem() != null && b.getItem() != null && a.getItem().isDamageable() && a.getItem() == b.getItem() )
{
try
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
2015-09-30 14:24:40 +02:00
final Item ai = a.getItem();
final Item bi = b.getItem();
2015-06-16 02:44:59 +02:00
return ( ai.getDurabilityForDisplay(a) > 1 ) == ( bi.getDurabilityForDisplay(b) > 1 );
}
else
{
2015-09-30 14:24:40 +02:00
final Item ai = a.getItem();
final Item bi = b.getItem();
2015-06-16 02:44:59 +02:00
2015-09-30 14:24:40 +02:00
final float percentDamagedOfA = 1.0f - (float) ai.getDurabilityForDisplay(a);
final float percentDamagedOfB = 1.0f - (float) bi.getDurabilityForDisplay(b);
return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint );
}
}
2015-09-30 14:24:40 +02:00
catch( final Throwable e )
{
if( mode == FuzzyMode.IGNORE_ALL )
{
return true;
}
else if( mode == FuzzyMode.PERCENT_99 )
{
return ( a.getItemDamage() > 1 ) == ( b.getItemDamage() > 1 );
}
else
{
2015-09-30 14:24:40 +02:00
final float percentDamagedOfA = (float) a.getItemDamage() / (float) a.getMaxDamage();
final float percentDamagedOfB = (float) b.getItemDamage() / (float) b.getMaxDamage();
return ( percentDamagedOfA > mode.breakPoint ) == ( percentDamagedOfB > mode.breakPoint );
}
}
}
2015-09-30 14:24:40 +02:00
final OreReference aOR = OreHelper.INSTANCE.isOre( a );
final OreReference bOR = OreHelper.INSTANCE.isOre( b );
if( OreHelper.INSTANCE.sameOre( aOR, bOR ) )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
/*
2014-02-09 02:34:52 +01:00
* // test ore dictionary.. int OreID = getOreID( a ); if ( OreID != -1 ) return OreID == getOreID( b );
2015-02-03 12:04:13 +01:00
*
2014-02-09 02:34:52 +01:00
* if ( Mode != FuzzyMode.IGNORE_ALL ) { if ( a.hasTagCompound() && !isShared( a.getTagCompound() ) ) { a =
* Platform.getSharedItemStack( AEItemStack.create( a ) ); }
2015-02-03 12:04:13 +01:00
*
2014-02-09 02:34:52 +01:00
* if ( b.hasTagCompound() && !isShared( b.getTagCompound() ) ) { b = Platform.getSharedItemStack(
* AEItemStack.create( b ) ); }
2015-02-03 12:04:13 +01:00
*
2014-02-09 02:34:52 +01:00
* // test regular items with damage values and what not... if ( isShared( a.getTagCompound() ) && isShared(
* b.getTagCompound() ) && a.itemID == b.itemID ) { return ((AppEngSharedNBTTagCompound)
* a.getTagCompound()).compareFuzzyWithRegistry( (AppEngSharedNBTTagCompound) b.getTagCompound() ); } }
*/
return a.isItemEqual( b );
}
2015-09-30 14:24:40 +02:00
public static LookDirection getPlayerRay( final EntityPlayer playerIn, final float eyeOffset )
{
2015-06-16 02:44:59 +02:00
double reachDistance = 5.0d;
2015-06-16 02:44:59 +02:00
final double x = playerIn.prevPosX + ( playerIn.posX - playerIn.prevPosX );
final double y = playerIn.prevPosY + ( playerIn.posY - playerIn.prevPosY ) + playerIn.getEyeHeight();
final double z = playerIn.prevPosZ + ( playerIn.posZ - playerIn.prevPosZ );
2015-06-16 02:44:59 +02:00
final float playerPitch = playerIn.prevRotationPitch + ( playerIn.rotationPitch - playerIn.prevRotationPitch );
final float playerYaw = playerIn.prevRotationYaw + ( playerIn.rotationYaw - playerIn.prevRotationYaw );
final float yawRayX = MathHelper.sin( -playerYaw * 0.017453292f - ( float ) Math.PI );
final float yawRayZ = MathHelper.cos( -playerYaw * 0.017453292f - ( float ) Math.PI );
final float pitchMultiplier = -MathHelper.cos( -playerPitch * 0.017453292F );
final float eyeRayY = MathHelper.sin( -playerPitch * 0.017453292F );
final float eyeRayX = yawRayX * pitchMultiplier;
final float eyeRayZ = yawRayZ * pitchMultiplier;
if ( playerIn instanceof EntityPlayerMP )
{
2015-06-16 02:44:59 +02:00
reachDistance = ( ( EntityPlayerMP ) playerIn ).theItemInWorldManager.getBlockReachDistance();
}
2015-06-16 02:44:59 +02:00
final Vec3 from = new Vec3( x, y, z );
final Vec3 to = from.addVector( eyeRayX * reachDistance, eyeRayY * reachDistance, eyeRayZ * reachDistance );
return new LookDirection( from, to );
}
2015-09-30 14:24:40 +02:00
public static MovingObjectPosition rayTrace( final EntityPlayer p, final boolean hitBlocks, final boolean hitEntities )
2014-01-20 17:41:37 +01:00
{
2015-09-30 14:24:40 +02:00
final World w = p.getEntityWorld();
2014-01-20 17:41:37 +01:00
2015-09-30 14:24:40 +02:00
final float f = 1.0F;
float f1 = p.prevRotationPitch + ( p.rotationPitch - p.prevRotationPitch ) * f;
2015-09-30 14:24:40 +02:00
final float f2 = p.prevRotationYaw + ( p.rotationYaw - p.prevRotationYaw ) * f;
final double d0 = p.prevPosX + ( p.posX - p.prevPosX ) * f;
final double d1 = p.prevPosY + ( p.posY - p.prevPosY ) * f + 1.62D - p.getYOffset();
final double d2 = p.prevPosZ + ( p.posZ - p.prevPosZ ) * f;
final Vec3 vec3 = new Vec3( d0, d1, d2 );
final float f3 = MathHelper.cos( -f2 * 0.017453292F - (float) Math.PI );
final float f4 = MathHelper.sin( -f2 * 0.017453292F - (float) Math.PI );
final float f5 = -MathHelper.cos( -f1 * 0.017453292F );
final float f6 = MathHelper.sin( -f1 * 0.017453292F );
final float f7 = f4 * f5;
final float f8 = f3 * f5;
final double d3 = 32.0D;
final Vec3 vec31 = vec3.addVector( f7 * d3, f6 * d3, f8 * d3 );
final AxisAlignedBB bb = AxisAlignedBB.fromBounds( Math.min( vec3.xCoord, vec31.xCoord ), Math.min( vec3.yCoord, vec31.yCoord ), Math.min( vec3.zCoord, vec31.zCoord ), Math.max( vec3.xCoord, vec31.xCoord ), Math.max( vec3.yCoord, vec31.yCoord ), Math.max( vec3.zCoord, vec31.zCoord ) ).expand( 16, 16, 16 );
2014-01-20 17:41:37 +01:00
Entity entity = null;
2014-09-21 01:46:15 +02:00
double closest = 9999999.0D;
if( hitEntities )
2014-01-20 17:41:37 +01:00
{
2015-09-30 14:24:40 +02:00
final List list = w.getEntitiesWithinAABBExcludingEntity( p, bb );
2014-01-20 17:41:37 +01:00
2015-09-30 14:22:21 +02:00
for( int l = 0; l < list.size(); ++l )
2014-01-20 17:41:37 +01:00
{
2015-09-30 14:24:40 +02:00
final Entity entity1 = (Entity) list.get( l );
2014-01-20 17:41:37 +01:00
if( !entity1.isDead && entity1 != p && !( entity1 instanceof EntityItem ) )
2014-01-20 17:41:37 +01:00
{
if( entity1.isEntityAlive() )
2014-01-20 17:41:37 +01:00
{
// prevent killing / flying of mounts.
if( entity1.riddenByEntity == p )
2015-04-29 02:30:53 +02:00
{
2014-01-20 17:41:37 +01:00
continue;
2015-04-29 02:30:53 +02:00
}
2014-01-20 17:41:37 +01:00
f1 = 0.3F;
2015-09-30 14:24:40 +02:00
final AxisAlignedBB boundingBox = entity1.getEntityBoundingBox().expand( f1, f1, f1 );
final MovingObjectPosition movingObjectPosition = boundingBox.calculateIntercept( vec3, vec31 );
2014-01-20 17:41:37 +01:00
if( movingObjectPosition != null )
2014-01-20 17:41:37 +01:00
{
2015-09-30 14:24:40 +02:00
final double nd = vec3.squareDistanceTo( movingObjectPosition.hitVec );
2014-01-20 17:41:37 +01:00
if( nd < closest )
2014-01-20 17:41:37 +01:00
{
entity = entity1;
2014-09-21 01:46:15 +02:00
closest = nd;
2014-01-20 17:41:37 +01:00
}
}
}
}
}
}
MovingObjectPosition pos = null;
Vec3 vec = null;
2014-01-20 17:41:37 +01:00
if( hitBlocks )
2014-01-20 17:41:37 +01:00
{
2015-06-16 02:44:59 +02:00
vec = new Vec3( d0, d1, d2 );
2014-02-09 02:34:52 +01:00
pos = w.rayTraceBlocks( vec3, vec31, true );
2014-01-20 17:41:37 +01:00
}
if( entity != null && pos != null && pos.hitVec.squareDistanceTo( vec ) > closest )
2014-01-20 17:41:37 +01:00
{
pos = new MovingObjectPosition( entity );
}
else if( entity != null && pos == null )
2014-01-20 17:41:37 +01:00
{
pos = new MovingObjectPosition( entity );
}
return pos;
}
public static long nanoTime()
{
2015-01-01 22:13:10 +01:00
// if ( Configuration.INSTANCE.enableNetworkProfiler )
2014-01-20 17:41:37 +01:00
// return System.nanoTime();
return 0;
}
2015-09-30 14:24:40 +02:00
public static <StackType extends IAEStack> StackType poweredExtraction( final IEnergySource energy, final IMEInventory<StackType> cell, final StackType request, final BaseActionSource src )
{
2015-09-30 14:24:40 +02:00
final StackType possible = cell.extractItems( (StackType) request.copy(), Actionable.SIMULATE, src );
long retrieved = 0;
if( possible != null )
2015-04-29 02:30:53 +02:00
{
retrieved = possible.getStackSize();
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final double availablePower = energy.extractAEPower( retrieved, Actionable.SIMULATE, PowerMultiplier.CONFIG );
2015-09-30 14:24:40 +02:00
final long itemToExtract = Math.min( (long) ( availablePower + 0.9 ), retrieved );
if( itemToExtract > 0 )
{
energy.extractAEPower( retrieved, Actionable.MODULATE, PowerMultiplier.CONFIG );
possible.setStackSize( itemToExtract );
2015-09-30 14:24:40 +02:00
final StackType ret = cell.extractItems( possible, Actionable.MODULATE, src );
2014-01-05 09:43:49 +01:00
if( ret != null && src.isPlayer() )
{
Stats.ItemsExtracted.addToPlayer( ( (PlayerSource) src ).player, (int) ret.getStackSize() );
}
2014-01-05 09:43:49 +01:00
return ret;
}
return null;
}
2015-09-30 14:24:40 +02:00
public static <StackType extends IAEStack> StackType poweredInsert( final IEnergySource energy, final IMEInventory<StackType> cell, final StackType input, final BaseActionSource src )
{
2015-09-30 14:24:40 +02:00
final StackType possible = cell.injectItems( (StackType) input.copy(), Actionable.SIMULATE, src );
long stored = input.getStackSize();
if( possible != null )
2015-04-29 02:30:53 +02:00
{
stored -= possible.getStackSize();
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final double availablePower = energy.extractAEPower( stored, Actionable.SIMULATE, PowerMultiplier.CONFIG );
2015-09-30 14:24:40 +02:00
final long itemToAdd = Math.min( (long) ( availablePower + 0.9 ), stored );
if( itemToAdd > 0 )
{
energy.extractAEPower( stored, Actionable.MODULATE, PowerMultiplier.CONFIG );
if( itemToAdd < input.getStackSize() )
{
2015-09-30 14:24:40 +02:00
final long original = input.getStackSize();
final StackType split = (StackType) input.copy();
split.decStackSize( itemToAdd );
input.setStackSize( itemToAdd );
2014-01-20 17:41:37 +01:00
split.add( cell.injectItems( input, Actionable.MODULATE, src ) );
if( src.isPlayer() )
{
2015-09-30 14:24:40 +02:00
final long diff = original - split.getStackSize();
Stats.ItemsInserted.addToPlayer( ( (PlayerSource) src ).player, (int) diff );
}
return split;
}
2014-01-05 09:43:49 +01:00
2015-09-30 14:24:40 +02:00
final StackType ret = cell.injectItems( input, Actionable.MODULATE, src );
2014-01-05 09:43:49 +01:00
if( src.isPlayer() )
{
2015-09-30 14:24:40 +02:00
final long diff = ret == null ? input.getStackSize() : input.getStackSize() - ret.getStackSize();
Stats.ItemsInserted.addToPlayer( ( (PlayerSource) src ).player, (int) diff );
}
2014-01-05 09:43:49 +01:00
return ret;
}
return input;
}
2015-09-30 14:24:40 +02:00
public static void postChanges( final IStorageGrid gs, final ItemStack removed, final ItemStack added, final BaseActionSource src )
{
2015-09-30 14:24:40 +02:00
final IItemList<IAEItemStack> itemChanges = AEApi.instance().storage().createItemList();
final IItemList<IAEFluidStack> fluidChanges = AEApi.instance().storage().createFluidList();
if( removed != null )
{
2015-09-30 14:24:40 +02:00
final IMEInventory<IAEItemStack> myItems = AEApi.instance().registries().cell().getCellInventory( removed, null, StorageChannel.ITEMS );
if( myItems != null )
{
2015-09-30 14:24:40 +02:00
for( final IAEItemStack is : myItems.getAvailableItems( itemChanges ) )
2015-04-29 02:30:53 +02:00
{
is.setStackSize( -is.getStackSize() );
2015-04-29 02:30:53 +02:00
}
}
2015-09-30 14:24:40 +02:00
final IMEInventory<IAEFluidStack> myFluids = AEApi.instance().registries().cell().getCellInventory( removed, null, StorageChannel.FLUIDS );
if( myFluids != null )
{
2015-09-30 14:24:40 +02:00
for( final IAEFluidStack is : myFluids.getAvailableItems( fluidChanges ) )
2015-04-29 02:30:53 +02:00
{
is.setStackSize( -is.getStackSize() );
2015-04-29 02:30:53 +02:00
}
}
}
if( added != null )
{
2015-09-30 14:24:40 +02:00
final IMEInventory<IAEItemStack> myItems = AEApi.instance().registries().cell().getCellInventory( added, null, StorageChannel.ITEMS );
if( myItems != null )
2015-04-29 02:30:53 +02:00
{
myItems.getAvailableItems( itemChanges );
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final IMEInventory<IAEFluidStack> myFluids = AEApi.instance().registries().cell().getCellInventory( added, null, StorageChannel.FLUIDS );
if( myFluids != null )
2015-04-29 02:30:53 +02:00
{
myFluids.getAvailableItems( fluidChanges );
2015-04-29 02:30:53 +02:00
}
}
gs.postAlterationOfStoredItems( StorageChannel.ITEMS, itemChanges, src );
}
2015-09-30 14:24:40 +02:00
public static <T extends IAEStack<T>> void postListChanges( final IItemList<T> before, final IItemList<T> after, final IMEMonitorHandlerReceiver<T> meMonitorPassthrough, final BaseActionSource source )
{
2015-09-30 14:24:40 +02:00
final LinkedList<T> changes = new LinkedList<T>();
2015-09-30 14:24:40 +02:00
for( final T is : before )
2015-04-29 02:30:53 +02:00
{
is.setStackSize( -is.getStackSize() );
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
for( final T is : after )
2015-04-29 02:30:53 +02:00
{
before.add( is );
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
for( final T is : before )
{
if( is.getStackSize() != 0 )
{
changes.add( is );
}
}
if( !changes.isEmpty() )
2015-04-29 02:30:53 +02:00
{
meMonitorPassthrough.postChange( null, changes, source );
2015-04-29 02:30:53 +02:00
}
}
2015-09-30 14:24:40 +02:00
public static int generateTileHash( final TileEntity target )
2013-12-28 22:05:58 +01:00
{
if( target == null )
2015-04-29 02:30:53 +02:00
{
2013-12-28 22:05:58 +01:00
return 0;
2015-04-29 02:30:53 +02:00
}
2013-12-28 22:05:58 +01:00
int hash = target.hashCode();
if( target instanceof ITileStorageMonitorable )
2015-04-29 02:30:53 +02:00
{
2014-01-03 19:25:29 +01:00
return 0;
2015-04-29 02:30:53 +02:00
}
else if( target instanceof TileEntityChest )
{
2015-09-30 14:24:40 +02:00
final TileEntityChest chest = (TileEntityChest) target;
chest.checkForAdjacentChests();
if( chest.adjacentChestZNeg != null )
2015-04-29 02:30:53 +02:00
{
hash ^= chest.adjacentChestZNeg.hashCode();
2015-04-29 02:30:53 +02:00
}
else if( chest.adjacentChestZPos != null )
2015-04-29 02:30:53 +02:00
{
hash ^= chest.adjacentChestZPos.hashCode();
2015-04-29 02:30:53 +02:00
}
else if( chest.adjacentChestXPos != null )
2015-04-29 02:30:53 +02:00
{
hash ^= chest.adjacentChestXPos.hashCode();
2015-04-29 02:30:53 +02:00
}
else if( chest.adjacentChestXNeg != null )
2015-04-29 02:30:53 +02:00
{
hash ^= chest.adjacentChestXNeg.hashCode();
2015-04-29 02:30:53 +02:00
}
}
else if( target instanceof IInventory )
{
hash ^= ( (IInventory) target ).getSizeInventory();
2013-12-28 22:05:58 +01:00
if( target instanceof ISidedInventory )
2013-12-28 22:05:58 +01:00
{
2015-09-30 14:24:40 +02:00
for( final EnumFacing dir : EnumFacing.VALUES )
2013-12-28 22:05:58 +01:00
{
2015-09-30 14:24:40 +02:00
final int[] sides = ( (ISidedInventory) target ).getSlotsForFace( dir );
if( sides == null )
2015-04-29 02:30:53 +02:00
{
return 0;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:22:21 +02:00
int offset = 0;
2015-09-30 14:24:40 +02:00
for( final int side : sides )
{
2015-09-30 14:24:40 +02:00
final int c = ( side << ( offset % 8 ) ) ^ ( 1 << dir.ordinal() );
2015-03-26 11:07:26 +01:00
offset++;
hash = c + ( hash << 6 ) + ( hash << 16 ) - hash;
}
2013-12-28 22:05:58 +01:00
}
}
}
return hash;
}
2015-09-30 14:24:40 +02:00
public static boolean securityCheck( final GridNode a, final GridNode b )
{
if( a.getLastSecurityKey() == -1 && b.getLastSecurityKey() == -1 )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
else if( a.getLastSecurityKey() == b.getLastSecurityKey() )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
final boolean a_isSecure = isPowered( a.getGrid() ) && a.getLastSecurityKey() != -1;
final boolean b_isSecure = isPowered( b.getGrid() ) && b.getLastSecurityKey() != -1;
if( AEConfig.instance.isFeatureEnabled( AEFeature.LogSecurityAudits ) )
2014-09-05 05:08:07 +02:00
{
AELog.info( "Audit: " + a_isSecure + " : " + b_isSecure + " @ " + a.getLastSecurityKey() + " vs " + b.getLastSecurityKey() + " & " + a.getPlayerID() + " vs " + b.getPlayerID() );
2014-09-05 05:08:07 +02:00
}
// can't do that son...
if( a_isSecure && b_isSecure )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
if( !a_isSecure && b_isSecure )
2015-04-29 02:30:53 +02:00
{
return checkPlayerPermissions( b.getGrid(), a.getPlayerID() );
2015-04-29 02:30:53 +02:00
}
if( a_isSecure && !b_isSecure )
2015-04-29 02:30:53 +02:00
{
return checkPlayerPermissions( a.getGrid(), b.getPlayerID() );
2015-04-29 02:30:53 +02:00
}
return false;
}
2015-09-30 14:24:40 +02:00
private static boolean isPowered( final IGrid grid )
{
if( grid == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final IEnergyGrid eg = grid.getCache( IEnergyGrid.class );
return eg.isNetworkPowered();
}
2015-09-30 14:24:40 +02:00
private static boolean checkPlayerPermissions( final IGrid grid, final int playerID )
{
if( grid == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final ISecurityGrid gs = grid.getCache( ISecurityGrid.class );
if( gs == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
if( !gs.isAvailable() )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
return !gs.hasPermission( playerID, SecurityPermissions.BUILD );
}
2014-02-09 02:34:52 +01:00
2015-09-30 14:24:40 +02:00
public static void configurePlayer( final EntityPlayer player, final AEPartLocation side, final TileEntity tile )
{
2015-03-26 12:13:34 +01:00
float pitch = 0.0f;
float yaw = 0.0f;
2015-06-16 02:44:59 +02:00
// player.yOffset = 1.8f;
switch( side )
{
case DOWN:
pitch = 90.0f;
2015-06-16 02:44:59 +02:00
// player.getYOffset() = -1.8f;
break;
case EAST:
yaw = -90.0f;
break;
case NORTH:
yaw = 180.0f;
break;
case SOUTH:
yaw = 0.0f;
break;
2015-06-16 02:44:59 +02:00
case INTERNAL:
break;
case UP:
pitch = 90.0f;
break;
case WEST:
yaw = 90.0f;
break;
}
2015-06-16 02:44:59 +02:00
player.posX = tile.getPos().getX() + 0.5;
player.posY = tile.getPos().getY() + 0.5;
player.posZ = tile.getPos().getZ() + 0.5;
player.rotationPitch = player.prevCameraPitch = player.cameraPitch = pitch;
player.rotationYaw = player.prevCameraYaw = player.cameraYaw = yaw;
}
2015-09-30 14:24:40 +02:00
public static boolean canAccess( final AENetworkProxy gridProxy, final BaseActionSource src )
{
try
{
if( src.isPlayer() )
{
return gridProxy.getSecurity().hasPermission( ( (PlayerSource) src ).player, SecurityPermissions.BUILD );
}
else if( src.isMachine() )
{
2015-09-30 14:24:40 +02:00
final IActionHost te = ( (MachineSource) src ).via;
final IGridNode n = te.getActionableNode();
if( n == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final int playerID = n.getPlayerID();
return gridProxy.getSecurity().hasPermission( playerID, SecurityPermissions.BUILD );
}
else
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
}
2015-09-30 14:24:40 +02:00
catch( final GridAccessException gae )
{
return false;
}
}
2015-09-30 14:24:40 +02:00
public static ItemStack extractItemsByRecipe( final IEnergySource energySrc, final BaseActionSource mySrc, final IMEMonitor<IAEItemStack> src, final World w, final IRecipe r, final ItemStack output, final InventoryCrafting ci, final ItemStack providedTemplate, final int slot, final IItemList<IAEItemStack> items, final Actionable realForFake, final IPartitionList<IAEItemStack> filter )
{
if( energySrc.extractAEPower( 1, Actionable.SIMULATE, PowerMultiplier.CONFIG ) > 0.9 )
{
if( providedTemplate == null )
2015-04-29 02:30:53 +02:00
{
return null;
2015-04-29 02:30:53 +02:00
}
2015-09-30 14:24:40 +02:00
final AEItemStack ae_req = AEItemStack.create( providedTemplate );
ae_req.setStackSize( 1 );
if( filter == null || filter.isListed( ae_req ) )
{
2015-09-30 14:24:40 +02:00
final IAEItemStack ae_ext = src.extractItems( ae_req, realForFake, mySrc );
if( ae_ext != null )
{
2015-09-30 14:24:40 +02:00
final ItemStack extracted = ae_ext.getItemStack();
if( extracted != null )
{
energySrc.extractAEPower( 1, realForFake, PowerMultiplier.CONFIG );
return extracted;
}
}
}
2015-09-30 14:24:40 +02:00
final boolean checkFuzzy = ae_req.isOre() || providedTemplate.getItemDamage() == OreDictionary.WILDCARD_VALUE || providedTemplate.hasTagCompound() || providedTemplate.isItemStackDamageable();
if( items != null && checkFuzzy )
{
2015-09-30 14:24:40 +02:00
for( final IAEItemStack x : items )
{
2015-09-30 14:24:40 +02:00
final ItemStack sh = x.getItemStack();
if( ( Platform.isSameItemType( providedTemplate, sh ) || ae_req.sameOre( x ) ) && !Platform.isSameItem( sh, output ) )
{ // Platform.isSameItemType( sh, providedTemplate )
2015-09-30 14:24:40 +02:00
final ItemStack cp = Platform.cloneItemStack( sh );
cp.stackSize = 1;
ci.setInventorySlotContents( slot, cp );
if( r.matches( ci, w ) && Platform.isSameItem( r.getCraftingResult( ci ), output ) )
{
2015-09-30 14:24:40 +02:00
final IAEItemStack ax = x.copy();
ax.setStackSize( 1 );
if( filter == null || filter.isListed( ax ) )
{
2015-09-30 14:24:40 +02:00
final IAEItemStack ex = src.extractItems( ax, realForFake, mySrc );
if( ex != null )
{
energySrc.extractAEPower( 1, realForFake, PowerMultiplier.CONFIG );
return ex.getItemStack();
}
}
}
ci.setInventorySlotContents( slot, providedTemplate );
}
}
}
}
return null;
}
2015-09-30 14:24:40 +02:00
public static boolean isSameItemType( final ItemStack that, final ItemStack other )
{
2015-05-18 17:52:56 +02:00
if( that != null && other != null && that.getItem() == other.getItem() )
{
2015-05-18 17:52:56 +02:00
if( that.isItemStackDamageable() )
2015-04-29 02:30:53 +02:00
{
return true;
2015-04-29 02:30:53 +02:00
}
2015-05-18 17:52:56 +02:00
return that.getItemDamage() == other.getItemDamage();
}
return false;
}
2015-09-30 14:24:40 +02:00
public static boolean isSameItem( @Nullable final ItemStack left, @Nullable final ItemStack right )
{
return left != null && right != null && left.isItemEqual( right );
}
2015-09-30 14:24:40 +02:00
public static ItemStack cloneItemStack( final ItemStack a )
2014-06-22 09:00:38 +02:00
{
return a.copy();
}
2015-09-30 14:24:40 +02:00
public static ItemStack getContainerItem( final ItemStack stackInSlot )
{
if( stackInSlot == null )
2015-04-29 02:30:53 +02:00
{
2014-06-22 09:00:38 +02:00
return null;
2015-04-29 02:30:53 +02:00
}
2014-06-22 09:00:38 +02:00
2015-09-30 14:24:40 +02:00
final Item i = stackInSlot.getItem();
if( i == null || !i.hasContainerItem( stackInSlot ) )
2014-06-22 09:00:38 +02:00
{
if( stackInSlot.stackSize > 1 )
2014-06-22 09:00:38 +02:00
{
stackInSlot.stackSize--;
return stackInSlot;
}
return null;
}
ItemStack ci = i.getContainerItem( stackInSlot.copy() );
if( ci != null && ci.isItemStackDamageable() && ci.getItemDamage() == ci.getMaxDamage() )
2015-04-29 02:30:53 +02:00
{
2014-06-22 09:00:38 +02:00
ci = null;
2015-04-29 02:30:53 +02:00
}
2014-06-22 09:00:38 +02:00
return ci;
}
2015-09-30 14:24:40 +02:00
public static void notifyBlocksOfNeighbors( final World worldObj, final BlockPos pos )
{
if( !worldObj.isRemote )
2015-04-29 02:30:53 +02:00
{
TickHandler.INSTANCE.addCallable( worldObj, new BlockUpdate( pos ) );
2015-04-29 02:30:53 +02:00
}
2014-07-09 02:36:20 +02:00
}
2015-09-30 14:24:40 +02:00
public static boolean canRepair( final AEFeature type, final ItemStack a, final ItemStack b )
{
if( b == null || a == null )
2015-04-29 02:30:53 +02:00
{
return false;
2015-04-29 02:30:53 +02:00
}
if( type == AEFeature.CertusQuartzTools )
{
final IItemDefinition certusQuartzCrystal = AEApi.instance().definitions().materials().certusQuartzCrystal();
return certusQuartzCrystal.isSameAs( b );
}
if( type == AEFeature.NetherQuartzTools )
2015-04-29 02:30:53 +02:00
{
return Items.quartz == b.getItem();
2015-04-29 02:30:53 +02:00
}
return false;
}
2015-09-30 14:24:40 +02:00
public static Object findPreferred( final ItemStack[] is )
{
final IParts parts = AEApi.instance().definitions().parts();
2015-09-30 14:24:40 +02:00
for( final ItemStack stack : is )
{
if( parts.cableGlass().sameAs( AEColor.Transparent, stack ) )
{
return stack;
}
if( parts.cableCovered().sameAs( AEColor.Transparent, stack ) )
{
return stack;
}
if( parts.cableSmart().sameAs( AEColor.Transparent, stack ) )
{
return stack;
}
if( parts.cableDense().sameAs( AEColor.Transparent, stack ) )
{
return stack;
}
}
return is;
}
2014-08-07 08:47:42 +02:00
2015-09-30 14:24:40 +02:00
public static void sendChunk( final Chunk c, final int verticalBits )
2014-08-07 08:47:42 +02:00
{
try
{
2015-09-30 14:24:40 +02:00
final WorldServer ws = (WorldServer) c.getWorld();
final PlayerManager pm = ws.getPlayerManager();
2014-08-07 08:47:42 +02:00
if( getOrCreateChunkWatcher == null )
2014-08-07 08:47:42 +02:00
{
getOrCreateChunkWatcher = ReflectionHelper.findMethod( PlayerManager.class, pm, new String[] { "getOrCreateChunkWatcher", "func_72690_a" }, int.class, int.class, boolean.class );
2014-08-07 08:47:42 +02:00
}
if( getOrCreateChunkWatcher != null )
2014-08-07 08:47:42 +02:00
{
2015-09-30 14:24:40 +02:00
final Object playerInstance = getOrCreateChunkWatcher.invoke( pm, c.xPosition, c.zPosition, false );
if( playerInstance != null )
2014-08-07 08:47:42 +02:00
{
Platform.playerInstance = playerInstance.getClass();
2014-08-07 08:47:42 +02:00
if( sendToAllPlayersWatchingChunk == null )
2014-08-07 08:47:42 +02:00
{
sendToAllPlayersWatchingChunk = ReflectionHelper.findMethod( Platform.playerInstance, playerInstance, new String[] { "sendToAllPlayersWatchingChunk", "func_151251_a" }, Packet.class );
2014-08-07 08:47:42 +02:00
}
if( sendToAllPlayersWatchingChunk != null )
2015-04-29 02:30:53 +02:00
{
sendToAllPlayersWatchingChunk.invoke( playerInstance, new S21PacketChunkData( c, false, verticalBits ) );
2015-04-29 02:30:53 +02:00
}
2014-08-07 08:47:42 +02:00
}
}
}
2015-09-30 14:24:40 +02:00
catch( final Throwable t )
2014-08-07 08:47:42 +02:00
{
AELog.error( t );
}
}
2014-08-08 08:36:50 +02:00
2015-09-30 14:24:40 +02:00
public static AxisAlignedBB getPrimaryBox( final AEPartLocation side, final int facadeThickness )
2014-08-08 08:36:50 +02:00
{
switch( side )
2014-08-08 08:36:50 +02:00
{
case DOWN:
2015-06-16 02:44:59 +02:00
return AxisAlignedBB.fromBounds( 0.0, 0.0, 0.0, 1.0, ( facadeThickness ) / 16.0, 1.0 );
case EAST:
2015-06-16 02:44:59 +02:00
return AxisAlignedBB.fromBounds( ( 16.0 - facadeThickness ) / 16.0, 0.0, 0.0, 1.0, 1.0, 1.0 );
case NORTH:
2015-06-16 02:44:59 +02:00
return AxisAlignedBB.fromBounds( 0.0, 0.0, 0.0, 1.0, 1.0, ( facadeThickness ) / 16.0 );
case SOUTH:
2015-06-16 02:44:59 +02:00
return AxisAlignedBB.fromBounds( 0.0, 0.0, ( 16.0 - facadeThickness ) / 16.0, 1.0, 1.0, 1.0 );
case UP:
2015-06-16 02:44:59 +02:00
return AxisAlignedBB.fromBounds( 0.0, ( 16.0 - facadeThickness ) / 16.0, 0.0, 1.0, 1.0, 1.0 );
case WEST:
2015-06-16 02:44:59 +02:00
return AxisAlignedBB.fromBounds( 0.0, 0.0, 0.0, ( facadeThickness ) / 16.0, 1.0, 1.0 );
default:
break;
2014-08-08 08:36:50 +02:00
}
2015-06-16 02:44:59 +02:00
return AxisAlignedBB.fromBounds( 0, 0, 0, 1, 1, 1 );
2014-08-08 08:36:50 +02:00
}
2015-09-30 14:24:40 +02:00
public static float getEyeOffset( final EntityPlayer player )
{
assert player.worldObj.isRemote : "Valid only on client";
return (float) ( player.posY + player.getEyeHeight() - player.getDefaultEyeHeight() );
}
2014-09-14 07:02:02 +02:00
2015-09-30 14:24:40 +02:00
public static void addStat( final int playerID, final Achievement achievement )
2014-09-14 07:02:02 +02:00
{
2015-09-30 14:24:40 +02:00
final EntityPlayer p = AEApi.instance().registries().players().findPlayer( playerID );
if( p != null )
2014-09-14 07:02:02 +02:00
{
p.addStat( achievement, 1 );
2014-09-14 07:02:02 +02:00
}
}
2015-09-30 14:24:40 +02:00
public static boolean isRecipePrioritized( final ItemStack what )
{
final IMaterials materials = AEApi.instance().definitions().materials();
boolean isPurified = materials.purifiedCertusQuartzCrystal().isSameAs( what );
isPurified |= materials.purifiedFluixCrystal().isSameAs( what );
isPurified |= materials.purifiedNetherQuartzCrystal().isSameAs( what );
return isPurified;
}
}